简体   繁体   中英

QQuickView shows an empty window when calling show

I am still trying to learn coding with QML + c++, so the very nature of this code snippet might sound a little bit unpractical. I am trying to write a class that inherits from QQuickView and loads a qml file. Here is my header file:

#ifndef FORMLOGIN_H
#define FORMLOGIN_H

#include <QQuickView>


class FormLogin:public QQuickView
{
public:
    FormLogin();
public slots:
    void myHide();
};

and here is its implementation:

#include "formlogin.h"
#include<QCoreApplication>
#include<QQmlEngine>
FormLogin::FormLogin()
{
    this->setSource(QUrl("qrc:/main.qml"));
    QObject::connect(this->engine(),&QQmlEngine::quit,&QCoreApplication::quit);

}
#include "iostream"
using namespace std;
void FormLogin::myHide(){
    cout<<"called"<<endl;
    if(this->isVisible()){
        this->hide();
    }else{
        this->show();
    }
}

and this is my main.cpp :

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include"formlogin.h"
#include<iostream>
#include<QTimer>
using namespace std;
FormLogin *formLogin;
QTimer *myTimer;
int main(int argc, char *argv[])
{
    //QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    
    formLogin=new FormLogin();
    myTimer=new QTimer();
    myTimer->start(3000);
    QObject::connect(myTimer,&QTimer::timeout,formLogin,&FormLogin::myHide);
    
    return app.exec();
}

And my main.qml looks like this:

import QtQuick 2.0
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtGraphicalEffects 1.0
Window {
    Rectangle{
        anchors.fill: parent
        color: "lightblue"
    }   

    title: qsTr("Title")
    width: 450; height: 550
    visible: true
}

Now, as you can realize from the code it has a QTimer that is connected to myHide and it shows and hides my login form. Here is what happens when I run my application:

  1. It opens the QML form that I have designed in main.qml ;
  2. it opens an empty window 3 seconds later;
  3. it hides the empty window after 3 seconds and it keeps going on that way.

My personal expectation was that it shouldn't show my QML form at first and it should wait until the emission of the timer's timeout signal. Yet, it shows the right QML window at first then it starts to show that strange empty window every time this->show gets called. And now it's time for my questions:

  1. Why does it show my QML window without "formLogin->show()"?
  2. What is this empty window?
  3. Why can't I hide my main window?

Explanation

The problem is caused because QQuickView expects an Item as root, not a Window.

The problem is because QQuickView expects an element as root, not a window. Your program does the following:

  1. When you start the window that is visible is the QML
  2. Then the QQuickView window appears
  3. And after it hides the QQuickView and passes step 2.

Steps 1 and 2 answer your question 1 and 2 respectively. In the case of question 3 the answer is that you are only hiding the second window.

This is pointed out in the QQmlApplicationEngine docs :

Unlike QQuickView, QQmlApplicationEngine does not automatically create a root window. If you are using visual items from Qt Quick, you will need to place them inside of a Window.

Solution

So there are 2 options:

  • Or replace Window with Item:

     import QtQuick 2.0 Rectangle{ anchors.fill: parent color: "lightblue" }
     #include "formlogin.h" #include<QCoreApplication> #include<QQmlEngine> #include <iostream> FormLogin::FormLogin() { setSource(QUrl("qrc:/main.qml")); connect(engine(), &QQmlEngine::quit, &QCoreApplication::quit); setTitle("Title"); resize(450, 550); } void FormLogin::myHide(){ std::cout << "called" << std::endl; setVisible(;isVisible()); }
     #include <QGuiApplication> #include <QTimer> #include "formlogin.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); FormLogin formLogin; QTimer myTimer; myTimer.start(3000); QObject::connect(&myTimer, &QTimer::timeout, &formLogin, &FormLogin::myHide); return app.exec(); }
  • Or use QQmlApplicationEngine instead of QQuickView

Plus:

If you want to modify the window from QML then you have 2 options:

  1. Or implement the logic in a C++ slot and invoke it from QML.

  2. Or export the window to QML using setContextProperty

     FormLogin::FormLogin() { rootContext()->setContextProperty("window", this); setSource(QUrl("qrc:/main.qml")); connect(this->engine(),&QQmlEngine::quit,&QCoreApplication::quit); setTitle("Title"); resize(450, 550); }
     import QtQuick 2.0 Rectangle{ id: root anchors.fill: parent color: "lightblue" Component.onCompleted: { window.flags = (window.flags | Qt.CustomizeWindowHint | Qt.FramelessWindowHint) & ~Qt.WindowTitleHint // window.showMaximized() } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM