No update of my QGraphicsPixmapItem
-
Re: No update of my QGraphicsPixmapItem
ademmler, is your problem also linked to the size of the pixmap ?
Because I am thinking of an extraction of the part of the pixmap which is supposed to be seen in the view. That way I will have a littler pixmap (in size) and put it in the scene. That might solve my problem ... -
Nohing to do, I have tried an update in QGraphicsView, an update in QGraphicsScene and a QCoreApplication::processEvents() my QGraphicsPixmapItem is not drawn ...
I feel a little despair ... -
@Wotan I have the same issue - and I am also only qt beginner and user.
I have also filed a bug in https://bugreports.qt.io
Pls - does somebody of the pros look at this.
-
Can you pass the address of the bug ?
-
-
@ademmler you had an answer on the report which is pretty clear: you are blocking the event loop so no update will occur except if you call processEvent. Therefore fix your code to not block the event loop.
-
@SGaist Are you talking about the bug report I made.
The solution described there I have got right now. I will test this.
https://bugreports.qt.io/browse/QTBUG-86086 -
Hi SGaist,
I am still trying to solve the issue with my measurement loop and painting to graphics scene.
But I get a "signal/slot" connect error. I can't see why it should not work.QObject::connect: No such signal MainWindow::&MainWindow::signalPaintColor(int i) in mainwindow.cpp:52
QObject::connect: (sender name: 'MainWindow')
QObject::connect: (receiver name: 'MainWindow')This is my modified minimal code example:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QGraphicsScene> #include <QGraphicsPixmapItem> #include <QThread> #include <QDebug> //QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } //QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); signals: void signalPaintColor(int i); private slots: void on_startButton_released(); void slotPaintColor(int i); private: Ui::MainWindow *ui; QGraphicsScene *scene; QGraphicsPixmapItem pixmap; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" using namespace std; struct rgb { int R; int G; int B; char cn [10]; } colors[5]; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); scene = new QGraphicsScene(this); ui->graphicsView->setScene(scene); scene->addItem(&pixmap); colors[0] = { 255, 255, 255, "white" }; colors[1] = { 255, 0, 0, "red" }; colors[2] = { 0, 255, 0, "green" }; colors[3] = { 0, 0, 255, "blue" }; colors[4] = { 0, 0, 0, "black" }; } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotPaintColor(int i){ QPixmap pix(ui->graphicsView->size()); pix.fill(QColor(colors[i].R, colors[i].G, colors[i].B)); pixmap.setPixmap(pix); ui->statusbar->showMessage("Color: " + QString(colors[i].cn), 0); QApplication::processEvents(); } void MainWindow::on_startButton_released() { ui->statusbar->showMessage("Start loop ...", 0); connect(this, SIGNAL(signalPaintColor(int i)), this, SLOT(slotPaintColor(int i))); for( int i = 0; i < 5; i++ ) { emit signalPaintColor(i); } }
-
@ademmler said in No update of my QGraphicsPixmapItem:
QObject::connect: No such signal MainWindow::&MainWindow::signalPaintColor(int i) in mainwindow.cpp:52
If you insist on using old-style signal/slot syntax, this is telling you you have got it wrong. Where did you get/copy
connect(this, SIGNAL(signalPaintColor(int i)), this, SLOT(slotPaintColor(int i)));
from? Please copy examples, should be:connect(this, SIGNAL(signalPaintColor(int)), this, SLOT(slotPaintColor(int)));
Do yourself a favor and switch over now to new-style for everything:
connect(this, &MainWindow::signalPaintColor, this, &MainWindow::slotPaintColor);
Isn't that neater? :)
Separately: why are you doing
connect()
signals/slots insideon_startButton_released()
? That means a new, additional connection will be made each time the button is pressed --- putqDebug()
s inslotPaintColor()
to see.connect()
s should be done during initialization only. -
@JonB
Dear Jon thx for this precise input to me.If you insist on using old-style signal/slot syntax, this is telling you you have got it wrong.
I would not insist here ...
Where did you get/copy
connect(this, SIGNAL(signalPaintColor(int i)), this, SLOT(slotPaintColor(int i)));
from?Honestly I do not remember.
Please copy examples, should be:
connect(this, SIGNAL(signalPaintColor(int)), this, SLOT(slotPaintColor(int)));
Do yourself a favor and switch over now to new-style for everything:
connect(this, &MainWindow::signalPaintColor, this, &MainWindow::slotPaintColor);
Isn't that neater? :)
Ofcourse it is neater. Doesn't the new syntax need to know about variables to be passed?
Separately: why are you doing
connect()
signals/slots insideon_startButton_released()
? That means a new, additional connection will be made each time the button is pressed --- putqDebug()
s inslotPaintColor()
to see.connect()
s should be done during initialization only.Its a leftover from trying things out - in this minimal code ...
Ofcourse I will move it back toMainWindow::MainWindow(QWidget *parent)
.What I am still wondering is how to get the loop from the measurement device together with painting the colors. Paint -> Measure -> Paint -> Measure ...
Would I need a "signal" telling me, that the color has changed on the monitor?thx for your help - it is most appreciated!
-
I changed the minimal example to this using two signals and two slots.
Please note " QThread::sleep(1);" is used only here - for simulating the measurement routine and the device - which is a black box routine eating some time ...The problem is still that with out
QApplication::processEvents();
inMainWindow::slotPaintColor(int i)
the color does not change.How can I achieve a loop which first changes the color and than - when this color is shown on screen (not before) - the measurement takes place ... and again until the colorlist is at the end ... all without using
QApplication::processEvents();
#include "mainwindow.h" #include "ui_mainwindow.h" using namespace std; struct rgb { int R; int G; int B; char cn [10]; } colors[5]; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this, &MainWindow::signalPaintColor, this, &MainWindow::slotPaintColor); connect(this, &MainWindow::signalMeasureColor, this, &MainWindow::slotMeasureColor); scene = new QGraphicsScene(this); ui->graphicsView->setScene(scene); scene->addItem(&pixmap); colors[0] = { 255, 255, 255, "white" }; colors[1] = { 255, 0, 0, "red" }; colors[2] = { 0, 255, 0, "green" }; colors[3] = { 0, 0, 255, "blue" }; colors[4] = { 0, 0, 0, "black" }; } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotPaintColor(int i){ QPixmap pix(ui->graphicsView->size()); pix.fill(QColor(colors[i].R, colors[i].G, colors[i].B)); pixmap.setPixmap(pix); ui->statusbar->showMessage("Color: " + QString(colors[i].cn), 0); QApplication::processEvents(); emit signalMeasureColor(); } void MainWindow::slotMeasureColor() { //Sleep is for simulation of external task here ... QThread::sleep(1); } void MainWindow::on_startButton_released() { ui->statusbar->showMessage("Start loop ...", 0); for( int i = 0; i < 5; i++ ) { emit signalPaintColor(i); } }
-
Well: do not block the event loop.
Since you are doing measures "on demand", use the worker object approach. Encapsulate the measurement part in its own class. Move the instance of that class to a dedicated QThread. And then use signals and slots to trigger the measure and pass back the data. Doing so you will decouple the controlling part and the UI.
-
@SGaist thx for the fast response.
Is there a "Qt standard Example" using this technique ?
That I can have a look how his works.Is this what you are talking about? https://wiki.qt.io/QThreads_general_usage
Am I right: This examples uses still old signal/slots syntax?
-
The wiki page is a bit outdated.
Check the QThread documentation. It has vastly improved and shows both technique with modern syntax.
-
Hi there,
now i have modified my minimal app to give threads a try.
I would need help with the new syntax for signal/slots across classes.I try to connect the signal from the thread with the slot in the main UI app like this:
connect(mThread, &MyThread::signalPaintColor, this, &MainWindow::slotPaintColor);mainwindow.cpp:20:5: error: no matching member function for call to 'connect'
qobject.h:242:43: note: candidate function [with Func1 = void (MyThread::)(int), Func2 = void (MainWindow::)(int)] not viable: cannot convert from base class pointer 'QThread ' to derived class pointer 'const typename QtPrivate::FunctionPointer<void (MyThread::)(int)>::Object ' (aka 'const MyThread ') for 1st argument
qobject.h:222:36: note: candidate function not viable: no known conversion from 'void (MyThread::)(int)' to 'const char ' for 2nd argument
qobject.h:225:36: note: candidate function not viable: no known conversion from 'void (MyThread::)(int)' to 'const QMetaMethod' for 2nd argument
qobject.h:481:41: note: candidate function not viable: no known conversion from 'void (MyThread::)(int)' to 'const char ' for 2nd argument
qobject.h:283:13: note: candidate template ignored: requirement '!QtPrivate::FunctionPointer<void (MainWindow::)(int)>::IsPointerToMemberFunction' was not satisfied [with Func1 = void (MyThread::)(int), Func2 = void (MainWindow::)(int)]
qobject.h:322:13: note: candidate template ignored: requirement 'QtPrivate::FunctionPointer<void (MainWindow::)(int)>::ArgumentCount == -1' was not satisfied [with Func1 = void (MyThread::)(int), Func2 = void (MainWindow::*)(int)]
qobject.h:274:13: note: candidate function template not viable: requires 3 arguments, but 4 were provided
qobject.h:314:13: note: candidate function template not viable: requires 3 arguments, but 4 were providedFrom mythread.h signals: void signalPaintColor(int i); public slots: void slotMeasureColor(int i);
From mainwindow.h signals: private slots: void on_startButton_released(); void slotPaintColor(int i);
-
@ademmler
Your error message is not on any of these. It states:mainwindow.cpp:20:5: error: no matching member function for call to 'connect'
qobject.h:242:43: note: candidate function [with Func1 = void (MyThread::)(int), Func2 = void (MainWindow::)(int)] not viable: cannot convert from base class pointer 'QThread ' to derived class pointer 'const typename QtPrivate::FunctionPointer<void (MyThread::)(int)>::Object ' (aka 'const MyThread ') for 1st argumentSo show your corresponding code. It even gives you the line number of the call.