首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在关闭另一个窗口后重新打开窗口?

如何在关闭另一个窗口后重新打开窗口?
EN

Stack Overflow用户
提问于 2019-11-24 13:36:11
回答 1查看 458关注 0票数 0

我从事基于qml的应用程序。

环境:

64bit

  • Python3.7

  • PyQt5

  • Qt 10
  • 5.13.1
  • 构建和运行:桌面QT5.13.1 MSVC2015 64位

我希望有以下行为:

  • 最初显示的是Login窗口。获得访问令牌后,
  • 将关闭登录页,并打开常规窗口。
  • 在关闭普通窗口登录窗口后再次打开。关闭登录窗口后的
  • (字面意思是,如果在关闭登录窗口后没有访问令牌),我的程序就完成了。

现在,在关闭没有访问令牌的登录窗口(login.res_token ==“”)后,我遇到了以下问题:

代码语言:javascript
复制
The program has unexpectedly finished.
The process was ended forcefully.
...\Python\Python37\python.exe crashed.

一段main.py:

代码语言:javascript
复制
def init_app():
    app_login = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    manager = ComponentCacheManager(engine)
    context = engine.rootContext()
    context.setContextProperty("componentCache", manager)

    current_path = os.path.abspath(os.path.dirname(__file__))
    qml_file = os.path.join(current_path, 'ui/LoginPage.qml')
    engine.load(qml_file)

    login = Login()
    engine.rootContext().setContextProperty("login", login)

    win = engine.rootObjects()[0]

    win.show()

    app_login.exec_()

    if(login.res_token != ""):
        main_app = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()

        manager = ComponentCacheManager(engine)
        context = engine.rootContext()
        context.setContextProperty("componentCache", manager)

        current_path = os.path.abspath(os.path.dirname(__file__))
        qml_file = os.path.join(current_path, 'ui/GeneralPage.qml')
        engine.load(qml_file)

        engine.rootContext().setContextProperty("access_token", login.res_token)

        win = engine.rootObjects()[0]

        win.show()
        main_app.exec_()
        init_app()
    else:
        sys.exit()

if __name__ == "__main__":
    init_app()

但是,如果我以另一种方式编写代码(不使用递归),则此操作将正确工作。例如:

代码语言:javascript
复制
if __name__ == "__main__":
    app_login = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    manager = ComponentCacheManager(engine)
    context = engine.rootContext()
    context.setContextProperty("componentCache", manager)

    current_path = os.path.abspath(os.path.dirname(__file__))
    qml_file = os.path.join(current_path, 'ui/LoginPage.qml')
    engine.load(qml_file)

    login = Login()
    engine.rootContext().setContextProperty("login", login)

    win = engine.rootObjects()[0]

    win.show()

    app_login.exec_()

    if(login.res_token != ""):
        main_app = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()

        manager = ComponentCacheManager(engine)
        context = engine.rootContext()
        context.setContextProperty("componentCache", manager)

        current_path = os.path.abspath(os.path.dirname(__file__))
        qml_file = os.path.join(current_path, 'ui/GeneralPage.qml')
        engine.load(qml_file)

        engine.rootContext().setContextProperty("access_token", login.res_token)

        win = engine.rootObjects()[0]

        win.show()
        main_app.exec_()
    else:
        sys.exit()

但在这里我不会在关闭普通窗口后重新打开登录窗口。

如果编写类似的内容,程序会在关闭General窗口后崩溃,其错误与此相同:

代码语言:javascript
复制
if __name__ == "__main__":
    while(True):
        app_login = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()

        manager = ComponentCacheManager(engine)
        context = engine.rootContext()
        context.setContextProperty("componentCache", manager)

        current_path = os.path.abspath(os.path.dirname(__file__))
        qml_file = os.path.join(current_path, 'ui/LoginPage.qml')
        engine.load(qml_file)

        login = Login()
        engine.rootContext().setContextProperty("login", login)

        win = engine.rootObjects()[0]

        win.show()

        app_login.exec_()

        if(login.res_token != ""):
            main_app = QGuiApplication(sys.argv)
            engine = QQmlApplicationEngine()

            manager = ComponentCacheManager(engine)
            context = engine.rootContext()
            context.setContextProperty("componentCache", manager)

            current_path = os.path.abspath(os.path.dirname(__file__))
            qml_file = os.path.join(current_path, 'ui/GeneralPage.qml')
            engine.load(qml_file)

            engine.rootContext().setContextProperty("access_token", login.res_token)

            win = engine.rootObjects()[0]

            win.show()
            main_app.exec_()
        else:
            break
    sys.exit()

怎样才能更好地解决这个问题呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-11-24 17:00:43

逻辑是使用信号通知更改,并在逻辑部分更改页面。

代码语言:javascript
复制
import os

from PyQt5 import QtCore, QtGui, QtQml


class AuthenticationManager(QtCore.QObject):
    login_signal = QtCore.pyqtSignal()
    logout_signal = QtCore.pyqtSignal()

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

    @QtCore.pyqtProperty(str, constant=True)
    def token(self):
        return self._token

    @QtCore.pyqtSlot(str, str, result=bool)
    def login(self, username, password):
        self._token = self._get_token(username, password)
        if self.token:
            self.login_signal.emit()
            return True
        return False

    @QtCore.pyqtSlot()
    def logout(self):
        self._token = ""
        self.logout_signal.emit()

    def _get_token(self, username, password):
        "emulate token"
        if username == "user" and password == "pass":
            return "Token"
        return ""


class WindowManager(QtCore.QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._current_page = ""

        self._engine = QtQml.QQmlApplicationEngine()

        self._authentication = AuthenticationManager()
        self._authentication.login_signal.connect(self.on_login_signal)
        self._authentication.logout_signal.connect(self.on_logout_signal)

        self._engine.rootContext().setContextProperty(
            "authentication", self._authentication
        )

    def init(self):
        self.on_logout_signal()

    def on_login_signal(self):
        self.current_page = "ui/GeneralPage.qml"

    def on_logout_signal(self):
        self.current_page = "ui/LoginPage.qml"

    @property
    def current_page(self):
        return self._current_page

    @current_page.setter
    def current_page(self, page):
        self._current_page = page
        current_dir = os.path.abspath(os.path.dirname(__file__))
        qml_file = os.path.join(current_dir, self.current_page)
        self._engine.load(qml_file)


if __name__ == "__main__":
    import sys

    app = QtGui.QGuiApplication(sys.argv)
    manager = WindowManager()
    manager.init()
    sys.exit(app.exec_())

LoginPage.qml

代码语言:javascript
复制
import QtQuick 2.13
import QtQuick.Controls 2.13 

ApplicationWindow {
    id: root
    visible: true
    width: 640
    height: 480
    title: "Login Page"

    Row{
        TextField {
            id: username
            placeholderText: qsTr("Enter name")
        }
        TextField {
            id: password
            placeholderText: qsTr("Enter password")
            echoMode: TextInput.Password
        }
        Button{
            text: "Login"
            onClicked: {
                if(authentication.login(username.text, password.text)){
                    console.log("token:", authentication.token)
                    root.close()
                }
            }
        }
    }
}

GeneralPage.qml

代码语言:javascript
复制
import QtQuick 2.13
import QtQuick.Controls 2.13 

ApplicationWindow {
    id: root
    visible: true
    width: 640
    height: 480
    title: "General Page"
    Button{
        text: "Logout"
        onClicked: close()
    }
    onClosing: authentication.logout()
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59018205

复制
相关文章

相似问题

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