I am integrating a single osgQt::GLWidget in a Qframe and using the pattern here: http://trac.osgeo.org/ossim/browser/trunk/ossimPlanetQt/src/gui/ossimPlanetQtMainWindow.cpp to switch between full-screen mode and back. Basically consuming the keystrokes within the widget and setting full screen from there.
I also have an event consumer in osgViewer::Viewer - osgViewer::WindowSizeHandler which handles the viewer size switch.
Is there a better pattern to implement this ?
Basically, what you do (or, what is done in the example) seems fine. (Note that I am assuming that you refer to void ossimPlanetQtMainWindow::on_viewToggleFullScreen_triggered(bool ))
However, in the example, the QGLWidget theGLWidget is reparented between tabWidget and theFullScreenFrame. Under Windows, reparenting a QGLWidget will lead to a recreation of the QGLContext. (see QGLWidget documentation
The workaround suggested by the docs is to wrap the GL widget in a dummy widget (a simple QWidget) and reparent that instead of the GL widget.
In my experience, this works fine.
Related
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 have an application utilizing QWinWidget in a Win32 window. I'd like to add DockWidgets and the associated behaviour to it. There don't seem to be any exposed APIs for adding custom DockAreas, and the latest docs are sparse beyond adding DockWidgets to a QMainWindow. Older docs imply there once was a public QDockArea class.
So far, my best option appears to be adding a neutered QMainWindow (no top-level status, no frame, etc.) to the QWinWidget and going from there (second source).
I was hoping there was a way to add DockAreas to any container, but it doesn't appear that way. As a side note, QWinWidget is used to have window manager control with our custom frame requirement, but if there's a pure QMainWindow/QWidget way to have the same result (with Qt::FramelessWindowHint), I'd be happy to switch over.
As I said in the comments, I've added within my QWinWidget in my Win32 window a QMainWindow field. That is:
class QWinWidget : public QWidget
{
...
QMainWidget* mainWidget;
}
QWinWidget::QWinWidget()
{
mainWidget = new QMainWindow(this);
mainWidget->setWindowFlags(Qt::Widget); //1
}
Note that while the docs and some forum posts (from this post) indicate you need to set window flags explicitly due to the QMainWindow constructor setting Qt::Window, I tested it without the setWindowFlags() line (marked with //1 above) without noticing anything wrong.
So, this gives me the nice QWinWidget window I spent so much time making, inside a frameless Win32 window, with a QMainWindow child and all the features that brings along with it. Docking, menu bar, status bar, etc.
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.
I am trying to implement a custom OpenGL scene (wrapped in a QGLWidget), but still use QT controls (such as slide bars and buttons). I tried to make my main widget a QGLWidget, which has QWidgets as children. The child widgets seem to work (when I click a pulldown menu, its options appear), but the widget fails to draw (I see a white square). I changed the base class of my children widgets from QWidget to QGLWidget, and now QPainter calls work, but QT GUI stuff is still not displaying...
Some claim that a QGLWidget can not have QWidgets as children... I am not sure about that and I'm not willing to give up. By the way, I am using Visualization Library to draw the OpenGL scene, but it is just an OpenGL wrapper...
Any clues where the problem might be? Also, key events stop being processed for some reason when I add subwidgets to the GQLWidget.
Update:
I tried various combinations of widgets and layouts. It seems that the QGLWidget just gets drawn on top of anything. I even tried with raise() to arrange Z-depth of the widgets, to no avail. Is overlayGL() the only way to draw on top of an OpenGL widget?
Update 2
After months of trying, I figured out it is something related to QT. Whenever a QGLWidget is drawn on top of another QGLWidget, the first's background() function is not called. So a button is there and can be clicked, but it's not drawn. My workaround was to draw everything myself using QPainter - that works. What I found curious is, one has to use QPainter::startNativePainting() in order to draw with it. One would expect that they would overload start() in QPainter to call startNativePainting() whenever a QGLWidget is the painting device...
Another (maybe useful) fact is that QPainter calls CHANGE the Opengl context. So if you have another tool in cooperation with QPainter (in my case Visualization Library), chances are that one of them will crash (in my case VL which checks if the context state has been cleared before each frame).
There is a labs example of rendering Qt widgets using opengl it's a little old and I haven't tried it with the improved qglwidget in 4.8
There is also an issue with drawing over the top of a fullscreen QGLwidget - it was supposedly a bug in NVidia's openGL driver. It doesn't seem to have been resolved
https://bugreports.qt-project.org/browse/QTBUG-7556
If I were you I would use the QGLWidget as a viewport for a QGraphicsScene, then you can draw your widgets using a QGraphicsProxyWidget. That way you get a proper OpenGL viewport with the ability to put widgets in and manipulate them easily.
Did u try to call update() explicitly? I find that sometimes QGLWidget update the display stuff kind of slow.
This is an old question, but I recently had quite a bit of trouble with this, and this is what helped me -
Use QML/QT Quick. QML is a javascript-like language that allows you to layout your widget elements on a window and do basic processing on events like mouse clicks. There are a few other cool features, but the one that is most relevant to this question is that you can import qt widgets from C++ code.
So you can make a custom QGLWidget, import it into the QML window, and set the size/position/stick widgets on top of it in whatever you want, very easily. QT's Scenegraph example does a great job explaining this. Scenegraph's code is also included as an example in at least Qt Creator 3.2.1 Open Source (that's the version I have anyway)
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.