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.
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 created one dialog that is used only to bindValues in a SQL database,
and I can save every new record sucessfully. The problem is that I've got another dialog with QSQlTableModel that only shows the information from the database. Every time I make a new record I must close the program and run it again to see the changes in the ShowInformationDialog().
Do you know some way such that I don't need to close the program to update the information in my ShowInformationDialog()?
You can use select() method of QSqlTableModel class to repopulate the model with data from the database. Bound views get updated automatically. I suggest connecting a signal from wherever you update the data in the database (i.e. your dialog updating the SQL database) to custom slot in your ShowInformationDialog() that calls the select() of the QSqlTableModel object. I assume you have a QMainWindow object that is parent of both dialogues which would be most likely the best place to establish the connection.
Also since your ShowInformationDialog()'s model is only used for viewing the data consider using QSqlQueryModel. If that is used then setQuery() method should be used instead of select() but otherwise (the connection of a signal to ShowInformationDialog()'s slot) it would be the same.
I'm using Qt 4.8 and trying to create a GUI showing one or more directory tree.
I read in a documentation that the QFileSystemModel uses separate thread.
I tried this:
QFileSystemModel *model = new QFileSystemModel;
model->setRootPath("C:/");
connect(model, SIGNAL(directoryLoaded(QString)), this, SLOT(alertLoaded(QString)));
ui->treeViewFolders->setModel(model);
Here alertLoaded only shows a message dialog when a directory is loaded.
So if I have right, when I'm trying to open a new directory branch in the tree, then it must load the items of the directory in the background so, that the UI is not freezed during the process.
But the problem is that it not seems to act like this. When I'm trying to open a directory with a 1000 or more files (e.g. system32), it freezes for a few seconds. Obviously the icons are slowing down the loading, but if the model is using a separate thread, why does it freeze?
The question:
How can I tell the model, that I really want to use a separate thread OR that I don't want to wait to the other thread?
AFAIK, QFileSystemModel always uses a separate thread. Sounds to me like your view is locking down your system while it retrieves the entire file list and resets the layout as it adds every item. The post is a little old, but they talk about your issue a little here.
Do you have the same delays if you use a QListView? If you use a QListView instead of a QTreeView you can set it to run in batch mode with QListView::setLayoutMode().
If you must have a QTreeView, you might consider subclassing it and using QAbstractItemView::scheduleDelayedItemsLayout() to layout everything in one go.
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.