如何用另一个框架替换框架

时间:2020-07-22 21:14:30

标签: python pyqt5

我有一个需要将一个框架替换为另一个框架的要求。我已经实现了下面的代码,它工作正常,但问题是我在同一文件中进行操作。如果我在一个.py文件中创建frame1,而在另一个.py文件中创建frame2,仍然可以达到相同的结果,就可以吗?

以下解决方案将无济于事,因为它将在单个文件中创建大量代码。

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(434, 362)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.frame = QtWidgets.QFrame(self.centralwidget)
        self.frame.setGeometry(QtCore.QRect(10, 10, 411, 311))
        self.frame.setFrameShape(QtWidgets.QFrame.Box)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")


        self.frame_2 = QtWidgets.QFrame(self.centralwidget)
        self.frame_2.setGeometry(QtCore.QRect(10, 10, 411, 311))
        self.frame_2.setFrameShape(QtWidgets.QFrame.Box)
        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_2.setObjectName("frame_2")


        self.label = QtWidgets.QLabel(self.frame_2)
        self.label.setGeometry(QtCore.QRect(10, 10, 131, 16))
        self.label.setObjectName("label")
    
        self.label_2 = QtWidgets.QLabel(self.frame)
        self.label_2.setGeometry(QtCore.QRect(10, 20, 131, 16))
        self.label_2.setObjectName("label_2")

        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(10, 330, 411, 23))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.changeFrame)
        MainWindow.setCentralWidget(self.centralwidget)

       self.frame.show()
       self.frame_2.hide()
    
       self.retranslateUi(MainWindow)
       QtCore.QMetaObject.connectSlotsByName(MainWindow)

   def retranslateUi(self, MainWindow):
       _translate = QtCore.QCoreApplication.translate
       MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
       self.label.setText(_translate("MainWindow", "Second Frame"))
       self.label_2.setText(_translate("MainWindow", "First Frame"))
       self.pushButton.setText(_translate("MainWindow", "Frame Change"))

   def changeFrame(self):
       self.frame.hide()
       self.frame_2.show()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Frame1.Py

from PyQt5 import QtCore, QtGui, QtWidgets

class Frame1(object):
def setupUi(self, MainWindow):
     MainWindow.setObjectName("MainWindow")
     MainWindow.resize(434, 362)
     MainWindow.setWindowTitle("MainWindow")
     self.centralwidget = QtWidgets.QWidget(MainWindow)
     self.centralwidget.setObjectName("centralwidget")
     self.frame = QtWidgets.QFrame(self.centralwidget)
     self.frame.setGeometry(QtCore.QRect(10, 10, 411, 311))
     self.frame.setFrameShape(QtWidgets.QFrame.Box)
     self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
     self.frame.setObjectName("frame")
     self.label = QtWidgets.QLabel(self.frame_2)
     self.label.setGeometry(QtCore.QRect(10, 10, 131, 16))
     self.label.setObjectName("label")
     self.pushButton.setText("Frame One")
     MainWindow.setCentralWidget(self.centralwidget)
     QtCore.QMetaObject.connectSlotsByName(MainWindow) 

 Frame2.py

 from PyQt5 import QtCore, QtGui, QtWidgets

 class Frame2(object):
 def setupUi(self, MainWindow):
     MainWindow.setObjectName("MainWindow")
     MainWindow.resize(434, 362)
     MainWindow.setWindowTitle("MainWindow")
     self.centralwidget = QtWidgets.QWidget(MainWindow)
     self.centralwidget.setObjectName("centralwidget")
     self.frame = QtWidgets.QFrame(self.centralwidget)
     self.frame.setGeometry(QtCore.QRect(10, 10, 411, 311))
     self.frame.setFrameShape(QtWidgets.QFrame.Box)
     self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
     self.frame.setObjectName("frame")
     self.label = QtWidgets.QLabel(self.frame_2)
     self.label.setGeometry(QtCore.QRect(10, 10, 131, 16))
     self.label.setObjectName("label")  
     self.label.setText("Second Frame")
     MainWindow.setCentralWidget(self.centralwidget)
     QtCore.QMetaObject.connectSlotsByName(MainWindow)


  Main.py

  from PyQt5 import QtCore, QtGui, QtWidgets
  from Frame1 import *
  from Frame2 import *

  class Main(object):
  def setupUi(self, MainWindow):
     MainWindow.setObjectName("MainWindow")
     MainWindow.resize(434, 362)
     self.centralwidget = QtWidgets.QWidget(MainWindow)
     self.centralwidget.setObjectName("centralwidget")

     Frame1.frame.show()
     Frame2.frame.hide() 
     self.pushButton = QtWidgets.QPushButton(self.centralwidget)
     self.pushButton.setGeometry(QtCore.QRect(10, 330, 411, 23))
     self.pushButton.setObjectName("pushButton")
     self.pushButton.clicked.connect(self.changeFrame)
     MainWindow.setCentralWidget(self.centralwidget)
     QtCore.QMetaObject.connectSlotsByName(MainWindow)


    def changeFrame(self):
        Frame1.frame.hide()
        Frame2.frame.show()

    if __name__ == "__main__":
        import sys
         app = QtWidgets.QApplication(sys.argv)
        MainWindow = QtWidgets.QMainWindow()
         ui = Main()
         ui.setupUi(MainWindow)
         MainWindow.show()
         sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

您的问题并不复杂,但是如果您需要进行许多改进:

  • 如果要更改窗口小部件的可见性(而不是替换),则必须使用QStackedLayout或QStackedWidget。

  • 在您的原始示例中,您使用QFrame,但在新代码中,您使用QMainWindow,这令人困惑,因为每个小部件都有一个目标,对于QMainWindow,它是具有预定义结构的窗口。因此,我将从头开始重新创建frame1.py和frame2.py。

  • 由QtDesigner生成的代码不是小部件,因此必须将其他类用作基础(有关更多信息,请参见here

考虑到上述情况,应该基于QFrame创建frame1和frame2的设计:

enter image description here

frame1.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Frame</class>
 <widget class="QFrame" name="Frame">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Frame</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLabel" name="label">
     <property name="text">
      <string>First Frame</string>
     </property>
     <property name="alignment">
      <set>Qt::AlignCenter</set>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

frame2.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Frame</class>
 <widget class="QFrame" name="Frame">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Frame</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QLabel" name="label">
     <property name="text">
      <string>Second Frame</string>
     </property>
     <property name="alignment">
      <set>Qt::AlignCenter</set>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

将.ui转换为.py:

pyuic5 frame1.ui -o frame1_ui.py -x
pyuic5 frame2.ui -o frame2_ui.py -x

创建frame1.py和frame2.py:

frame1.py

from PyQt5 import QtWidgets

from frame1_ui import Ui_Frame


class Frame1(QtWidgets.QFrame, Ui_Frame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)

frame2.py

from PyQt5 import QtWidgets

from frame2_ui import Ui_Frame


class Frame2(QtWidgets.QFrame, Ui_Frame):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)

您必须使用与要显示的QFrame一样多的按钮创建QMainWindow,并建立QStackedWidget:

mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QStackedWidget" name="stackedWidget"/>
    </item>
    <item>
     <layout class="QVBoxLayout" name="verticalLayout">
      <item>
       <widget class="QPushButton" name="btn1">
        <property name="text">
         <string>PushButton</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="btn2">
        <property name="text">
         <string>PushButton</string>
        </property>
       </widget>
      </item>
      <item>
       <spacer name="verticalSpacer">
        <property name="orientation">
         <enum>Qt::Vertical</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>20</width>
          <height>40</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>26</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

从.ui转换为.py:

pyuic5 mainwindow.ui -o mainwindow_ui.py -x

在main.py中执行逻辑:

main.py

from PyQt5 import QtWidgets

from mainwindow_ui import Ui_MainWindow
from frame1 import Frame1
from frame2 import Frame2


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi(self)

        self.frame1 = Frame1()
        self.frame2 = Frame2()

        self.stackedWidget.addWidget(self.frame1)
        self.stackedWidget.addWidget(self.frame2)

        self.btn1.clicked.connect(self.on_clicked1)
        self.btn2.clicked.connect(self.on_clicked2)

    def on_clicked1(self):
        self.stackedWidget.setCurrentIndex(0)

    def on_clicked2(self):
        self.stackedWidget.setCurrentIndex(1)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())