Previously, I asked about running model and view in different threads and now, I understand how it poses a problem. To circumvent the problem, I was thinking of duplication of data. When data is modified by the worker thread, it simultaneously sends an update to GUI/Model thread to update the model with the same data (so there exist a exact copy of data with the GUI/model).
Does this sound like a plausible approach? Other method is to use direct widgets with default models like QTableWidget etc. but then I need to do a lot of things that are powered by QTableView by default.
Please suggest!
Link to other question: Design Pattern, Qt Model/View and multiple threads
There are 2 scenarios that are possible but in either case you will need at least 2 objects as follows:
Data Object
Contains all functions required for maintaining and manipulating data. Data is stored in Pointers to objects describing data. Data Structures for this I will leave up to you.
Model
Contains a vector of pointers to data that is currently being displayed
Scenario 1
Data in QTableView is display only in which case on a QTimer signal or a different signal the data storage is locked and vector for display model is cut and put into the model and reset() is called to have QTableView repainted with new data.
Scenario 2
You can manipulate data via custom ItemEditor in QTableView. In this case the top widget that has QTableView should have references to your data object and QTableView and a signal handler for the signal emitted by the ItemEditor when the edit is complete. This signal handler will then lock the data structure inside data object and update it, once done it may cut a new vector to display but more often then not it won't have to.
How you will set up the locking, searching, etc is entirely up to you.
Related
I am working on a packet sniffer with C++, using QT for the user interface.
I have two main threads: QT's main thread, and another thread that takes care of the packet capture and processing.
The capture thread captures and processes the packets -> it then sends the result to the GUI thread which displays it using the signals and slots mechanism.
I am using a QTableWidget to display the packets.
The problem is that when I have a massive flow of packets (When downloading something for example) the program starts to lag and the program starts to eat a lot of CPU (Up to 17% during a download or a video)
Is there a solution to optimize a QTableWidget and make my program more fluid?
My QTableWidget:
Your best bet is probably to stop using QTableWidget and use a QTableView instead. The difference between a QTableWidget and a QTableView is that a QTableWidget dynamically allocates a separate QTableWidgetItem object to hold the state of each cell; if you are creating and/or deleting a lot of cells in a short period of time (which it appears you are), the creation and/or deletion of all of these objects can be quite inefficient.
QTableView, on the other hand, doesn't require the creation of any per-cell QTableWidgetItem objects, which allows it to be more efficient when under heavy load. Instead a QTableView has to consult a model-object, and the model object tells the QTableView what data to display at any given moment. You'll need to create your own subclass of QAbstractTableModel for your QTableView to consult with, and call setModel() on your QTableView object with a pointer to your model-object.
It's all a bit involved, so you will want to read through Qt's documentation on the subject and look at their example-programs before trying to implement your own.
I've used this approach to implement e.g. a log-view which sometimes has dozens-to-hundreds of log messages generated per second, and it works well once you've set up the model correctly.
I have bunch of data that has to be displayed continuously on the GUI. I can actually achieve it by setting timer and assigning the new values to the displayed values but I do not want to do in that way. Is there any solution or practical way to do that?
I think you have two options to achieve that:
All your data have a Q_PROPERTY. That means create a get function and a signal
If you want to show them under a list or a treeview, I suggest you gather all the data up, under a QAbstractListModel.
https://doc.qt.io/qt-5/qabstractlistmodel.html
Then implementing the function data, index, ecc., you will have everything already done for the UI
Have you tried using Q_Property? Notify Signal may work for your situation.
You can find the documentation from here.
First, I defined the property and added the notifier called payloadChanged to the signals of my class.
Q_PROPERTY(QList<qreal> PayloadList READ getPayloadList NOTIFY payloadChanged)
Secondly,
qmlRegisterType<<YOUR_CLASS_NAME>>("sample1.sample2", 1, 0, "<QML_ITEM_NAME>");
Finally
QML_ITEM_NAME{
console.log("PROPERTY")
}
When I applied these steps my data is automatically updated without any timer stuff.
I have some newbie question. I'm not sure if I understand Model-View-Controller design pattern correctly.
Maybe I will start from describing my problem. I'm reading some data from file. This can take let's say 10 seconds and after that I present those data in the table. The question is how should I store those data? Besides QStandardItemModel should I have another container to which I will read data from file and use it in other threads? For example, I have QStandardItemModel in Gui thread and I create another container let's say QVector. I load data from file to QVector and then I move data from QVector to QStandardItemModel?
I can't use QStandardItemModel in other thread and read data directly from file to QStandardItemModel because GUI freeze as I know because QStandardItemModel emits signal to update view after appendRow.
Or maybe I should create custom model and add method to update view only when whole file is loaded into QStandardItemModel? QTableView has own container for data and it's not synchronized with the model? Is it possible/correct way?
What with situation when I read a new file?
Thanks for any help.
I think you can do such steps for resolve your problem:
When you need to load new data from file, set model for your QTableView in nullptr.
Fill QStandardItemModel (this model was the model for your QTableView) in non-main (non-GUI) thread with data from file.
Set model with data for your QTableView in main (GUI) thread.
Of course, the simplest way to solve your problem also may be to show for user something like this: "Data loading, please wait...", while you load data in QStandardItemModel in main (GUI) thread.
I have a really big tree structure and I cant load the complete tree into Ram on client side. I am using Qt's QTreeView.
I want to load the sub elements of an item dynamically when the user expands the element.
Is there some signal that triggers when the user opens an item in the tree?
I am using the tutorial Simple Tree Model Example. When I do changes to the model the view has also to be updated. And I dont want to loose the focus to avoid user confusion!
and after some time (request to the server)...
You need to implement a subclass of QAbstractItemModel that can process needed amount of data. When an item is expanded in the view, it calls QAbstractItemModel::rowCount to determine children count and then QAbstractItemModel::flags and QAbstractItemModel::data to get children data. If requested data is not available at the moment, you should return placeholder data (i.e. 1 row containing "Loading"), and start a request. When the data is received, emit rowsAboutToBeInserted and rowsInserted signals to notify the view about new data (you should also notify it about removing "Loading" row). The view will then call rowCount, data, and flags methods again, and your model should now provide loaded data. Use QCache to keep last accessed data in memory.
I have a QT application that allows a user to define a list of models. Each model defined has a fairly complex widget class that is created. Currently this is all being done in the main (GUI) thread. The program works fine for normal use, but I tried to stress test it by creating 200 to 1000 models and the creation of the GUI took a VERY long time (20 seconds to many minutes).
I tried a couple attempts at threading out the work using QtConcurrent::run, but the program always complained because "Widgets must be created in the GUI thread."
I found this answer on SO: How do I create a Window in different QT threads?. But this doesn't seem to be doing much in the new thread except telling the main thread to create a new widget. This does not distribute the workload, as far as I can tell.
With all of that, I have a couple direct questions:
1) Is there a better design (faster performance) than looping through my list of models and serially creating each widget?
2) If this process is possible to be multithreaded, can someone point me in the direction of a simple example?
There really is no way to put widget stuff to other threads. OpenGL rendering or some data processing for a widget to show when ready, stuff like that can easily use other thread, but not the actual widgets.
Better design would be to create the widget when you need it. Or just have one widget and update the data it displays (unless widgets for different items are actually different).
If you are worried about performance when scrolling, then one solution to that is to switch widget only after current one has been visible for some minimum time (say, 500ms if user keeps scrolling, or 200ms after last scroll event, some logic like that) note that this is not delay for reacting to user selection, this is delay after selection and visible widget change, so if user just changes to next item, GUI is updated immediately. But in scrolling the widget is not updated for every item briefly selected, and things don't slow down. Use QTimer or two to send signal when widget should be updated.