代码之家  ›  专栏  ›  技术社区  ›  Mohammad Farahi

PyQt5多页面应用程序将变慢

  •  0
  • Mohammad Farahi  · 技术社区  · 4 年前

    我在单独的.py文件中有两个UI类,我将使用控制器py文件切换页面并正常工作。 这是我称之为main.py的第一个UI

    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()
    

    第二个UI文件我称之为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在UI之间切换

    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或settings.py中打开Control方法,pyqtSignal触发器用于使用控制器打开另一个UI。我的问题是:当我多次在UI之间切换时,程序速度会明显变慢。有什么办法解决这个问题吗。

    0 回复  |  直到 4 年前
        1
  •  1
  •   musicamante    4 年前

    ui变慢的原因是您正在连接 self.uiSetting.mainSignal self.Ui_Main.settingSignal 每次运行相应的函数时,都会导致“部分递归”。
    结果是,与这些窗口相关的函数被调用 每一次 信号已连接,包括连接本身:

    1. startUIWindow 被调用,它连接 Ui_Main.settingSignal
    2. 什么时候 settingSignal 发出,它调用 startSetting 反之亦然
    3. 什么时候 mainSignal 发出,它调用 startUI窗口 它也连接 再一次 信号
    4. 什么时候 设置信号 如果再次发出,它将调用 startSettings 两次 ,这将导致 主信号 再次连接 两次
    5. 什么时候 主信号 如果发出,它将调用 startUI窗口 时间,这将再次连接 settingsSignal 其他三次等等。。。

    如您所见,这显然是 一个好的方法。

    我唯一能建议你的就是 具体的 case是添加一个简单的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来规避这种方法带来的一些问题,但它没有任何意义也没有任何好处;要正确使用这些文件,请遵循以下官方指南 using Designer ,或者只使用QWidget(在您的情况下为QMainWindow)子类构建接口;此外,您从pyuic“继承”的许多呼叫对您的情况完全无用(最重要的是: setObjectName() , QMetaObject.connectSlotsByName );
    • 除非你 真正地 确切地知道如何使用它们,什么时候你真的需要它们,如果你知道如何使用,什么时候真正需要它们,你可能会 完全使用它们;