如何在主窗口中插入表单

问题描述:

我想在主窗口选项卡中显示一个表单.mainWindow 已经创建并填充了空选项卡,Form 也已创建并填充了空组合框、标签等.

I'd like to display a Form into a mainWindow tab. The mainWindow is already created and filled with empty tabs, and the Form is also created and filled with empty comboBox, labels and such.

mainWindow 称为 home,Form listInvoice.它们自己运行良好,但是当我从主页选项卡调用 listInvoice 时,它​​会打开一个新窗口,显示 listInvoice GUI,而不是在选项卡中显示 listInvoice.

The mainWindow is called home and the Form listInvoice. They work well on their own, but when I call listInvoice from the home tab, it opens a new window displaying the listInvoice GUI instead of displaying listInvoice within the tab.

您知道如何从 mainWindow 选项卡中调用表单吗?感谢您的帮助.

Do you know how to call a form from within a mainWindow tab? Thank you for your help.

home.ui 文件(由 QT Designer 创建):

home.ui file (created by QT Designer):

<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>500</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QLabel" name="lDate">
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </item>
    <item row="1" column="0">
     <widget class="QTabWidget" name="tabWidget">
      <property name="tabPosition">
       <enum>QTabWidget::West</enum>
      </property>
      <property name="currentIndex">
       <number>0</number>
      </property>
      <property name="elideMode">
       <enum>Qt::ElideNone</enum>
      </property>
      <widget class="QWidget" name="tabHome">
       <attribute name="title">
        <string>Home</string>
       </attribute>
       <layout class="QGridLayout" name="gridLayout_2"/>
      </widget>
      <widget class="QWidget" name="tabCompanies">
       <attribute name="title">
        <string>Companies</string>
       </attribute>
      </widget>
      <widget class="QWidget" name="tabProjects">
       <attribute name="title">
        <string>Projects</string>
       </attribute>
      </widget>
      <widget class="QWidget" name="tabInvoices">
       <attribute name="title">
        <string>Invoices</string>
       </attribute>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

家庭类:

# Class import
from listInvoice import ListInvoice

# GUI manager 
from PyQt5.QtWidgets import QApplication, QComboBox, QDialog, QDialogButtonBox, QFrame, QLabel, QLineEdit, QMainWindow, QMessageBox, QPushButton, QTabWidget, QVBoxLayout,QWidget
from PyQt5.uic import loadUi

# Other imports
import datetime
import sys


class Home(QMainWindow):
    print("home.py")
    def __init__(self):
        super(Home, self).__init__()
        loadUi("home.ui", self)
        self.setWindowTitle("Home")

        # Display current date
        self.lDate.setText(str(datetime.date.today()))

        # Insert widget into tabs
        self.tabInvoices = ListInvoice()


app = QApplication(sys.argv)
widget = Home()
widget.show()
sys.exit(app.exec_())

listInvoice.ui(由 QT Designer 创建):

The listInvoice.ui (created by QT Designer):

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>735</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="1" column="0">
    <spacer name="horizontalSpacer">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
     <property name="sizeHint" stdset="0">
      <size>
       <width>40</width>
       <height>20</height>
      </size>
     </property>
    </spacer>
   </item>
   <item row="1" column="2">
    <widget class="QPushButton" name="pbSearch">
     <property name="text">
      <string>Search</string>
     </property>
    </widget>
   </item>
   <item row="4" column="0" colspan="3">
    <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>
   <item row="0" column="2">
    <widget class="QPushButton" name="pbAddInvoice">
     <property name="text">
      <string>Add invoice</string>
     </property>
    </widget>
   </item>
   <item row="2" column="0">
    <widget class="QLabel" name="label">
     <property name="text">
      <string>Filter by:</string>
     </property>
    </widget>
   </item>
   <item row="1" column="1">
    <widget class="QLineEdit" name="leSearch"/>
   </item>
   <item row="2" column="1" colspan="2">
    <widget class="QPushButton" name="pbCertified">
     <property name="text">
      <string>To certified</string>
     </property>
     <property name="checkable">
      <bool>true</bool>
     </property>
    </widget>
   </item>
   <item row="3" column="0" colspan="3">
    <widget class="QTableWidget" name="twInvoices"/>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

还有 ListInvoice 类:

And the ListInvoice class:

class ListInvoice(QDialog):
    print("listInvoice.py")
    def __init__(self):
        super(ListInvoice, self).__init__()
        loadUi("listInvoice.ui", self)
        self.setWindowTitle("Invoices")

预期的输出应该是主页选项卡中的 listInvoice.

The expected output should be the listInvoice within the home tab.

你错误地认为通过执行 sef.tabInvoices = ListInvoice() 你正在替换小部件,那么不,变量self.tabInvoices 指向对象,当您重新分配它时,该变量将不再指向初始对象,而是指向另一个对象.

You are wrong to think that by doing sef.tabInvoices = ListInvoice() you are replacing the widget, then no, the variable self.tabInvoices points the object and when you reassign it then that variable will no longer point to the initial object but to another.

考虑到上述情况,至少有两种解决方案:

Considering the above there are at least 2 solutions:

使用布局将 ListInvoice 小部件放置在 tabInvoices 中,它不是被替换而是放置在里面.

Use a layout to place the ListInvoice widget inside the tabInvoices, it is not being replaced but placing inside.

class Home(QMainWindow):
    print("home.py")
    def __init__(self):
        super(Home, self).__init__()
        loadUi("home.ui", self)
        self.setWindowTitle("Home")
        # Display current date
        self.lDate.setText(str(datetime.date.today()))
        # Insert widget into tabs
        self.tabInvoices_w = ListInvoice()  # <---
        lay = QVBoxLayout(self.tabInvoices) # <---
        lay.addWidget(self.tabInvoices_w)   # <---

2.推广小部件

使用 Qt 设计器推广 ListInvoice,有关更多信息,您可以查看以下答案:

2. Promote widget

Promote ListInvoice using Qt Designer, for more information you can review the following answers:

考虑到解决方案是将home.ui改为:

Considering that the solution is to change the home.ui to:

<?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>500</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QLabel" name="lDate">
      <property name="text">
       <string>TextLabel</string>
      </property>
     </widget>
    </item>
    <item row="1" column="0">
     <widget class="QTabWidget" name="tabWidget">
      <property name="tabPosition">
       <enum>QTabWidget::West</enum>
      </property>
      <property name="currentIndex">
       <number>3</number>
      </property>
      <property name="elideMode">
       <enum>Qt::ElideNone</enum>
      </property>
      <widget class="QWidget" name="tabHome">
       <attribute name="title">
        <string>Home</string>
       </attribute>
       <layout class="QGridLayout" name="gridLayout_2"/>
      </widget>
      <widget class="QWidget" name="tabCompanies">
       <attribute name="title">
        <string>Companies</string>
       </attribute>
      </widget>
      <widget class="QWidget" name="tabProjects">
       <attribute name="title">
        <string>Projects</string>
       </attribute>
      </widget>
      <widget class="ListInvoice" name="tabInvoices">
       <attribute name="title">
        <string>Invoices</string>
       </attribute>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <customwidgets>
  <customwidget>
   <class>ListInvoice</class>
   <extends>QWidget</extends>
   <header>listInvoice</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

并删除家庭类中的 self.tabInvoices = ListInvoice() 因为它不是必需的.

And remove self.tabInvoices = ListInvoice() in home class since it is not necessary.