How do you get a QWindow from a widget?



  • I want to set a QQuickView to be a child of my main application. But it takes a QWindow* as a parent, and whilst my QWidget has a window() function, it actually returns a QWidget*. So I have no idea how you actually go about getting the QWindow that the QWidget is on.

    A QWindow is not a QWidget, so I can not dynamic cast.Surely from a QMainWindow I can get the QWindow?

    I must have missed something!



  • Hi,

    In Qt < 5.3 you can use "QWidget::createWindowContainer()":http://qt-project.org/doc/qt-5/qwidget.html#createWindowContainer

    In Qt 5.3 there is a new class "QQuickWidget":http://doc-snapshot.qt-project.org/qt5-release/qquickwidget.html



  • So you HAVE to turn it into a QWidget so that you can parent it? The QWindow classes seem somewhat hamstrung.

    I actually worked out you could get the window like this:
    QGuiApplication* gapp = qApp;
    QWindow* window = gapp->topLevelAt(pos);

    But damn, surely it should be easier than that?



  • Hi,

    read "here":http://www.ics.com/blog/combining-qt-widgets-and-qml-qwidgetcreatewindowcontainer#.U2yXnPl_sbg.

    The example is
    @
    #include <QQuickView>
    #include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), qApp, SLOT(quit()));

    QQuickView *view = new QQuickView();
    QWidget *container = QWidget::createWindowContainer(view, this);
    container->setMinimumSize(200, 200);
    container->setMaximumSize(200, 200);
    container->setFocusPolicy(Qt::TabFocus);
    view->setSource(QUrl("main.qml"));
    ui->verticalLayout->addWidget(container);
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }@



  • Yeh, I know this stuff already - I am using a QQuickView as my tooltip. So on a hover, it does a beautiful preview of the main view. So I WANT it to be a window. I want to make sure that the tooltip appears on the right screen, so I need to get the QScreen that the application is running on:

    @QGuiApplication* gapp = qApp;
    QWindow* window = gapp->topLevelAt(pos);
    if (window != nullptr) {
    setScreen(window->screen());
    }
    @

    I can do this:
    @int scr = QApplication::desktop()->screenNumber(pos); @
    And that returns a screen number.
    If I do
    @QApplication::desktop()->screen(pos); @
    It returns a QWidget and not a QScreen.

    Seems that getting a QScreen for the widget in question is a bit round a bout.


  • Moderators

    [quote author="gemmell" date="1399625296"]So you HAVE to turn it into a QWidget so that you can parent it? The QWindow classes seem somewhat hamstrung.[/quote]Do you have a particular reason for parenting? Or is it just to get the screen?

    [quote]I actually worked out you could get the window like this:
    QGuiApplication* gapp = qApp;
    QWindow* window = gapp->topLevelAt(pos);[/quote]You didn't need the qApp and gapp pointers; topLevelAt() is a static function.

    Anyway, if I've understood correctly, you want your QQuickView to pop up on the same screen as your QMainWindow? Try
    @QScreen* screen = QGuiApplication::focusWindow()->screen()@

    If that's not what you're after, please describe your intended application behaviour in more detail.



  • [quote author="JKSH" date="1399646727"][quote author="gemmell" date="1399625296"]So you HAVE to turn it into a QWidget so that you can parent it? The QWindow classes seem somewhat hamstrung.[/quote]Do you have a particular reason for parenting? Or is it just to get the screen?
    [/quote]
    Just to get the screen. Originally I thought I needed to parent it to the top level window so that I could use those coordinates, but it's just as easy to mapToGlobal - just so long as I pop it up on the correct screen.
    [quote author="JKSH" date="1399646727"]
    [quote]I actually worked out you could get the window like this:
    QGuiApplication* gapp = qApp;
    QWindow* window = gapp->topLevelAt(pos);[/quote]You didn't need the qApp and gapp pointers; topLevelAt() is a static function.

    Anyway, if I've understood correctly, you want your QQuickView to pop up on the same screen as your QMainWindow? Try
    @QScreen* screen = QGuiApplication::focusWindow()->screen()@

    If that's not what you're after, please describe your intended application behaviour in more detail.[/quote]

    Since it's a tooltip I actually have a QPoint so I figured I may as well use the topLevelAt - thanks for the pointer that it was static, didn't notice that. Point taken that if it's a tooltip it shouldn't be showing unless the window is in focus, so I could also use focusWindow(). Ta.



  • "QTBUG 32934":https://bugreports.qt-project.org/browse/QTBUG-32934?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab seems related.

    Its not clear to me when you NEED to contain a QQuickView and what happens if you don't.



  • "QTBUG 32934":https://bugreports.qt-project.org/browse/QTBUG-32934?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab seems related.

    Its not clear to me when you NEED to contain a QQuickView and what happens if you don't.


  • Moderators

    [quote author="bootchk" date="1416694909"]Its not clear to me when you NEED to contain a QQuickView and what happens if you don't.[/quote]Do you mean, "Why you need to call QWidget::createWindowContainer() on QQuickView"?

    QWidget::createWindowContainer() was provided to let us embed a QQuickView inside a QWidget. In Qt 5.1/5.2, you need to use it to embed Qt Quick content in a QWidget. (If you don't call that function, you can't embed -- that's all).

    Starting from Qt 5.3, you never need QWidget::createWindowContainer() anymore. Just use QQuickWidget instead of QQuickView.


  • Moderators

    [quote author="bootchk" date="1416694909"]Its not clear to me when you NEED to contain a QQuickView and what happens if you don't.[/quote]Do you mean, "Why you need to call QWidget::createWindowContainer() on QQuickView"?

    QWidget::createWindowContainer() was provided to let us embed a QQuickView inside a QWidget. In Qt 5.1/5.2, you need to use it to embed Qt Quick content in a QWidget. (If you don't call that function, you can't embed -- that's all).

    Starting from Qt 5.3, you never need QWidget::createWindowContainer() anymore. Just use QQuickWidget instead of QQuickView.



  • Thanks, and I will elaborate my question: what does "embed" do for you?

    Because the OP is not embedding, and yet seems to be displaying QML that is invoked by a QWidget app. So embedding is sufficient but not necessary for displaying QML from a QWidget app. (Although the code to manage the display of the QML part is different, since it is dealing with QWindows instead of QWidgets?)

    It seems that embedding is necessary if you want the QML to be a child of a QWidget, e.g. layed out in. Then embedding gives you the size and position and stacking management (over the QML part) that comes with QWidgets.

    The reason I ask is that I was attempting similar as the OP, to create a QQuickView without embedding it (mine was not a hover but a QML Dialog) and it behaved unpredictably (sometimes visible, other times not.) Its probably just that I don't understand and was not properly managing QWindows. So I took the path of least resistance and embedded it, which worked more as I expected.

    But still not totally as I expected. The QML dialog is embedded (contained) in a QWidget that I parented to the main window, yet it is not transient (on top of) the main window, and is decorated with window manager controls.

    Also, the OP is doing something very simple: QML that displays but doesn't interact with the user. When there is interaction, you need more machinery (interfacing between the QML and C++). Creating the container is only part of the machinery.



  • Thanks, and I will elaborate my question: what does "embed" do for you?

    Because the OP is not embedding, and yet seems to be displaying QML that is invoked by a QWidget app. So embedding is sufficient but not necessary for displaying QML from a QWidget app. (Although the code to manage the display of the QML part is different, since it is dealing with QWindows instead of QWidgets?)

    It seems that embedding is necessary if you want the QML to be a child of a QWidget, e.g. layed out in. Then embedding gives you the size and position and stacking management (over the QML part) that comes with QWidgets.

    The reason I ask is that I was attempting similar as the OP, to create a QQuickView without embedding it (mine was not a hover but a QML Dialog) and it behaved unpredictably (sometimes visible, other times not.) Its probably just that I don't understand and was not properly managing QWindows. So I took the path of least resistance and embedded it, which worked more as I expected.

    But still not totally as I expected. The QML dialog is embedded (contained) in a QWidget that I parented to the main window, yet it is not transient (on top of) the main window, and is decorated with window manager controls.

    Also, the OP is doing something very simple: QML that displays but doesn't interact with the user. When there is interaction, you need more machinery (interfacing between the QML and C++). Creating the container is only part of the machinery.


  • Moderators

    Just to check that I've understood you correctly: By "embed", you mean "pass the QQuickView into QWidget::createWindowContainer()"?

    When I said "embed", I meant "insert into a QWidget layout". I wasn't thinking about making one window transient for another.

    [quote author="bootchk" date="1416753963"]So embedding is sufficient but not necessary for displaying QML from a QWidget app. (Although the code to manage the display of the QML part is different, since it is dealing with QWindows instead of QWidgets?)[/quote]Correct.

    As a side note, I notice you used the phrase "displaying QML from a QWidget app". I think it's better to think of it as a "hybrid app that contains both QML and C++ components" -- their technologies are quite separate, but they can coexist happily in the same app. (There are limitations in interactions between C++ widgets and QML windows though)

    [quote author="bootchk" date="1416753963"]It seems that embedding is necessary if you want the QML to be a child of a QWidget, e.g. layed out in. Then embedding gives you the size and position and stacking management (over the QML part) that comes with QWidgets.[/quote]Correct. That's the reason why QWidget::createWindowContainer() was invented -- to allow a QML GUI component to be placed inside a QWidget layout.

    [quote author="bootchk" date="1416753963"]The reason I ask is that I was attempting similar as the OP, to create a QQuickView without embedding it (mine was not a hover but a QML Dialog) and it behaved unpredictably (sometimes visible, other times not.) Its probably just that I don't understand and was not properly managing QWindows. So I took the path of least resistance and embedded it, which worked more as I expected.[/quote]I'm guessing that you need to understand the difference between Item/Rectangle and Window/Dialog. Also understand the difference between QQuickView and QQmlApplicationEngine. See http://qt-project.org/forums/viewthread/49581/ for a summary.

    Anyway, if you still have questions and want to discuss this further, please start a new thread (and post some code to illustrate what you mean). This is quite a different discussion from the OP (the OP's goal was to find the QScreen associated with a QWidget, that's all).


  • Moderators

    Just to check that I've understood you correctly: By "embed", you mean "pass the QQuickView into QWidget::createWindowContainer()"?

    When I said "embed", I meant "insert into a QWidget layout". I wasn't thinking about making one window transient for another.

    [quote author="bootchk" date="1416753963"]So embedding is sufficient but not necessary for displaying QML from a QWidget app. (Although the code to manage the display of the QML part is different, since it is dealing with QWindows instead of QWidgets?)[/quote]Correct.

    As a side note, I notice you used the phrase "displaying QML from a QWidget app". I think it's better to think of it as a "hybrid app that contains both QML and C++ components" -- their technologies are quite separate, but they can coexist happily in the same app. (There are limitations in interactions between C++ widgets and QML windows though)

    [quote author="bootchk" date="1416753963"]It seems that embedding is necessary if you want the QML to be a child of a QWidget, e.g. layed out in. Then embedding gives you the size and position and stacking management (over the QML part) that comes with QWidgets.[/quote]Correct. That's the reason why QWidget::createWindowContainer() was invented -- to allow a QML GUI component to be placed inside a QWidget layout.

    [quote author="bootchk" date="1416753963"]The reason I ask is that I was attempting similar as the OP, to create a QQuickView without embedding it (mine was not a hover but a QML Dialog) and it behaved unpredictably (sometimes visible, other times not.) Its probably just that I don't understand and was not properly managing QWindows. So I took the path of least resistance and embedded it, which worked more as I expected.[/quote]I'm guessing that you need to understand the difference between Item/Rectangle and Window/Dialog. Also understand the difference between QQuickView and QQmlApplicationEngine. See http://qt-project.org/forums/viewthread/49581/ for a summary.

    Anyway, if you still have questions and want to discuss this further, please start a new thread (and post some code to illustrate what you mean). This is quite a different discussion from the OP (the OP's goal was to find the QScreen associated with a QWidget, that's all).


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.