![](/img/trans.png)
[英]Is there a way to reopen a window after closing it using destroy() in tkinter?
[英]How to reopen window after closing other one?
我從事基於 qml 的應用程序。
環境:
我想有以下行為:
現在,在沒有訪問令牌的情況下關閉登錄窗口后出現以下問題(login.res_token == ""):
The program has unexpectedly finished.
The process was ended forcefully.
...\Python\Python37\python.exe crashed.
一段main.py:
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()
但是,如果我以另一種方式進行編碼(不使用遞歸),則此操作可以正常工作。 例如:
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()
但是在這里我沒有在關閉常規窗口后重新打開登錄窗口。
如果我寫這樣的東西,程序會在關閉常規窗口后崩潰並出現相同的錯誤:
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()
如何更好地解決這個問題?
邏輯是使用信號通知更改並在邏輯部分更改頁面
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_())
登錄頁面.qml
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()
}
}
}
}
}
通用頁面.qml
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()
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.