#python #pyqt5
#python #pyqt5
Вопрос:
У меня есть два класса пользовательского интерфейса в отдельных файлах .py, и я собираюсь переключать страницы с помощью файла py контроллера и работает должным образом. Вот мой первый пользовательский интерфейс, который я вызвал main.py
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
position = 3
class Ui_MainWindow(QObject):
settingSignal = pyqtSignal()
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.frame = QFrame(self.centralwidget)
self.frame.setObjectName(u"frame")
self.frame.setGeometry(QRect(0, 0, 1920, 1080))
self.frame.setStyleSheet(u"background-color: rgb(255, 255, 255);")
self.frame.setFrameShape(QFrame.StyledPanel)
self.frame.setFrameShadow(QFrame.Raised)
self.optical = QLabel(self.frame)
self.upgrade = QLabel(self.frame)
self.menu = QLabel(self.frame)
self.calibration = QLabel(self.frame)
self.media = QLabel(self.frame)
MainWindow.setCentralWidget(self.centralwidget)
self.imageChange(position)
QMetaObject.connectSlotsByName(MainWindow)
def imageChange(self, Pos):
self.menu.setGeometry(QRect(160, 410, 200, 200))
self.upgrade.setGeometry(QRect(510, 410, 200, 200))
self.optical.setGeometry(QRect(860, 410, 200, 200))
self.calibration.setGeometry(QRect(1210, 410, 200, 200))
self.media.setGeometry(QRect(1520, 410, 200, 200))
self.optical.setStyleSheet(u"background-color: rgb(0, 0, 0);")
self.calibration.setStyleSheet(u"background-color: rgb(0, 0, 0);")
self.menu.setStyleSheet(u"background-color: rgb(0, 0, 0);")
self.media.setStyleSheet(u"background-color: rgb(0, 0, 0);")
self.upgrade.setStyleSheet(u"background-color: rgb(0, 0, 0);")
if Pos == 1:
self.menu.setGeometry(QRect(110, 360, 300, 300))
self.menu.setStyleSheet(u"background-color: rgb(255, 0, 255);")
elif Pos == 2:
self.upgrade.setGeometry(QRect(460, 360, 300, 300))
self.upgrade.setStyleSheet(u"background-color: rgb(255, 0, 255);")
elif Pos == 3:
self.optical.setGeometry(QRect(810, 360, 300, 300))
self.optical.setStyleSheet(u"background-color: rgb(255, 0, 255);")
elif Pos == 4:
self.calibration.setGeometry(QRect(1160, 360, 300, 300))
self.calibration.setStyleSheet(u"background-color: rgb(255, 0, 255);")
elif Pos == 5:
self.media.setGeometry(QRect(1470, 360, 300, 300))
self.media.setStyleSheet(u"background-color: rgb(255, 0, 255);")
def Control(self, key):
global position
if key == "LEFT":
if position > 1:
position -= 1
else:
position = 1
self.imageChange(position)
elif key == "RIGHT":
if position < 5:
position = 1
else:
position = 5
self.imageChange(position)
elif key == "OK":
if position == 1:
self.settingSignal.emit()
И второй файл пользовательского интерфейса, который я вызвал setting.py
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
class Ui_SettingWindow(QObject):
mainSignal = pyqtSignal()
def setupUi(self, SettingWindow):
if not SettingWindow.objectName():
SettingWindow.setObjectName(u"MenuWindow")
self.centralwidget = QWidget(SettingWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.frame = QFrame(self.centralwidget)
self.frame.setObjectName(u"frame")
self.frame.setGeometry(QRect(0, 0, 1920, 1080))
self.frame.setStyleSheet(u"background-color: rgb(255, 0, 255);")
self.frame.setFrameShape(QFrame.StyledPanel)
self.frame.setFrameShadow(QFrame.Raised)
SettingWindow.setCentralWidget(self.centralwidget)
QMetaObject.connectSlotsByName(SettingWindow)
def Control(self, key):
global position
if key == "BACK":
self.mainSignal.emit()
Я собираюсь переключаться между пользовательскими интерфейсами с помощью Controller.py
import sys
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow
from ui import main, setting
PageIsNow = "main"
RemoteKey = ""
class InitWindow(QMainWindow):
keyPressed = QtCore.pyqtSignal(QtCore.QEvent)
def __init__(self, parent=None):
super(InitWindow, self).__init__(parent)
self.Ui_Main = main.Ui_MainWindow()
self.uiSetting = setting.Ui_SettingWindow()
self.startUIWindow()
self.keyPressed.connect(self.on_key)
def startSetting(self):
global PageIsNow
self.uiSetting.setupUi(self)
PageIsNow = "setting"
self.uiSetting.mainSignal.connect(self.startUIWindow)
self.show()
def startUIWindow(self):
global PageIsNow
self.Ui_Main.setupUi(self)
PageIsNow = "main"
self.Ui_Main.settingSignal.connect(self.startSetting)
self.show()
def keyPressEvent(self, event):
super(InitWindow, self).keyPressEvent(event)
self.keyPressed.emit(event)
def on_key(self, event):
global PageIsNow, RemoteKey
if event.key() == QtCore.Qt.Key_Left:
RemoteKey = "LEFT"
elif event.key() == QtCore.Qt.Key_Right:
RemoteKey = "RIGHT"
elif event.key() == QtCore.Qt.Key_Up:
RemoteKey = "UP"
elif event.key() == QtCore.Qt.Key_Down:
RemoteKey = "DOWN"
elif event.key() == QtCore.Qt.Key_Return:
RemoteKey = "OK"
elif event.key() == QtCore.Qt.Key_Backspace:
RemoteKey = "BACK"
else:
RemoteKey = ""
self.OpenPage()
def OpenPage(self):
global PageIsNow, RemoteKey
if PageIsNow == "setting":
self.uiSetting.Control(RemoteKey)
elif PageIsNow == "main":
self.Ui_Main.Control(RemoteKey)
else:
RemoteKey = ""
if __name__ == '__main__':
app = QApplication(sys.argv)
w = InitWindow()
w.showFullScreen()
sys.exit(app.exec_())
Код прост и выполняется без ошибок, а стратегия проста, прослушиватель клавиатуры находится в контроллере при нажатии клавиши, открывает метод управления в main.py или установка.триггеры py и pyqtSignal предназначены для открытия другого пользовательского интерфейса с помощью контроллера. Моя проблема в том, что когда я переключаюсь между пользовательскими интерфейсами несколько раз, скорость работы программы значительно снижается. Есть ли какие-либо идеи для решения этой проблемы.
Ответ №1:
Причина замедления пользовательского интерфейса заключается в том, что вы подключаете self.uiSetting.mainSignal
и self.Ui_Main.settingSignal
каждый раз, когда запускаете соответствующие функции, что вызывает «частичную рекурсию».
В результате функции, связанные с этими окнами, вызываются каждый раз, когда сигнал был подключен, включая само соединение:
startUIWindow
вызывается, который подключаетсяUi_Main.settingSignal
- при
settingSignal
отправке он вызываетstartSetting
, который делает обратное - при
mainSignal
отправке он вызываетstartUIWindow
, который также снова подключает сигнал settingSignal
startSettings
при повторном запуске он будет вызываться дважды, что приведет к повторному подключению дваждыmainSignal
- при
mainSignal
отправке он будет вызыватьсяstartUIWindow
три раза, что приведет к повторному подключению ещеsettingsSignal
три раза и т. Д…
Как вы можете видеть, это явно не очень хороший подход.
Единственное, что я могу предложить вам для этого конкретного случая, это добавить простую переменную bool, чтобы запомнить, было ли уже установлено соединение:
class InitWindow(QMainWindow):
keyPressed = pyqtSignal(QEvent)
def __init__(self, parent=None):
super(InitWindow, self).__init__(parent)
self.mainConnected = self.settingsConnected = False
self.Ui_Main = Ui_MainWindow()
self.uiSetting = Ui_SettingWindow()
self.startUIWindow()
self.keyPressed.connect(self.on_key)
def startSetting(self):
# ...
if not self.settingsConnected:
self.settingsConnected = True
self.uiSetting.mainSignal.connect(self.startUIWindow)
def startUIWindow(self):
# ...
if not self.mainConnected:
self.mainConnected = True
self.Ui_Main.settingSignal.connect(self.startSetting)
Но я должен быть откровенным: это всего лишь основная проблема с вашим кодом, поскольку на самом деле существует множество других проблем, в том числе:
- глобальных файлов следует избегать, черт возьми;
- строки не должны использоваться для сравнения переменных;
- создание сигнала для ключевых событий, который просто вызывает функцию, которая принимает событие (и это также следующая функция), совершенно бесполезно; вы либо интегрируете другую функцию внутри
keyPressEvent
, либо просто вызываете ее оттуда; - нет никакой пользы в непрерывном вызове
setupUi
каждый раз, когда окно перемещается - попытка имитировать вывод
pyuic
не очень хорошая идея; Я вижу, что вы пытались обойти некоторые проблемы, связанные с этим подходом, путем наследования от QObject, но это не имеет ни смысла, ни пользы; чтобы правильно использовать эти файлы, следуйте официальным рекомендациям по использованию Designer или просто создайте свои интерфейсыс подклассами QWidget (или QMainWindow, в вашем случае); кроме того, многие вызовы, которые вы «унаследовали» от pyuic, совершенно бесполезны для вашего случая (самое главное:setObjectName()
,QMetaObject.connectSlotsByName
); - не используйте глобальные переменные, если вы действительно не знаете точно, как их использовать и когда они вам действительно нужны, а если вы знаете, как их использовать и когда они вам действительно нужны, вы, вероятно, вообще не будете их использовать;