I need to iterate over QTableWidget items from QMainWindow in a separate thread. Is there an easy way to do this or is it better to create the internal list and add table widget elements there? I have a lot of items (thousands) and I was thinking if it could be some performance bottleneck.
-
up vote 0 down vote You can not interact with the GUI from a secondary thread, when you want to modify the GUI from a different thread to the main you must do it through signals and slot. read this for more information: https://stackoverflow.com/questions/16501284/qt-updating-main-window-with-second-thread – eyllanesc Jun 27 '17 at 00:59
-
So what do you want to change? – eyllanesc Jun 27 '17 at 00:59
-
I don't want to change anything. I just want to iterate over items list and use these items as an arguments to a function. I just want to read the list. – Konrad Jun 27 '17 at 01:00
-
Obtain the list of items with `QTableWidget::items()` and pass it to the new thread. Also, have you verified that you generate that bottleneck that you comment? – eyllanesc Jun 27 '17 at 01:03
-
No, I haven't verified. It's a design issue at the moment. – Konrad Jun 27 '17 at 01:05
-
You should do a test before asking, so you will contribute more and we will appreciate it. :P – eyllanesc Jun 27 '17 at 01:06
-
Why don't use directly in same thread ? – DreamInBox Jun 27 '17 at 05:42
-
1If you need only readonly access and you are sure, that data will not be changed - you can. – Dmitry Sazonov Jun 27 '17 at 07:43
1 Answers
I need to iterate over QTableWidget items from QMainWindow in a separate thread.
Qt generally doesn't support this -- Qt's GUI objects are intended to be accessed only from the main thread; the Qt GUI event loop will access them without any locking or serialization (e.g. when it's redrawing the window), so it's unsafe to access them from another thread. If you try to access them from another thread, you are likely to run into race conditions, particularly if either the main thread or the GUI thread ever tries to modify or delete any of the items they are accessing. Therefore the safe approach is to have your separate thread only work on data objects that your main thread does not have access to; when the separate thread is done processing them, it can then send them on to the main/GUI thread via postEvent() or a queue signal/slot connection or similar.
That said, if you can guarantee that neither Qt nor the separate thread will ever try to modify the list of QTableWidget items, or the QTableWidget items themselves, then you might be able to get away with doing read-only accesses to them concurrently from both the GUI and the other thread. Of course, that assumes that Qt's code isn't secretly modifying their internal state behind your back in ways that you wouldn't expect (e.g it might be storing calculated size/position values inside the objects to avoid having to recalculate them over and over again). So I wouldn't advise doing that unless you're really desperate for a speedup and willing to take some risks to get it.
Note that if you plan on having a huge number of items in your table, but also require good performance, then QTableWidget is probably not the right tool for the job. In that case, the overhead of allocating a separate QWidgetItem for each cell in the table is just too large. For a giant table (i.e. hundreds or thousands of rows and columns), you'll be better off instead with a QTableView and a custom QAbstractTableModel object. That way Qt can simply query your QAbstractTableModel object whenever it needs to draw (or edit) a cell, and your QAbstractTableModel object can provide the necessary data using whatever logic is most appropriate and efficient for your use case. (See Qt's $QTDIR/examples/widgets/itemviews/pixelator example application for an example of this approach) That way your app's table can be fast without resorting to multiple threads.

- 70,199
- 15
- 131
- 234