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.
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.
In my application the main window's GUI is designed in the Qt-Creator designer. I have had some trouble in getting it to look just the way I'd like, but I can when doing the GUI in C++ code.
So, I plan to change the application's main window to be laid out in code.
What should I keep in mind when doing this?
How do I make sure all the menu items and button clicks etc. get migrated, too?
In my Qt experience I almost always write layout in code and here is what I can suggest:
a) Spend some time thinking which Layout to use, personally I tend to use either QGridLayout or nested QHboxLayout and QVBoxLayout which give you lot of flexibility.
b) I normally declare all child widgets as class variables always pointers and I create the real objects in the Main windows constructor.
About not to forget any control I suggest to print the XML of the UI file and draw a line on each control you recreate in the code.
As a good starting point, simply copy-pase the setupUi method from the ui_xxx.h file that uic had generated for you. You can then manually edit the setup code to suit your needs.
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.
In my application I have a file manager similar to the standart windows explorer.
The structure is:
QScrollArea
QWidget
EFile
EFile
EFile
etc...
Each EFile widget contains 5 QLabels. So when the count of files is more than 30 I have a little delay while they are being created. I decided to create only visible files and create hidden on scroll or resize when they become visible. But it's not a solution - the delay remained (although it decreased of course).
The question is how should I modify my application to remove the delay while showing files.
The answer is that you do not compose your custom widget of QLabels. Instead, you overwrite the paint() function and draw the texts/pixmaps with QPainter. It is not as much work as it sounds. There are tons of examples for that in the Qt examples/tutorials.
If it really is a file explorer you want to implement, you should consider using a QFileSystemModel in combination with a QTreeView as shown in the example here:
http://qt-project.org/doc/qt-4.8/qfilesystemmodel.html
This will save you a lot of trouble.
I am currently writing a wizard-style application using Qt4. I am not using the wizard class however, since going next/back does not make sense from every step in the process.
The user starts off at a "hub"-window with five buttons, each of which take him to another window at a different stage of the process. At the beginning all but the first button of the hub are disabled. After clearing each stage, the user will be directed back to the hub and one new button/stage will get enabled.
Since every stage has significantly differing objectives, I coded every single stage as a single QWidget that gets instantiated in the main() function. To switch between the widgets, I simply hide() the one I am leaving and show() the one I am going to.
However, this leads to problems if the user resized or moved one widget, since the next widget will always show up at its default position instead of the new one.
Is there a way to synchronize the widgets' sizes and positions?
Or, better yet, is there a more elegant way to deal with those different windows than switching between several hidden widgets?
Thank you in advance!
Create one top-level widget that holds the others.
I suggest that you either use QStackedWidget, or, if you want more control, create your own widget and use QStackedLayout directly.
Why not just have one main QWidget as a container for your pages? That way if the user moves the main QWidget and then goes to the next page, it will still open in the new position inside the main widget.
Generally, I've never had occasion to create multiple widgets inside my main method. Don't quite see the point.
I'm beginning on something similar - with different views (perspectives) for different tasks along the way. Using toolbar icons and file menu, not buttons, to move between views. Similar to how MS Outlook allows you to have the window display email, or a calendar, or contacts, etc.
My intent (haven't started yet) is to have one QMainWindow as the application window, containing my various QWidgets that offer the various views. Depending on what task the user is doing, one composite widget will be visible, and the others hidden.