Приложение с несколькими страницами будет работать медленнее

#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 каждый раз, когда запускаете соответствующие функции, что вызывает «частичную рекурсию».
В результате функции, связанные с этими окнами, вызываются каждый раз, когда сигнал был подключен, включая само соединение:

  1. startUIWindow вызывается, который подключается Ui_Main.settingSignal
  2. при settingSignal отправке он вызывает startSetting , который делает обратное
  3. при mainSignal отправке он вызывает startUIWindow , который также снова подключает сигнал
  4. settingSignal startSettings при повторном запуске он будет вызываться дважды, что приведет к повторному подключению дважды mainSignal
  5. при 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 );
  • не используйте глобальные переменные, если вы действительно не знаете точно, как их использовать и когда они вам действительно нужны, а если вы знаете, как их использовать и когда они вам действительно нужны, вы, вероятно, вообще не будете их использовать;