Одна річ, яка іноді виникає в підтримці , полягає в тому, що коли у вас є кілька видів діаграм, було б добре вирівняти їх один щодо одного таким чином, щоб фактичний розмір графіка був однаковим для обох діаграм. Якщо у вас однакові розміри осей то цього легко досягти, тому що вони займуть однакову ширину і, відповідно, вирівняються. Однак якщо це не так, що часто буває, тоді ми можемо використовувати поля, щоб змусити його прийняти бажані розміри.
Отже, давайте уявимо, що наш графік зараз виглядає так:
Якщо ви використовуєте C++ для коду своєї діаграми, цього можна досягти за допомогою одного слота, який можна підключити до сигналу
QChart::plotAreaChanged()
.
Для початку нам потрібно запобігти рекурсії, тому що ми мінятимемо поля, але якщо ми хочемо, щоб внутрішні пристрої продовжували робити свою справу, ми не блокуватимемо сигнали. Для цього ми матимемо статичне логічне значення, для якого ми встановимо значення
true
, щоб вказати, що ми знаходимося в середині наших обчислень:
void updatePlotArea(const QRectF &area) { static bool fixing = false; if (fixing) return; fixing = true;
Наступне, що потрібно зробити: визначити, який графік краще використовувати для вирівнювання інших. Це означає, що потрібно вибрати той, який має найбільше ліве значення для графіка (тобто той, який має найширшу вісь). На даний момент ми використовуємо «змінену» як відправну точку, і, якщо такі є насправді, ми змінюємо поля для них, оскільки це забезпечить найбільший розмір, доступний для області графіка в будь-якій точці для найбільшої осі.
QChart *bestChart = (QChart *)sender(); QRectF bestRect = area; foreach(QChart *chart, charts) { if (chart->plotArea().left() > bestRect.left()) { bestChart = chart; bestRect = chart->plotArea(); chart->setMargins(QMargins(20, 0, 20, 0)); } }
Потім, за винятком того, що виявляється «кращим» (bestChart), ми коригуємо поля, щоб переконатися, що вони збігаються з «кращим» і правильно вирівнялися, встановивши поля як існуюче поле плюс різницю між областю «кращого» графіка та поточного. Зрештою, ми надсилаємо будь-які опубліковані події, щоб вони одразу ж оновлювалися для нас.
foreach(QChart *chart, charts) { if (bestChart != chart) { const int left = chart->margins().left() + (bestRect.left() - chart->plotArea().left()); const int right = chart->margins().right() + (chart->plotArea().right() - bestRect.right()); chart->setMargins(QMargins(left, 0, right, 0)); } } QApplication::sendPostedEvents(); fixing = false;
Це дасть нам два вирівняні графіки, які виглядають наступним чином:
Що стосується QML, ми можемо зробити щось подібне через функцію, яка викликається за допомогою onPlotAreaChanged .
property bool fixing: false property var chartViews: [chartview, chartview_b] function updatePlotArea(chart, area) { if (fixing) return fixing = true var tmpChart var bestRect = chart.plotArea var bestChart = chart for (var i = 0; i Math.ceil(bestRect.left) || (Math.ceil(tmpChart.plotArea.left) === Math.ceil(bestRect.left) && Math.floor(tmpChart.plotArea.right) < Math.floor(bestRect.right))) { bestChart = tmpChart; bestRect = tmpChart.plotArea; } } bestRect.left = Math.ceil(bestRect.left) bestRect.right = Math.floor(bestRect.right) for (i = 0; i < chartViews.length; i++) { tmpChart = chartViews[i] if (tmpChart !== bestChart) { var newLeft = 20 + bestRect.left - Math.floor(tmpChart.plotArea.left); var newRight = 20 + Math.ceil(tmpChart.plotArea.right) - bestRect.right; tmpChart.margins.left = newLeft tmpChart.margins.right = newRight } } fixing = false; }
Єдина відмінність полягає в тому, що ми враховуємо той факт, що область графіка використовує реальні значення, а поля, як і раніше, ґрунтуються на цілих числах, тому в результаті ми робимо деякі додаткові облікові дані.