Как установить соотношение сторон QChart
Я пытаюсь реализовать алгоритм для поддержания соотношения сторон QChart. Это вроде как работает, но мне было интересно, есть ли у кого-нибудь более простое решение.
ниже приведен код, который возникает при изменении размера
void TrainChartView::maintainAspectRatio(QSizeF eventSize) {
int aspect = 8;
QSizeF chartSize = m_chart->size();
QValueAxis* axisX = qobject_cast<QValueAxis*>(m_chart->axisX());
QValueAxis* axisY = qobject_cast<QValueAxis*>(m_chart->axisY());
// get Min Max X-axis Value
double minAxisX = axisX->min();
double maxAxisX = axisX->max();
double minAxisY = axisY->min();
double maxAxisY = axisY->max();
// Get Coordinates in scene of min and max X-axis value
QPointF minAxisXPosition = m_chart->mapToPosition(QPointF(minAxisX, 0));
QPointF maxAxisXPosition = m_chart->mapToPosition(QPointF(maxAxisX, 0));
QPointF minAxisYPosition = m_chart->mapToPosition(QPointF(0, minAxisY));
QPointF maxAxisYPosition = m_chart->mapToPosition(QPointF(0, maxAxisY));
double axisXSize = abs(maxAxisXPosition.x() - minAxisXPosition.x());
double axisYSize = abs(maxAxisXPosition.y() - minAxisYPosition.y());
// get the size of axis x in the coordinate system
double deltaAxisXSize = maxAxisXPosition.x() - minAxisXPosition.x();
if (chartSize.width() != eventSize.width()) {
QPointF maxAxisValue = m_chart->mapToValue(QPointF(0, (minAxisYPosition.y() - deltaAxisXSize)));
axisY->setRange(minAxisY, maxAxisValue.y() / aspect);
}
if (chartSize.height() != eventSize.height() && m_chart->minimumSize().height() >= eventSize.height()) {
double deltaHeight = eventSize.height() - chartSize.height();
maxAxisYPosition.setY(maxAxisYPosition.y() - deltaHeight);
QPointF maxAxisValue = m_chart->mapToValue(QPointF(maxAxisYPosition));
axisY->setRange(minAxisY, maxAxisValue.y());
}
1 ответ
Я немного изменил фрагмент кода, который вы сделали, и вот что у меня получилось:
в.h
//! \brief The QChartView_scaledAxis class extends the QChartView class but force the graph to be normalized
//! (i.e.) 1 pixel on the x-axis represent the same amount as 1 pixel on the y-axis.
class QChartView_scaledAxis : public QChartView {
public:
void resizeEvent(QResizeEvent *event) override;
};
в.cpp
void QChartView_scaledAxis::resizeEvent(QResizeEvent *event) {
QChartView::resizeEvent(event);
// Get the axis of the graph
QValueAxis* axisX = qobject_cast<QValueAxis*>(this->chart()->axes(Qt::Horizontal)[0]);
QValueAxis* axisY = qobject_cast<QValueAxis*>(this->chart()->axes(Qt::Vertical)[0]);
// Get the series displayed on the graph
const QList<QAbstractSeries*> series = this->chart()->series();
// get Min Max values (on X and Y) of all the points plotted on the graph
float minX = std::numeric_limits<double>::max();
float maxX = std::numeric_limits<double>::min();
float minY = std::numeric_limits<double>::max();
float maxY = std::numeric_limits<double>::min();
for(QAbstractSeries *p_serie : series) { //iterate on all the series in the graph
//Assuming all the series in the graph are QXYSeries...
for(QPointF p : qobject_cast<QXYSeries*>(p_serie)->points()) { //iterate on each point of each serie
minX = fmin(minX, p.x());
maxX = fmax(maxX, p.x());
minY = fmin(minY, p.y());
maxY = fmax(maxY, p.y());
}
}
// Get the points at both ends of the axis (will help to determine the plottable area in pixel)
const QPointF minPosition = this->chart()->mapToPosition(QPointF(axisX->min(), axisY->min()));
const QPointF maxPosition = this->chart()->mapToPosition(QPointF(axisX->max(), axisY->max()));
// Ration between the size of the axis in pixel and in term of represented value
const double axisX_PixToValue = (maxX - minX) / (maxPosition.x() - minPosition.x());
const double axisY_PixToValue = (maxY - minY) / (maxPosition.y() - minPosition.y());
// The smallest ratio must be 'kept' and applied to the other axis
if(abs(axisX_PixToValue) > abs(axisY_PixToValue)) {
axisY->setMin(minY);
axisY->setMax(minY + (maxPosition.y() - minPosition.y()) * std::copysign(axisX_PixToValue, axisY_PixToValue));
} else {
axisX->setMin(minX);
axisX->setMax(minX + (maxPosition.x() - minPosition.x()) * std::copysign(axisY_PixToValue, axisX_PixToValue));
}
}
Этот код рассчитан на соотношение 1:1, но я уверен, что его можно легко изменить для любого другого соотношения...