I was exploring Qt layouts and widget management and have come across the behaviour I can't explain.
I have a base UI with the following hierarchy:
MainWindow(QMainWindow) ->
centralwidget (QWidget),
menubar(QMenuBar),
statusbar(QStatusBar)
Later I add several layouts and widgets to the centralwidget, but, I beleive, it's not important in this context.
Now, if we check MainWindow's children objects and their objectNames we will see the following:
<PyQt5.QtWidgets.QLayout object at 0x00000000089425E8> _layout
<PyQt5.QtWidgets.QWidget object at 0x00000000087C6F78> centralwidget
<PyQt5.QtWidgets.QMenuBar object at 0x0000000008942048> menubar
<PyQt5.QtWidgets.QStatusBar object at 0x00000000089420D8> statusbar
For some reason, a QLayout object _layout appears. But this is not all. It seems to me that this QLayout is not persistent and, occasionally, is being added and removed, for example on resize. I have added an eventFilter for a resize event, and here are the object addresses after several window resizes:
<PyQt5.QtWidgets.QLayout object at 0x0000000008942708> _layout
<PyQt5.QtWidgets.QLayout object at 0x00000000089425E8> _layout
<PyQt5.QtWidgets.QLayout object at 0x0000000008942798> _layout
<PyQt5.QtWidgets.QLayout object at 0x00000000089428B8> _layout
The layout is there, but every time the object is new.
What's going on here? What's the purpose of this QLayout, and why it behaves this way?
The QMainWindow class has a built-in custom layout that manages all the toolbars, menubars, dock-widgets, statusbar and central-widget area:
This layout cannot be removed, or replaced by a different layout. If you try to do that, Qt will complain (or possibly even crash).
The object id shown in the repr doesn't mean much. This is the id of the PyQt wrapper for the layout and not the memory address of the underlying C++ object. The layout is actually a QMainWindowLayout - but that is not a public type, so PyQt can only return a QLayout (which is its base-class). It is likely that PyQt is returning a new wrapper around the same underlying C++ object every time you access it.
Related
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.
I'm new to Qt programming and I am developing a drawing application. I have a class MyWidget which has a member QGraphicsView. MyWidget is a member of another class MainWidget (which has other widgets as well and all of them are in a layout).MainWidget is the central widget of my subclass of QMainWindow.
I have created functions to scale the view with the mouse wheel event and a function to drag the scene around.
The problem is - I want to set the Scene's size to be fixed, and to be 3 times the size of the view, but since the view is managed by a layout in order to take as much space as possible I can't get the view's size?
Any help appreciated.
the size property will give you the current size of your widget:
http://qt-project.org/doc/qt-4.8/qwidget.html#size-prop
Alternatively, you could subclass QGraphicsView and re-implement the resizeEvent:
http://qt-project.org/doc/qt-4.8/qwidget.html#resizeEvent
For a full example, have a look into:
http://qt-project.org/doc/qt-4.8/widgets-scribble.html
You can definitely get the view's size. There are two ways to go about it:
Attach an event filter object to your view: myView->installEventFilter(filterObject). The filterObject's eventFilter method will be invoked for all events reaching your view, including resize events.
Use a custom view class and reimplement resizeEvent. This method gets called each time the widget is resized. Do note that designer allows you to add custom classes without having to write plugins.
I think i'm having a fairly basic Qt problem, but i can't figure it out:
I have a QMainWindow which holds a QStackedWidget. All page widgets in there are seperate classes derived from QWidget.
So:
QMainWindow implements QStacked Window in one class.
All other pages inside the stacked widget are added classes and all have there own .ui filled with buttons and lists trough the Designer.
For navigating to different pages, inside the Mainwindow i have access to: ui.stackedWidget->setCurrentIndex(2);
It seems i don't have access to ui.stackedWidget on another page inside the stacked widget? I have no access to the ui.stackedWidget because Ui is a private member in the mainwindow class. (auto generated by Qt - using VS addon for adding QT4 classes)
I would like to know, how can i jump to another page in the stacked widget, when clicking on a button that belongs to another page inside this widget?
Note:
All pages are added to the StackedWidget in mainWIndow's constructor:
ui.stackedWidget->addWidget(page1Widget);
ui.stackedWidget->addWidget(page2Widget);
// etc..
Example of a button click signal-slot inside page1Widget:
connect(ui.btnViewData, SIGNAL(clicked()), this, SLOT(viewData()));
::viewData()
{
// navigate to another page here.
// note: ui.stackedWidget->setCurrentIndex(3); is not accessible here!
}
I believe that putting your connect() and viewData() functions within your QMainWindow object will solve your problem, since the main window can have access to both the signals emited by the child widgets and the QStackedWidget items.
You might need to write a Ui getter for each of your page, and then do something like
connect(page1Widget->getUi().btnViewData, SIGNAL(clicked()), this, SLOT(viewData)));
hope it helps,
cheers
I made a form using the Qt Designer which has some dockwidgets, these dockwidgets have some children widgets. How I can access the dockwidget and these child widgets in my mainwindow.cpp?
I highly recommend reading the docs for these kinds of things, but to give you a little head start, QDockWidget inherits from QWidget, which inherits from QObject:
https://doc.qt.io/qt-4.8/qobject.html#children
widget->children() would simply tell you the children of this widget. This would be needed if you didn't already know the names of the objects to be accessed directly, or had no reference to them.
Update
When you create objects in Qt Designer, and you run the setupUi(this) that is generated for you, inside of your MainWindow, you will then have access to all of the widgets you had set up as members. You can access them directly as they were named in Qt Designer. Please check out one of the numerous tutorials on getting started with Qt. Here is one that shows you how to make use of your ui file, and access the members from it: http://sector.ynet.sk/qt4-tutorial/my-first-qt-gui-application.html
You can also get a list of all the dockWidgets from the mainwindow with
QList<QDockWidget *> dockWidgets = findChildren<QDockWidget *>();
A similar technique works for getting toolbars etc. so you don't have to manually store a list as you create them
I have a QML file which contains a layout of QML items and now I want one of those items to be a QGLWidget. i.e. I want to render to a specific QML item.
Is anyone aware of how to do this?
The simplest way I suppose it to provide QML a new custom component implemented in C++. I couldn't find anything ready.
You could subclass the QDeclarativeItem and implement your OpenGL code in the paint function after using the QPainter::beginNative() function. After that you can "export" your new custom item to QML this way. This is quite simple and should work, but you'll have to setup the viewport of you QDeclarativeView to be a QGLWidget, something like this:
QDeclarativeView view;
// This is needed because OpenGL viewport doesn't support partial updates.
view.setViewportUpdateMode(QGraphicsView::FullViewportUpdateMode);
view.setViewport(new QGLWidget);
or you'll have to use the opengl graphics system for the entire application.
Another way is using QML/3D.
This thread will give you some other information.