简体   繁体   English

QQuickView 在调用 show 时显示一个空的 window

[英]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.我仍在尝试使用 QML + c++ 来学习编码,所以这个代码片段的本质可能听起来有点不切实际。 I am trying to write a class that inherits from QQuickView and loads a qml file.我正在尝试编写一个继承自QQuickView并加载qml文件的 class 。 Here is my header file:这是我的 header 文件:

#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 :这是我的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:我的main.qml看起来像这样:

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.现在,您可以从代码中了解到它有一个连接到myHideQTimer ,它显示和隐藏我的登录表单。 Here is what happens when I run my application:以下是我运行应用程序时发生的情况:

  1. It opens the QML form that I have designed in main.qml ;它打开了我在 main.qml 中设计的main.qml
  2. it opens an empty window 3 seconds later;它会在 3 秒后打开一个空的 window;
  3. it hides the empty window after 3 seconds and it keeps going on that way.它在 3 秒后隐藏了空的 window 并继续这种方式。

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.我个人的期望是它不应该首先显示我的 QML 表格,它应该等到定时器的超时信号发出。 Yet, it shows the right QML window at first then it starts to show that strange empty window every time this->show gets called.然而,它首先显示正确的 QML window 然后它开始显示奇怪的空 window 每次调用this->show时。 And now it's time for my questions:现在是我提问的时候了:

  1. Why does it show my QML window without "formLogin->show()"?为什么它显示我的 QML window 而没有“formLogin->show()”?
  2. What is this empty window?这个空的 window 是什么?
  3. Why can't I hide my main window?为什么我不能隐藏我的主 window?

Explanation解释

The problem is caused because QQuickView expects an Item as root, not a Window.问题是因为 QQuickView 需要一个项目作为根,而不是 Window。

The problem is because QQuickView expects an element as root, not a window.问题是因为 QQuickView 需要一个元素作为根,而不是 window。 Your program does the following:您的程序执行以下操作:

  1. When you start the window that is visible is the QML当您启动 window 时,可见的是 QML
  2. Then the QQuickView window appears然后出现QQuickView window
  3. And after it hides the QQuickView and passes step 2.在它隐藏 QQuickView 并通过第 2 步之后。

Steps 1 and 2 answer your question 1 and 2 respectively.步骤 1 和 2 分别回答您的问题 1 和 2。 In the case of question 3 the answer is that you are only hiding the second window.对于问题 3,答案是您只隐藏了第二个 window。

This is pointed out in the QQmlApplicationEngine docs : QQmlApplicationEngine 文档中指出了这一点:

Unlike QQuickView, QQmlApplicationEngine does not automatically create a root window.与 QQuickView 不同,QQmlApplicationEngine 不会自动创建根 window。 If you are using visual items from Qt Quick, you will need to place them inside of a Window.如果您使用 Qt Quick 中的视觉项目,则需要将它们放置在 Window 内。

Solution解决方案

So there are 2 options:所以有2个选项:

  • Or replace Window with Item:或将 Window 替换为项目:

     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或者使用 QQmlApplicationEngine 代替 QQuickView

Plus:加:

If you want to modify the window from QML then you have 2 options:如果您想从 QML 修改 window,那么您有 2 个选项:

  1. Or implement the logic in a C++ slot and invoke it from QML.或者在 C++ 插槽中实现逻辑并从 QML 调用它。

  2. Or export the window to QML using setContextProperty或使用 setContextProperty 将 window 导出到 QML

     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() } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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