Custom Widget in QListWidget doesn't show correct in list
I created a custom widget in Qt designer, (with source for changing properties) consisting of a label, progress bar and a checkbox. I have that as an object in a mainwindow to display in a list when triggered. The first trigger displays the widget. Each successive trigger displays the widget in a subsequent row down the list but there only exists one widget with empty rows above.
Widget Code:
Controls.h
Code:
#ifndef CONTROLS_H
#define CONTROLS_H
#include <QWidget>
namespace Ui {
class Controls;
}
{
Q_OBJECT
public:
explicit Controls
(QWidget *parent
= 0);
~Controls();
public:
Ui::Controls* ui;
public slots:
void WriteInfoNumber(int);
private:
// Ui::Controls *ui;
};
#endif // CONTROLS_H
Controls.cpp
Code:
#include "controls.h"
#include "ui_controls.h"
#include <QDebug>
Controls
::Controls(QWidget *parent
) : QWidget(parent
), ui
(new Ui
::Controls){
ui->setupUi(this);
}
Controls::~Controls()
{
delete ui;
}
void Controls::WriteInfoNumber(int value)
{
qDebug() << "ID Value = " << value;
ui
->label
->setText
(QString::number(value
));
}
MainWindow.h
Code:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "controls.h"
namespace Ui {
class MainWindow;
}
{
Q_OBJECT
public:
explicit MainWindow
(QWidget *parent
= 0);
~MainWindow();
signals:
void UpdateInfo(int);
private slots:
void on_actionFile_triggered();
void on_actionE_xit_triggered();
private:
Ui::MainWindow* ui;
Controls* ctls;
};
#endif // MAINWINDOW_H
MainWindow.cpp
Code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_Controls.h"
#include <QTime>
{
ui->setupUi(this);
ctls = new Controls();
connect(this, SIGNAL(UpdateInfo(int)), ctls, SLOT(WriteInfoNumber(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionE_xit_triggered()
{
}
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
ui->listWidget->insertItem(ui->listWidget->size().height(),item);
ui->listWidget->setItemWidget(item, ctls);
emit UpdateInfo(t.msec());
}
It seems so straightforward. Don't know what I'm missing.
Re: Custom Widget in QListWidget doesn't show correct in list
You only have one object of type Controls, obviously it can only be displayed in one place.
Cheers,
_
P.S.:you don't need to insert the QListWidgetItem, passing the list widget to the constructor takes care of that already.
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
You only have one object of type Controls, obviously it can only be displayed in one place.
Cheers,
_
P.S.:you don't need to insert the QListWidgetItem, passing the list widget to the constructor takes care of that already.
Yes that's correct. I only want one type of object displayed in the list. I want to add it to the list for every trigger so as to get a list of rows of the object displayed.
Hope that's clearer than what I originally wrote.
Re: Custom Widget in QListWidget doesn't show correct in list
What anda_skoa said was, "You only have one object of type Controls", not "You only have one type of object." It stands to reason that a single Controls widget can be displayed in only the one place. If you want to simultaneously display multiple widgets of type Controls then you need to create multiple objects of that type.
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
ChrisW67
What anda_skoa said was, "You only have one object of type Controls", not "You only have one type of object." It stands to reason that a single Controls widget can be displayed in only the one place. If you want to simultaneously display multiple widgets of type Controls then you need to create multiple objects of that type.
.
Right!
So call new Controls() in line 29 rather than ctls does the trick for handling multiple entries but breaks the emitted signal for updating the label part of the custom widget. What broke? Perhaps I need a different sender in the signal/slot line in the ctor?
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
astodolski
.
So call new Controls() in line 29 rather than ctls does the trick for handling multiple entries but breaks the emitted signal for updating the label part of the custom widget. What broke? Perhaps I need a different sender in the signal/slot line in the ctor?
How do you connect now?
Cheers,
_
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
How do you connect now?
Cheers,
_
Line 10 MainWindow.cpp. I connect the emitted signal to the method WriteInfoNumber in Control.cpp
Re: Custom Widget in QListWidget doesn't show correct in list
That was from before, when you had only one instance.
If you want all instances of your widget to receive the signal, you need to connect to each one after its respective creation.
Cheers,
_
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
That was from before, when you had only one instance.
If you want all instances of your widget to receive the signal, you need to connect to each one after its respective creation.
Cheers,
_
So my trigger method is now as follows:
Code:
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
ui->listWidget->insertItem(ui->listWidget->size().height(),item);
ui->listWidget->setItemWidget(item, new Controls);
emit UpdateInfo(t.msec());
}
The slot connected to UpdateInfo does not change the label. If as you suggest, I connect to each successive instance, I still don't get a change in the label from the slot associated. What I do see however is a call to the slot for each entry in the list: i.e 1 call for the first, 2 calls for the second entry, 3 calls for the third in the list etc.
Should there be a different connect?
What I was able to do as perhaps an interitm step is to call the following which fortunately sets the text for the label:
Code:
item
->setText
(QString::number(t.
msec()));
Since I have two other controls, that being a progress bar and the other a checkbox, I still am not sure how to set those other items in the custom widget
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
astodolski
So my trigger method is now as follows:
Code:
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
ui->listWidget->insertItem(ui->listWidget->size().height(),item);
ui->listWidget->setItemWidget(item, new Controls);
emit UpdateInfo(t.msec());
}
That is still missing the connect
Code:
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
// create instance of Controls
Controls *ctls = new Controls;
// connect signal to Controls instance
connect(this, SIGNAL(UpdateInfo(int)), ctls, SLOT(WriteInfoNumber(int)));
ui->listWidget->setItemWidget(item, ctls);
emit UpdateInfo(t.msec());
}
Cheers,
_
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
That is still missing the connect
Code:
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
// create instance of Controls
Controls *ctls = new Controls;
// connect signal to Controls instance
connect(this, SIGNAL(UpdateInfo(int)), ctls, SLOT(WriteInfoNumber(int)));
ui->listWidget->setItemWidget(item, ctls);
emit UpdateInfo(t.msec());
}
Cheers,
_
I may be misunderstanding. The Controls instance is the object named ctls. The signal UpdateInfo is connected to the WriteInfoNumber slot belonging to the Controls class.
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
astodolski
The Controls instance is the object named ctls.
Yes.
Quote:
Originally Posted by
astodolski
The signal UpdateInfo is connected to the WriteInfoNumber slot belonging to the Controls class.
Yes. The connect() call's arguments are:
1) sender object
2) signal
3) receiver object
4) slot
Your original code was creating a Controls instance in the constructor and connected to it.
Your new code creates new Controls instances on every actionFile triggered(). If you want those instances to receive the signal as well, you connect to them as well.
Cheers,
_
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
Yes.
Yes. The connect() call's arguments are:
1) sender object
2) signal
3) receiver object
4) slot
Your original code was creating a Controls instance in the constructor and connected to it.
Your new code creates new Controls instances on every actionFile triggered(). If you want those instances to receive the signal as well, you connect to them as well.
Cheers,
_
If I copy the connect call from the ctor to the actionFile_triggered() method, the SLOT gets called for every entry that's in the list. That is for the initial entry, one call. The next instance doesn't signal the slot once, it get's called twice and so on. How do I fix that?
Re: Custom Widget in QListWidget doesn't show correct in list
I am not sure I understand, the slot should only get called once per receiver object.
Do something like this in the slot
Code:
qDebug() << Q_FUNC_INFO << "this=" << this;
and check if "this" is the same twice per emit.
Cheers,
_
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
I am not sure I understand, the slot should only get called once per receiver object.
Do something like this in the slot
Code:
qDebug() << Q_FUNC_INFO << "this=" << this;
and check if "this" is the same twice per emit.
Cheers,
_
I will try this but in the meantime look at the slot in Controls.cpp It contains a debug statement:
Code:
qDebug() << "ID Value = " << value;
For every instance the slot gets called the number of entries in the list. All the code for this small sample is posted. Maybe you can load it and run it to see what I mean. A UI which isn't posted will have to be created to have the three controls that is supposed to be in the custom widget.
Update:
The results of your suggestion is as follows:
Code:
ID Value = 268
void __thiscall Controls::WriteInfoNumber(int) this= Controls(0x389ef0, name = "Controls")
ID Value = 147
void __thiscall Controls::WriteInfoNumber(int) this= Controls(0x389ef0, name = "Controls")
ID Value = 147
void __thiscall Controls::WriteInfoNumber(int) this= Controls(0x389ef0, name = "Controls")
ID Value = 627
void __thiscall Controls::WriteInfoNumber(int) this= Controls(0x389ef0, name = "Controls")
ID Value = 627
void __thiscall Controls::WriteInfoNumber(int) this= Controls(0x389ef0, name = "Controls")
ID Value = 627
void __thiscall Controls::WriteInfoNumber(int) this= Controls(0x389ef0, name = "Controls")
That's when calling on_actionFile_triggered() 3 times!
Re: Custom Widget in QListWidget doesn't show correct in list
I pieced together the bits and created dummy .ui files and I get this
Code:
created new control Controls(0x20c5340, name = "Controls")
this= Controls(0x20c5340, name = "Controls") ID Value = 503
created new control Controls(0x20757d0, name = "Controls")
this= Controls(0x20c5340, name = "Controls") ID Value = 511
this= Controls(0x20757d0, name = "Controls") ID Value = 511
created new control Controls(0x20f4d40, name = "Controls")
this= Controls(0x20c5340, name = "Controls") ID Value = 26
this= Controls(0x20757d0, name = "Controls") ID Value = 26
this= Controls(0x20f4d40, name = "Controls") ID Value = 26
The "created new control" comes right from after creating the control inside the slot
Code:
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
ctls = new Controls();
qDebug() << "created new control" << ctls;
connect(this, SIGNAL(UpdateInfo(int)), ctls, SLOT(WriteInfoNumber(int)));
ui->listWidget->setItemWidget(item, ctls);
emit UpdateInfo(t.msec());
}
The other one obviously from the slot in Controls.
As we can see, the first control is created, it receives the signal. Then he second control is created and both instances get the signals, as expected
Then a third control is created and, again as expected, all three get the signal.
Now, I have no idea why you want all of them to show the same value, but the do. No receiver's slot is called twice per emit.
Cheers,
_
1 Attachment(s)
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
I pieced together the bits and created dummy .ui files and I get this
Code:
created new control Controls(0x20c5340, name = "Controls")
this= Controls(0x20c5340, name = "Controls") ID Value = 503
created new control Controls(0x20757d0, name = "Controls")
this= Controls(0x20c5340, name = "Controls") ID Value = 511
this= Controls(0x20757d0, name = "Controls") ID Value = 511
created new control Controls(0x20f4d40, name = "Controls")
this= Controls(0x20c5340, name = "Controls") ID Value = 26
this= Controls(0x20757d0, name = "Controls") ID Value = 26
this= Controls(0x20f4d40, name = "Controls") ID Value = 26
The "created new control" comes right from after creating the control inside the slot
Code:
void MainWindow::on_actionFile_triggered()
{
item
->setSizeHint
(QSize(300,
35));
ctls = new Controls();
qDebug() << "created new control" << ctls;
connect(this, SIGNAL(UpdateInfo(int)), ctls, SLOT(WriteInfoNumber(int)));
ui->listWidget->setItemWidget(item, ctls);
emit UpdateInfo(t.msec());
}
The other one obviously from the slot in Controls.
As we can see, the first control is created, it receives the signal. Then he second control is created and both instances get the signals, as expected
Then a third control is created and, again as expected, all three get the signal.
Now, I have no idea why you want all of them to show the same value, but the do. No receiver's slot is called twice per emit.
Cheers,
_
I appreciate you staying with me on this problem. However your observation is incorrect. The "ID Value = " does in fact get displayed more times than it is supposed to. There should ONLY be one ID value for each instance - at least that's what the goal is:
Attachment 10067
Code:
created new control Controls(0x5b16b8, name = "Controls")
ID Value = 309
void __thiscall Controls::WriteInfoNumber(int) this = Controls(0x5b16b8, name = "Controls")
created new control Controls(0x5df218, name = "Controls")
ID Value = 802
void __thiscall Controls::WriteInfoNumber(int) this = Controls(0x5b16b8, name = "Controls")
ID Value = 802
void __thiscall Controls::WriteInfoNumber(int) this = Controls(0x5df218, name = "Controls")
created new control Controls(0x5dfda8, name = "Controls")
ID Value = 896
void __thiscall Controls::WriteInfoNumber(int) this = Controls(0x5b16b8, name = "Controls")
ID Value = 896
void __thiscall Controls::WriteInfoNumber(int) this = Controls(0x5df218, name = "Controls")
ID Value = 896
void __thiscall Controls::WriteInfoNumber(int) this = Controls(0x5dfda8, name = "Controls")
If I debug into the slot for Controls, it does get hit as many times as the debug statements show.
Re: Custom Widget in QListWidget doesn't show correct in list
That shows the same output as for me, i.e. each Controls's slot is called once per signal emit.
Every time the signal gets emitted, the main window sends a single value to all objects that are connected to that signal.
At first there is only one object, so only one debug output it shown.
Then there are two receiver objects, so two debug outputs are shown, and so on.
A signal "broadcasts" information, anyone interested in that information can connect to the signal and get notified about these broadcasts. Each receiver is independent of any other, all receive the information equally, just like if they were the only receiver.
The current code is doing what your initial code attempted to do: having "one" object in every row, the value updating simultaniously in all rows.
Is this is not what you were aiming at then this is the wrong approach :)
Cheers,
_
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
anda_skoa
That shows the same output as for me, i.e. each Controls's slot is called once per signal emit.
For each emit of the signal UpdateInfo, a breakpoint on the slot it is connected to gets a hit more than once after the initial instance. I illustrated that with the debug output as well as the screen shot.
Quote:
The current code is doing what your initial code attempted to do: having "one" object in every row, the value updating simultaniously in all rows.
Well, not exactly. One object per row, sure. The ID which I represented by a time interval is expected to be a unique number for each instance. The same value in all rows is definitely not what is intended.
Quote:
Is this is not what you were aiming at then this is the wrong approach :)
Cheers,
_
I hope I at least conveyed the right approach :)
Re: Custom Widget in QListWidget doesn't show correct in list
Quote:
Originally Posted by
astodolski
For each emit of the signal UpdateInfo, a breakpoint on the slot it is connected to gets a hit more than once after the initial instance.
A breakpoint on a method is hit every time the method is invoked. Since you have multiple objects of that class, and all their slots are connected, your breakpoint is hit once per instance.
Quote:
Originally Posted by
astodolski
Well, not exactly. One object per row, sure. The ID which I represented by a time interval is expected to be a unique number for each instance. The same value in all rows is definitely not what is intended.
So does this value change over time?
If not, why use a signal and not just imply pass the value via a setter or constructor argument?
Cheers,
_