QT QChart can't show,refresh doesn't work
-
I'm trying to use qbarset in qchart, but he can't display it correctly, the code is as follows:
CMakeLists.txtcmake_minimum_required(VERSION 3.26) project(VisualDataStructure) set(CMAKE_CXX_STANDARD 23) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) find_package(Qt6 COMPONENTS Core Gui Widgets Charts REQUIRED) INCLUDE_DIRECTORIES(Graphics) INCLUDE_DIRECTORIES(Structure) add_executable(VisualDataStructure main.cpp MainWindow.cpp MainWindow.h Sort.h ) target_link_libraries(VisualDataStructure Qt::Core Qt::Gui Qt::Widgets Qt::Charts )
main.cpp
#include "MainWindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow main_window; main_window.show(); return a.exec(); }
mainwindow.h
#ifndef _MAINWINDOW_H_ #define _MAINWINDOW_H_ #include <QMainWindow> namespace Ui{ class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT Ui::MainWindow *ui = nullptr; public: MainWindow(QWidget *prent = nullptr); ~MainWindow() = default; }; #endif // _MAINWINDOW_H_
mainwindow.cpp
#include <iostream> #include <thread> #include <algorithm> #include <QtCharts/QChart> #include <QtCharts/QBarSet> #include <QtCharts/QChartView> #include <QtCharts/QBarSeries> #include "MainWindow.h" #include "ui_MainWindow.h" #include "Sort.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow){ ui->setupUi(this); auto sort_action = new QAction("sort"); ui->menu_bar->addAction(sort_action); auto s = new Sort(); QObject::connect(sort_action,&QAction::triggered,[=]{ std::thread run(&Sort::begin,s); run.detach(); }); auto chart = new QChart(); auto series = new QBarSeries(); auto view = new QChartView(); QBarSet* barSet = new QBarSet(""); series->append(barSet); chart->addSeries(series); view->setChart(chart); setCentralWidget(view); QObject::connect(s, &Sort::UPUI, [=]() { std::cout << "upui" << std::endl; *barSet << 50 << 60 << 70 << 80 << 90; view->repaint(); chart->update(); }); }
sort.h:
#ifndef VISUALDATASTRUCTURE_SORT_H #define VISUALDATASTRUCTURE_SORT_H #include <vector> #include <random> #include <chrono> #include <thread> class Sort : public QObject { Q_OBJECT signals: void UPUI(); private: std::vector<int >vec; public: Sort() { GetRandomVector(100); } void begin() { std::sort(vec.begin(),vec.end(),[=](const int val1,const int val2){ emit UPUI(); std::this_thread::sleep_for(std::chrono::seconds(1)); if (val1 < val2) return true; else return false; }); } void GetRandomVector(size_t size) { vec.resize(10); std::default_random_engine rand_engine; for (auto &p : vec) { p = rand_engine() % 100; } } }; #endif //VISUALDATASTRUCTURE_SORT_H
The begin method in sort originally wanted to emit emit and refresh the UI every time it was compared, so that the sorting process could be visualized. But after my first attempt, I found that the ui was not refreshed, so I modified the code in connect, just as a test, but the display still cannot be refreshed
The result of the operation is as follows:"UPUI" is triggered correctly, but does not refresh the display of qbarset.
I found that the order of
series->append(barSet); chart->addSeries(series); view->setChart(chart);
seems to have some effect on the display, but I didn't find the specific problem.
Running multiple times, I have a very small probability that I will also get the following output information:
or
project information:
qt6 + gcc13
The demo is in the page https://godbolt.org/z/xbqhx71cv ,The last two problems are small probability events and cannot be reproduced stably. My problem is mainly focused on the first problem, that is, the display of the QBarSet cannot be refreshed. -
@printfne
My understanding is the same as I keep saying. When you add new points to a chart after it has been shown, it's not thatQChartView
doesn't update, it's that its current axes --- which were set up when the initial points were added before being added to the chart --- are out of range for the new point. In some shape or form, you need to rescale the axes horizontally and/or vertically so that they include the new point(s) within their range.Keep your horizontal & vertical axes visible at least while you develop. If you do not see a new point that you added, look to see whether it is outside the current horizontal/vertical ranges. That is what my code was doing and it displays the new points in real time without my having to write any extra "updating/repainting" calls.
-
@printfne
I suggest you look at my code at https://forum.qt.io/topic/145986/qchart-line-series-not-shown/3 and read through that thread where much the same about "not being to able to see updates" was asked. I have not needed anyrepaint()
s orupdate()
s. As per there, you do have to sort out the axes yourself, I suspect that might be your issue here? -
@JonB I think, I found a minimal demo:
auto chart = new QChart(); auto series = new QBarSeries(); auto view = new QChartView(); setCentralWidget(view); auto bar = new QBarSet(""); *bar << 1 << 2; series->append(bar); chart->addSeries(series); view->setChart(chart);
it's perfectly normal.But when I move
*bar << 1 << 2;
to any position afterchart->addSeries(series);
, the bars of the histogram are no longer displayed, like the screenshot of the main window given in the original question. -
I haven't used
QChart
that much,but I think you need to set the series after you add the points. Therefore you cant modify just the series when it has been drawn already.
[ok, judging from the example, you dont need to, but you need to set the axis to match your data]
You could search for "dynamic qchart series" or somethingEdit:
There is even a Qt Example
wth... this example has no code available in 6.5?!
There is a page in the example section but it seems that the code got removed?!The code is available in Qt5.15
-
@Pl45m4 @JonB
I modified the axis to followChart::handleTimeout
in examplehttps://code.qt.io/cgit/qt/qtcharts.git/tree/examples/charts/dynamicspline/chart.cpp?h=5.15
, but it seems to have no effect on the display of the histogram. Also I noticed that in the example the scroll is called after adding a point, but I only added the barset once at the beginning, I don't know if that would have an effect.
Here is the modified code:auto view = new QChartView(); auto chart = new QChart(); auto series = new QBarSeries(); auto bar = new QBarSet(""); setCentralWidget(view); view->setChart(chart); chart->addSeries(series); series->append(bar); QValueAxis *m_axisX = new QValueAxis(); QValueAxis *m_axisY = new QValueAxis(); chart->addAxis(m_axisX,Qt::AlignBottom); chart->addAxis(m_axisY,Qt::AlignLeft); *bar << 1 << 2 << 3; m_axisX->setTickCount(5); m_axisX->setRange(0, 100); m_axisY->setRange(0, 100); qreal x = chart->plotArea().width() / m_axisX->tickCount(); qreal y = (m_axisX->max() - m_axisX->min()) / m_axisX->tickCount(); chart->scroll(x, 0);
This is the effect after running:
It is worth mentioning that I need to frequently modify the content displayed by the bar later, so in this demo I write the output of the bar later. -
@JonB Oh! I saw the form, but it's so weird, first of all, the code in form
series->append(bar);chart->addSeries(series);*bar << 1 << 2 << 3;*bar << 20 << 5 << 30;
doesn't work properly, but the form*bar << 1 << 2 << 3; series->append(bar); chart->addSeries(series); *bar << 20 << 5 << 30;
does, I think it's weird. Secondly, the display of this chart looks so strange, I found that the displayed content is related tom_axisX->setTickCount(1);
andqreal x = chart->plotArea().width() / m_axisX->tickCount();chart->scroll(x, 0);
, but what confuses me is that it seems that I should not manually assign a value tochart->scroll(x, 0)
, Because I can't seem to calculate how much I should scroll.
The complete code is as follows:auto view = new QChartView(); auto chart = new QChart(); auto series = new QBarSeries(); auto bar = new QBarSet(""); setCentralWidget(view); view->setChart(chart); QValueAxis *m_axisX = new QValueAxis(); QValueAxis *m_axisY = new QValueAxis(); chart->addAxis(m_axisX,Qt::AlignBottom); chart->addAxis(m_axisY,Qt::AlignLeft); *bar << 1 << 2 << 3; series->append(bar); chart->addSeries(series); *bar << 20 << 5 << 30; m_axisX->setTickCount(1); m_axisX->setRange(-500, 1000); m_axisY->setRange(0, 10000); qreal x = chart->plotArea().width() / m_axisX->tickCount(); chart->scroll(x, 0);
The running effect is as follows:
-
@printfne
My code does not use any of tick counts, plat area sizes or scrolling. So that is specific to the example you copied from. If you stick with what you have you will have to play with the values if you want all 4 bars to have the same visible width as each other. -
@JonB That is to say, I have to manually specify the range of
chart->scroll
?Also I have another question, in the above code, I used the code
*bar << 1 << 2 << 3;series->append(bar);chart->addSeries(series);*bar< < 20 << 5 << 30;
, he can work normally, let’s call it code A, and use the codeseries->append(bar);chart->addSeries(series);*bar << 1 << 2 << 3;*bar << 20 << 5 << 30;
, it cannot be displayed normally, let’s call it code B for now. Here code A can run normally, that is to say, afterseries-append
andchart->addSeries
The code*bar << num1 << num2
can be displayed, but in code B, this is not displayed, what is the reason What caused it? -
@printfne
My understanding is the same as I keep saying. When you add new points to a chart after it has been shown, it's not thatQChartView
doesn't update, it's that its current axes --- which were set up when the initial points were added before being added to the chart --- are out of range for the new point. In some shape or form, you need to rescale the axes horizontally and/or vertically so that they include the new point(s) within their range.Keep your horizontal & vertical axes visible at least while you develop. If you do not see a new point that you added, look to see whether it is outside the current horizontal/vertical ranges. That is what my code was doing and it displays the new points in real time without my having to write any extra "updating/repainting" calls.
-
-
-