Python 如何更改QQuickView的源

Python 如何更改QQuickView的源,python,pyqt,qml,qquickview,Python,Pyqt,Qml,Qquickview,我正在开发这个游戏,它是用qml和pyqt编写的,但应该分为两个窗口(Launcher+游戏)。在这两个qml文件之间切换的正确方式是什么?我不想使用QmlLoader,因为它不会调整窗口大小,而且需要很多信号!我也在尝试这个变体: view.engine().clearComponentCache() view.setSource(source()) 但它不起作用(qml窗口停止工作…-典型的windows错误,但在pycharm控制台中没有写入错误) 我的代码如下所示: from PyQt

我正在开发这个游戏,它是用qml和pyqt编写的,但应该分为两个窗口(Launcher+游戏)。在这两个qml文件之间切换的正确方式是什么?我不想使用QmlLoader,因为它不会调整窗口大小,而且需要很多信号!我也在尝试这个变体:

view.engine().clearComponentCache()
view.setSource(source())
但它不起作用(qml窗口停止工作…-典型的windows错误,但在pycharm控制台中没有写入错误)

我的代码如下所示:

from PyQt5.QtCore import pyqtProperty, QRectF, QUrl, QObject, pyqtSignal, pyqtSlot, QVariant
from PyQt5.QtGui import QColor, QGuiApplication, QPainter, QPen
from PyQt5.QtQml import qmlRegisterType
from PyQt5.QtQuick import QQuickItem, QQuickPaintedItem, QQuickView
from PyQt5 import QtNetwork as QN
from PyQt5 import QtCore as QC

from multiprocessing import Process
import server as S
import client as C
from time import time, sleep


class Launcher(QQuickItem):
    PORTS = (9998, 9999)
    PORT = 9999
    SIZEOF_UINT32 = 4

    changeUI = pyqtSignal()
    changeName= pyqtSignal(int, str)
    connection= pyqtSignal(int, bool)
    connected= pyqtSignal(QVariant)


    @pyqtSlot(name="startGame")
    def start_game(self):
        #app.exit()
        startGame()
        print ("startGame")

    @pyqtProperty(str)
    def name(self):
        print ("return name")
        return self._name

    @name.setter
    def name(self, n):
        print ("set name")
        self._name= n


    @pyqtSlot(name= "terminate")
    def terminate_server(self):
        if not self.server: return
        self.server.terminate()     #Bye
        self.server.join()
        #self.bstopServer.setEnabled(False)
        #self.bserver.setEnabled(True)
        self.server = None

    @pyqtSlot()
    def _quit(self):
        if self.server:
            self.server.terminate()     #Bye
            self.server.join()
        app.exit()

    @pyqtSlot()
    def back(self):
        self.client.disconnect()


    def __init__(self, parent=None):
        super(Launcher, self).__init__(parent)

        self.socket= QN.QTcpSocket()        #Yeah, the game will be over internet
        self.server = None
        self.client = None                  #client is a QObject

        self._turnedOn = False
        self._players = 1
        self._name = "YourName"


class Game(QQuickItem):
    def __init__(self, parent= None):
        super(Game, self).__init__(parent)

        self.client = True      #I should get the client from the launcher, but I don´t know how


def startGame():
    view.engine().clearComponentCache()
    view.setResizeMode(QQuickView.SizeViewToRootObject)
    view.showFullScreen()
    view.setSource(
            QUrl.fromLocalFile(
                    os.path.join(os.path.dirname(__file__),'Game.qml')))
    view.show()
    #app.exec_()

def startLauncher():
    view.engine().clearComponentCache()
    view.setResizeMode(QQuickView.SizeViewToRootObject)
    view.setSource(
            QUrl.fromLocalFile(
                    os.path.join(os.path.dirname(__file__),'Launcher.qml')))


    view.show()

    app.exec_()

if __name__ == '__main__':
    import os
    import sys

    app = QGuiApplication(sys.argv)

    qmlRegisterType(Launcher, "ParanoiaLauncher", 1, 0, "App")
    qmlRegisterType(Game, "ParanoiaGame", 1, 0, "App")

    view = QQuickView()

    startLauncher()

正如你可能看到的,我的结构有点混乱,因为我是第一次做这种切换行为,所以我真的不知道,应该如何做对。。。欢迎大家提出宝贵意见!:)

同一时间,我不得不面对同样的问题。相反,我使用相同的
QQuickView
反复加载相同的组件,我在QML中创建了一个组件作为内容容器,并将所需的组件作为它的子组件加载。每次设置新组件时,我们都会销毁当前组件并将新组件再次设置为子组件

// ContentFrame.qml
Item{
    width: 800
    height: 600
    Item{
        id: contentContainer
        anchors.fill: parent
        anchors.margins: 4
    }
}
在任何事情之前,请原谅我,但是功能代码是用C++编写的,但是我认为这个概念是可以理解的。我制作了一个流程的缩短版本,我希望它可以移植到python

为了加载ContentFrame组件,我使用了一个从QQuickView(ViewManager)派生的类,该类有一个名为setView的方法。此方法加载一个组件(在您的情况下是启动器或游戏),将其设置为
contentContainer
的子组件,并设置其
锚定。fill
以填充整个父组件

ViewManager::ViewManager() :  QQuickView("ContentFrame.qml")
{
    // More ctor code
}

 // Other stuff

void ViewManager::setView(const QString &filename)
{
    QQuickItem *mostTopItem = rootObject(); //QQuickView::rootObject() method
    QQuickItem *contentItem->findChild<QQuickItem*>("contentContainer");
    if(m_current != NULL)
    {
        m_current->setProperty("visible", false);
    }

    // Call a method to load the component and create an instance of it
    QQuickItem *newItem = createOurComponentFromFile(filename);

    newItem->setProperty("parent", QVariant::fromValue<QObject*>(contentItem));

    // When "delete item" in C++, the object will be destroyed in QQmlEngine
    // in pyqt???
    QQmlEngine::setObjectOwnership(newItem, QQmlEngine::CppOwnership);

    newItem->setProperty("anchors.fill", QVariant::fromValue<QObject*>(contentItem));

    // Cleanup current object
    if(m_current != NULL)
    {
        delete m_current;
    }
    m_current = newItem;
}
ViewManager::ViewManager():QQuickView(“ContentFrame.qml”)
{
//更多ctor代码
}
//其他东西
void ViewManager::setView(常量QString和文件名)
{
QQuickItem*mostTopItem=rootObject();//QQuickView::rootObject()方法
QQuickItem*contentItem->findChild(“contentContainer”);
如果(m_current!=NULL)
{
m_current->setProperty(“可见”,假);
}
//调用一个方法来加载组件并创建其实例
QQuickItem*newItem=createOurComponentFromFile(文件名);
newItem->setProperty(“父”,QVariant::fromValue(contentItem));
//当C++中“删除项”时,对象将在QQmlEngine中被销毁
//在pyqt???
QQmlEngine::setObjectOwnership(newItem,QQmlEngine::CppOwnership);
newItem->setProperty(“anchors.fill”,QVariant::fromValue(contentItem));
//清理当前对象
如果(m_current!=NULL)
{
删除当前m_;
}
m_当前=新项目;
}

有更多的代码,但是ViewManager的核心是这个方法。我在这里不调用
QQmlEngine::clearComponentCache()
,因为我多次加载相同的组件,但在您的情况下,这可能是一个好主意。

谢谢您,这对我帮助很大。