Using Pyside, but a general Qt question:
I am building a Qt app with a controlling QMainWindow. From this window the user can open other QMainWindows (or QDialogs) and from some of those she can open more. The user is intended to think of the first QMainWindow as "the app" and the others as lots of different views on more or less the same data.
So I'd like all the windows to be independently stackable so the user can set up the screen to their own requirements. In particular I want the user to be able to bring the first QMainWindow on top if wanted. But I don't really want each window to have its own task bar entry (though I can live with that). Also I would like them to minimise and restore together, and I would like them all to close when the first main window closes.
If I parent them all on the first mainwindow it works nicely except they stay on top of it which is not what I want.
Instead I have it kind of working by making them all independent with parent = None. Then I register them all with the main window and close them all when it closes. But this makes them a bit too independent - they minimise separately and have their own task bar entry.
Am I missing some obvious fix to this? Is there any easy way (a flag?) to stop the children staying on top of the parent?
Or is there some UI guideline that I am breaking by desiring this?
Or is there a cleaner design somehow? I thought of adding a dummy parent that they could all descend from but maybe that's messy. Would that parent need a visual presence? I wouldn't want that.
Suggestions?
You can have as many QMainWindows as you want, or parentless QWidgets. I think the best way to handle your situation is to create your own pseudo parent-child relationship like this:
In your QMainWindow subclass, store a QList of all the QWidgets you want it to manage. Then, again in your QMainWindow subclass, reimplement methods such as QWidget::closeEvent(), QWidget::hideEvent() (for when the window is minimized), and QWidget::showEvent() (for when it is restored) so that it also closes, hides, or shows all of the widgets in its QList. Make sure to also delete them in the QMainWindow subclass's destructor. Now, whenever you create a sub-window, pass the main window a pointer to it not as a normal QWidget child, but just so that it can be added to the main window's QList of QWidgets to manage. E.g.:
MainWindowSubclass::addPseudoChild(QWidget *pseudoChild)
{
myListOfPseudoChildren.append(pseudoChild);
}
Another alternative that hasn't been mentioned yet is populating a QMdiArea with QMdiSubWindows. It doesn't do exactly what you asked for, but it's a pretty clean design nonetheless.
So I thought I would add what I eventually settled upon. This was particularly inspired by the comments of #leemes (Thanks - good stuff) and a little experimentation of my own.
I used the code attached here DetachTabExample
to develop a "Detachable Tab" widget and tab bar. This allows tabs to be dragged outside the main window when they become independent windows. Then if closed they return to the tab bar.
Then I placed all my content in the QMainWindow but in separate tabs. The users can drag the ones they want out on to the other monitor. Seems to be working fine. There are still some extra windows that I have floating but it has cut down the clutter and clarified the structure.
Related
I have to render a QQuickItem owned by a particular window, into another. Basically MyQQuickItem owned by window1 to be rendered on window2. This switch has to happen in my app repeatedly due to a certain functionality.
I do the following to achieve the goal & the code basically works fine.
Code:
MyQQuickItem * myQuickItem = qmlEngine->rootObjects()[0]->findChild<QQuickItem*>("myquickitemobject");
myQuickItem->setParentItem(window1->contentItem());
// do the required on window2
// then set window1 as parent back again
myQuickItem->setParentItem(window2->contentItem());
Problem:
Above technique functionally works fine. But this requires me to flip flop a few times juggling between setting parent item from window1 to window2 & back again.
Question:
Is there some other way to share MyQQuickItem between the 2 windows? Or is it possible display MyQQuickItem on the both the windows alternatively without having to change the parent hierarchy?
You might use grabToImage() and display the grabbed image on your second window.
This might not be ideal, performance wise. You can find some questions on how to do this on this site. Especially interesting might be this.
I don't know your case, but it might be better, to have two instances of the same component displaying the same data model - possible with input for one disabled.
I am making my first steps with Qt. As an exercise, I am writing a GUI for a many-core processor, and individual cores are shown in a separate window. From this window, there may be several copies, with their independent life, including menus, status line, etc. That is, they are essentially like a QMainWindow, but having a QMoreMainWindow :). Might be any side effect if I use QMainWindow several times?
Nothing prevents you from using any of them for anything. They do have different roles and properties:
QMainWindow is just that: a main window. It has a toolbar, dockwidgets, a menu bar, a status bar, and a central widget. If you don't need all (most of) those things, you clearly don't want a QMainWindow.
QWindow is a barebones object in which is useful if you don't want/need QWidget's functionality.
QDialog is meant to be used for pop-up windows (i.e. "dialogs") like a messagebox or an open file dialog.
QWidget is the basic window or window element. If in doubt, use this.
Reading your question, it seems you want each of those windows to be a QMainWindow. Note I'd still prefer a custom QWidget with only the parts I needed if I were you. Adding a statusbar and menu isn't that much code.
multiple main windows is no issue at all. I also use them in my application and they work fine. You can either have the main windows separately (no parent) or dependant on some main mainwindow, so that they are closed when the main mainwindow is closed.
When your main windows have independent lives and menus, status lines etc., this speaks even more for multiple main windows that probably should all have no parent assigned.
So, yes, your approach seems perfectly fine to me.
I would like to know if anybody knows if it is possible to drag a QDockWidget from one window to another.
I am developping an application that has a lot of windows. Each of these windows has a specific usage. I want to use QDockWidget because of the automatic rescaling when docking a widget in the main window. But I would also like to have the possibility to have a new dock area in a new window so that I can put together all the widgets related one to each other.
Does anyone have a suggestion?
As far as I know, you cannot drag a QDockWidget from one application to another if they are developed separately.
On the other hand, I think that you can reparent a QDockWidget to another QMainWindow, only if it's part of the same application.
...aaaaand you can always try to intercept the drap/drop events and pass information between the two windows with a protocol of your own: define a new mime type for the drag and define the syntax of the data associated to the QDockWidget. Then, implement the code to analyze the data and reconstruct the contents of the QDockWidget in the target window... not an easy task!
Some programs like Maya and Wings3D have a menu, which includes a special link on some menu items on the right side (usually a square) that triggers a different feature. For example, Wings3D might have an item called "Cube", which makes a standard cube. However, if you click on the highlightable/selectable box beside the "Cube" item, it will perform a different operation. I attached an image of the Wings3D example.
Is this an easy way to do this using QMenu and QAction? Should I create a special layout for the QMenu or do I need to subclass it to get more fine-grained control?
You could try using QWidgetAction to accomplish this. But it might take a bit of work to ensure that those actions stay consistent in terms of the look & feel with the typical rendering of QActions across different platforms and styles.
Is there any way to attach two Qt windows together? For example, if window A is the main window and window B is another widget I want to be able to show window B to the side of A and have both windows move together if the windows are dragged.
Not that I am aware of, but you can try following the trail of QMoveEvent. When a given widget is moved void QWidget::moveEvent ( QMoveEvent * event ) is called, and the QMoveEvent contains both old and new pos. Using this information, you can inject a move event in the other widget as well, and make it follow.
Of course, I am speaking of two independent widgets, each one in its own window. If they are contained, you don't need anything but a Layout management (see QLayout and related classes).
I don't work with Qt since a long time, so there could be a better method, but if I had to do it right now, this is the strategy I would use.
Also, I have the feeling that the QMoveEvent will be invoked only at start and end, unless you enable mouse tracking. If the former is the case, you will obtain that the other widget will "teleport" at the end of the move, instead of following smoothly.
You might be after something like this:
http://doc.qt.io/archives/4.6/qt4-mainwindow.html
Window A would be a QMainWindow and window B would be a QDockWidget.