首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何改变QQuickView的来源

如何改变QQuickView的来源
EN

Stack Overflow用户
提问于 2015-01-15 19:49:01
回答 1查看 1.5K关注 0票数 0

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

代码语言:javascript
复制
view.engine().clearComponentCache()
view.setSource(source())

但它不起作用(qml窗口停止工作.-classic窗口错误,但是没有在py魅力控制台中写入错误)

我的代码如下所示:

代码语言:javascript
复制
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()

正如你可能看到的,我的结构有点混乱,因为我第一次做这种转换行为,所以我不知道该怎么做。欢迎每一项建议:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-01-16 08:15:37

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

代码语言:javascript
复制
// ContentFrame.qml
Item{
    width: 800
    height: 600
    Item{
        id: contentContainer
        anchors.fill: parent
        anchors.margins: 4
    }
}

在此之前,请原谅我,但是函数式代码是用C++编写的,但我认为这个概念是不够的。我对这个过程做了一个缩短的版本,我希望它可以移植到python。

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

代码语言:javascript
复制
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的核心是这个方法。我不会在这里调用QQmlEngine::clearComponentCache(),因为我不止一次加载相同的组件,但在您的例子中,这可能是个好主意。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27971799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档