Empty rows in QTableWidget
-
I'm developing an application in Qt/C++ which uses a QTableWidget. Something that's really bugging me is that the table, which is vertically scrollable, has a large amount of empty rows which do not appear to be caused by my code. I also can't seem to delete them; I've tried clearContents() and using removeRow() in a loop, but they're still there. For example:
I would greatly appreciate if anyone could help me resolve this issue, or even provide some insight as to the problem.
-
use QTableView instead of QTableWidget.
link data source with appropriate Model and then link Model with view(QTableView)this with enable u to simulate data
-
Oke,
The big difference between a TableWidget and a TableView is the way it is build up. When you use the QTableWidget you are the one adding the widgetItems to the table. The Table doesn't think them up himself, so check your code where you add the underling widgets. If the TableWidget does have to many rows/column you can easily delete them with: setRowCount(x), but be aware the the rows also included the widgets and they will be cleaned up with the remove of the rows.
When you use the TableView/Model concept you are responsible to controle the data displayed in the model. The model controls the amount or rows/columns in the view.
You can check out the fine tutorial: "Model/View tutorial":http://qt-project.org/doc/qt-4.8/model-view-programming.html
Hope this helps!
Greetz -
Thanks for the replies.
So are you saying the problem must be in my code? I have a decent amount of code structured around this TableWidget, so if it can be fixed I'd rather keep it this way. Otherwise, I guess I'll look into QTableView.To illustrate, this is how I'm adding content:
@void MainWindow::update_table()
{
vectorproc::process proc_vector;
QTableWidgetItem *pid_item;
QTableWidgetItem *procname_item;
QTableWidgetItem *procstate_item;while(true) { proc_vector = proc::list_processes(); ui->procTable->clearContents(); for(size_t x = 0; x < proc_vector.size(); x++) { pid_item = new QTableWidgetItem(QString::number(atoi(proc_vector.at(x).pid.c_str())), Qt::DisplayRole); procname_item = new QTableWidgetItem(QString::fromStdString(proc_vector.at(x).name), Qt::DisplayRole); procstate_item = new QTableWidgetItem(QString::fromStdString(proc_vector.at(x).state), Qt::DisplayRole); ui->procTable->insertRow(x); ui->procTable->setItem(x, 0, pid_item); ui->procTable->setItem(x, 1, procname_item); ui->procTable->setItem(x, 2, procstate_item); } sleep(3); }
}@
-
From the docs for QTableWidget::clearContents():
bq. Removes all items not in the headers from the view. This will also remove all selections. The table dimensions stay the same.
So, each time around this loop you are adding more rows to the existing rows. If you want to start at zero rows each time you need to setRowCount(0).
The other problem your code has is that it never returns to the Qt event loop, so once you enter this function the program will stop being usefully responsive. If you want to update this table once every three seconds then you should use a QTimer to trigger a slot that does one update and then exits.
-
[quote author="ChrisW67" date="1353130288"]From the docs for QTableWidget::clearContents():
bq. Removes all items not in the headers from the view. This will also remove all selections. The table dimensions stay the same.
So, each time around this loop you are adding more rows to the existing rows. If you want to start at zero rows each time you need to setRowCount(0).
The other problem your code has is that it never returns to the Qt event loop, so once you enter this function the program will stop being usefully responsive. If you want to update this table once every three seconds then you should use a QTimer to trigger a slot that does one update and then exits.[/quote]
I must have overlooked that in the documentation, cheers. Okay, I added setRowCount(0), but strangely now the empty rows appear only sometimes when the program is launched.
I don't see how you mean it becomes unresponsive, I have this function executing using QtConcurrent::run()? -
bq. I don’t see how you mean it becomes unresponsive, I have this function executing using QtConcurrent::run()?
Well, in that case it is only running by accident. Accessing elements of the (typically private) GUI from a thread other than the main one, and doing so without synchronisation is a Bad Thing. From the "Threads and QObjects":http://doc.qt.nokia.com/latest/threads-qobject.html docs:
bq. Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.
Use signal/slot connection or rethink why you want to do this. You certainly do not need multiple threads to achieve this periodic update.
-
Okay, I've changed the class to use a signal and slot connection for these actions, and it's definitely solved a lot of stability problems. Thanks for all the help. :)
On a final note, when the program initially launches it prints this message:
QMetaObject::connectSlotsByName: No matching signal for on_procTable_updated(bool)
However, the slot is definitely being called and everything seems to work as it should. -
I assume the slot is being called because you are manually connecting something to it.
You have a slot called on_procTable_updated(bool) in your class that the ui->setup() tries to find a match for in the UI using QMetaObject::connectSlotsByName(). It fails because you do not have a widget called "procTable" that has a signal called "updated(bool)" in that UI. It's a warning, not an error. You can avoid it by naming your manually connected slot so it does not match the magic pattern.
-
[quote author="ChrisW67" date="1353472147"]I assume the slot is being called because you are manually connecting something to it.
You have a slot called on_procTable_updated(bool) in your class that the ui->setup() tries to find a match for in the UI using QMetaObject::connectSlotsByName(). It fails because you do not have a widget called "procTable" that has a signal called "updated(bool)" in that UI. It's a warning, not an error. You can avoid it by naming your manually connected slot so it does not match the magic pattern.
[/quote]
Thank you, that explains a lot. I've gotten rid of the warning now.
I was under the impression that by the way I had named the signal and the slot they should have successfully connected without the call to connect(), though.