I would like to know what the established procedure is for initializing the controls within a Qt custom dialog box. In the code I am writing, the dialog would present a QListView containing directories from an object passed (by reference) to the dialog class during construction. When the dialog is displayed, I obviously want the list to display the directories currently configured in the object.
Where should this be done though? Perhaps in the overridden showEvent() method?
Background: I used to do a lot of MFC programming back in the day, and would have done this sort of stuff in the OnCreate method, or some such, once the window object had been created.
Thankfully Qt doesn't require you to do any hooking to find the moment to create things (unless you want to). If you look over the Qt examples for dialogs, most do all the constructing in the constructor:
http://doc.qt.io/archives/qt-4.7/examples-dialogs.html
The tab dialog example--for instance--doesn't do "on-demand" initializing of tabs. Although you could wire something up via the currentChanged signal:
http://doc.qt.io/archives/qt-4.7/qtabwidget.html#currentChanged
Wizard-style dialogs have initializePage and cleanupPage methods:
http://doc.qt.io/archives/qt-4.7/qwizardpage.html#initializePage
http://doc.qt.io/archives/qt-4.7/qwizardpage.html#cleanupPage
But by and large, you can just use the constructor. I guess the main exception would be if find yourself allocating the dialog at a much earlier time from when you actually display it (via exec), and you don't want to bear the performance burden for some part of that until it's actually shown. Such cases should be rare and probably the easiest thing to do is just add your own function that you call (like finalizeCreationBeforeExec).
Related
I'm learning qt by working on given examples. I've started to play a bit with keyboard shortcuts. To assign them I've used QtDesigner which is very handy, for example using "return" key to click a research QPushButton.
Here my main class is a Widget called TextFinder, which has a pointer on a Ui::TextFinder class, which is automatically built from QtCreator, which is the standard procedure to encapsulate user interface attributs and methods.
By assigning a shortcut using QtDesigner, the following lines are generated in the Ui::TextFinder class:
#ifndef QT_NO_SHORTCUT
findButton->setShortcut(QApplication::translate("TextFinder", "Return", nullptr));
#endif // QT_NO_SHORTCUT
where findButton is an alias for my QPushButton. So far so good.
Suppose now, in a large program, I want to implement many shortcuts to trigger many kinds of signal and I use QtDesigner to do so, it will generate these lines of code, possibly in different header files corresponding to different widgets. It will become quickly difficult to manage them and have a global vision of the "shortcuts state" of the program.
What would be a good method to manage all the shortcuts in the program at one place? Is it possible to make some config file to perform this task?
Typically in this case you go one level up from the shortcuts and look into Actions.
A QAction is a somewhat global (e.g. on the level of a QMainWindow) vehicle for something that the user can trigger (or toggle) through various ways. To name the most prominent ones,
Menu entries
(Toolbar) buttons
Shortcuts
You can manage your actions through Qt Designer (if you have a QMainWindow), or at a central place in your code. Note that the action encompasses not only the shortcut, but also title, icon etc.
You can arrange a toolbar in Qt Designer by dragging actions onto it, but you can also manually assign an action to any button in code.
How do you use QStyledItemDelegate / QItemDelegate to permanently display a complex widget, i.e. to handle the Qt.DisplayRole, not just Qt.EditRole?
The documentation eludes to using paint()... but that's just way to complex! Let's take for example rendering a QTreeView or QTableVeiw inside of a QTableView cell.
There is QAbstractItemView.setIndexWidget(), but that is a bad idea as it only used to display static content (and whats the fun in static models?).
Note
I found part of the answer in another post, but it was only a small subset of the answer, so I thought it warranted a new post with proper question.
The key is to use QAbstractItemView.openPersistentEditor() to always keep the cell in edit mode.
Some additional key elements
The Qt.EditRole flag will need to be provided for the cells which use delegates.
QStyledItemDelegate.sizeHintChanged.emit(index) needs to be called anytime the size of the editor widget has changed.
Implementing QStyledItemDelegate.sizeHint() can be tricky and tedious (or you can do index.internalPointer().editor_widget.sizeHint() assuming you saved a reference of the editor to the internal pointer during QStyledItemDelegate.createEditor()
here is a good post on how to determine sizes: What are the mechanics of the default delegate for item views in Qt?
Caution
It should be mentioned that opening editors is costly, so if you have thousands of indexes and they are all loaded at once, it can take a while. There are many ways to mitigate this issue:
Load the model incrementally using a thread
Use Qt's fetchMore() mechanism
call openPersistentEditor incrementally (using a timer, or as they come into view for the first time)
call openPersistentEditor when the parent is expanded and closePersistentEditor when the parent is collapsed, and possibly restrict the use of expand-all on nodes with many children.
[EDIT] - wasn't getting to the disable code the way I thought I was; works fine with any of the solutions below.
I have a modeless QT dialog, in which all kinds of user settings can be manipulated. In addition, it can save and load large data sets, which can take several seconds. Lots going on in the main window underneath (realtime app) and that's fine, and interaction there is okay, but in the dialog itself, I need to block user interaction.
Essentially, during the load, I don't want the user to be able to change / affect any of the controls in the modeless dialog (and there are a lot of them.)
Rather than disable each one individually (or even that way if that's the only way), is there a straightforward means I can use to disable input to the dialog entirely until the load is complete?
There's a progress bar in it that shows what's going on, too, which is constantly updated by the load process, so that needs to keep on working.
I tried this...
On dialog open:
QDialog *window = this;
Then around load:
window->setDisabled(true);
....
window->setDisabled(false);
...which compiles fine, and runs without complaint, but the window did not disable.
I also tried:
window->setEnabled(false);
....
window->setEnabled(true);
...that doesn't seem to do anything either.
I tried this too:
QList<QWidget*> list = window->findChildren<QWidget *>();
foreach(QWidget *qw, list)
{
qw->setEnabled(false);
}
....
QList<QWidget*> list = window->findChildren<QWidget *>();
foreach(QWidget *qw, list)
{
qw->setEnabled(true);
}
..also does nothing.
Based on Qt documentation (http://doc.qt.io/archives/qt-4.8/qwidget.html#enabled-prop):
Disabling a widget implicitly disables all its children. Enabling
respectively enables all child widgets unless they have been
explicitly disabled.
So your snippets are essentially doing same thing in different ways so that doesn't seem to be a problem and modality of dialog shouldn't have any effect on this as well. How are you loading / saving the data? If you are doing it in e.g. click slot then you are basically blocking the UI event loop which means that UI doesn't have cycles to react to your changes. If you want to isolate UI from background action so it will properly react even that you are doing heavy lifting in the background and you should consider using QRunnable or QTread to offload the work away from UI thread.
I am writing an application in qt. This application will have many dialogs. My question is: what is the strategy with dialog handling? Should I create them in the constructor of the main window or shouold they be created when the user click on buttons (that is when the user need it). Should they be destroyed or they are automatically destroyed?
There is no hard rule to this. Generally dialogs are small and light, and therefore are created when opened and destroyed (usually automatically) when closed. However, if you have a custom dialog that contains very heavy widgets and/or needs to get data from a slow source, then you can create a dialog and only show when it when required.
Should they be destroyed or they are automatically destroyed?
This depends entirely on how you create it. The best I can do is point you to the most informative source.
I need help to understand to use QEvents in QT, this is driving me crazy.
I am writting an application using custom events, but as in QApplication::postEvent function, it's necesary to specify the target object.
As I understand, it's possible to post events to Qt's event loop with
QApplication::postEvent(obj_target, QEvent myevent);
This means that I'm trying to catch "myevent" event in obj_target an do some stuff.
But I need to post events without specify a target object, as QMouseEvent or QKeyEvent do
I mean, when clicking in a QMainWindow with a lot of buttons, how is that I can click
any button and that button is pressed?
What is the target object when the click event is posted?
It's possible to register objects to "listen" for a specific event?
I'm really confused, it's possible to post an event without specifying a target object?
Thank you very much in advance
There is no trivial way to post events "globally", as Dan has said. All of the event dispatching of native events is done by private Qt implementation code.
The important distinction is:
There are native messages/events, delivered by the operating system, usually received by a window-specific event loop.
There are QEvents.
Internally, Qt keeps track of the top-level Widgets (windows, really), so when it receives an event from the OS, it knows which window it should go to - it can match it using the platform window id, for example.
QEvent delivery makes no sense without a receiving object, since sending an event to an object really only means that QObject::event(QEvent*) method is called on that object. It's impossible to call this method without having an object instance!
If you want to synthesize a global key press or mouse click event, then you have to figure out what object the event goes to. Namely:
Identify what top-level window (widget) the event should go to. You can enumerate top level widgets via qApp->topLevelWidgets().
Identify the child widget the event should go to. If it's a keyboard event, then sending the event to currently focused widget via qApp->focusWidget() is sufficient. You need to enumerate the child widgets to find the deepest one in the tree that overlaps the mouse coordinates.
Send the correct QEvent subclass to the widget you've just identified. Events delivered to top-level widgets will be routed to the correct child widget.
When sending mouse events, you also need to synthesize relevant enter and leave events, or you risk leaving the widgets in an invalid state. The application.cpp source file should give you some ideas there.
This doesn't give you access to native graphical items, such as menus on OS X.
Please tell us exactly what you're trying to do. Why do you want to post a broadcast event? Who receives it? Since your own QObject-derived classes will receive those broadcasts, I presume, it's easy enough to use signal-slot mechanism. You'd simply connect(...) those receiver classes to some global broadcaster QObject's signal(s).
For this purpose, I have a specific singleton class which I call GuiSignalHub. It regroups all the application-wide signals.
Objects that want to trigger an application-level action (such as opening context help) just connect their signal to the GuiSignalHub signal. Receivers just connect the GuiSignalHub to their slot.