PyQt5 - 具有相同对象的选项卡

Posted

技术标签:

【中文标题】PyQt5 - 具有相同对象的选项卡【英文标题】:PyQt5 - Tabs having same objects 【发布时间】:2021-10-19 20:44:44 【问题描述】:

所以我不想为任何选项卡使用布局。我将使用 .setGeometry 来放置对象,因为要放置的对象很多:)

问题是:在 Tab1.py 和 Tab2.py 中创建的任何对象都出现在所有选项卡上。

Tab3.py 代码与 Tab2.py 相同(只是一个按钮)

我认为问题出在父/子代码上,但不确定我是否出错了。任何指导将不胜感激。 你也可以忽略一些导入,我只是还没有得到那个代码 :)

MainWindow.py

import os, sys, subprocess, atexit, PyQt5, pyodbc, time, datetime, getpass, csv, xlsxwriter
import Tab1, Tab2, Tab3

from PyQt5.QtWidgets import QApplication, QTabBar, QLayout, QLabel, QLineEdit, QMainWindow, QTabWidget, QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QGroupBox, QRadioButton, QTextEdit, QCheckBox, QInputDialog, QFileDialog, QProgressBar, QTableWidget, QTableWidgetItem
from PyQt5.QtCore import *

class MainWindow(QMainWindow):

    # define main window size and position on screen
    def __init__(MainWindow, parent=None):
        super().__init__()

        MainWindow.left = 50
        MainWindow.top = 50
        MainWindow.width = 720
        MainWindow.height = 600
        MainWindow.setGeometry(MainWindow.left,
                               MainWindow.top,
                               MainWindow.width,
                               MainWindow.height)

        MainWindow.table_widget = MainWindowWidget(MainWindow)
        MainWindow.setCentralWidget(MainWindow.table_widget)

        MainWindowWidget()


class MainWindowWidget(QWidget):

    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)

        # configure layout
        self.layout = QVBoxLayout(self)
        self.setLayout(self.layout)

        # initialize tab screen
        self.tabs = QTabWidget()
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tab3 = QWidget()
        self.layout.addWidget(self.tabs)

        # add tabs
        self.tabs.addTab(self.tab1, "Tab1")
        self.tabs.addTab(self.tab2, "Tab2")
        self.tabs.addTab(self.tab2, "Tab3")

        # create first tab
        Tab1.Tab1.CreateTab1(self)
        Tab2.Tab2.CreateTab2(self)
        Tab3.Tab3.CreateTab3(self)


    def exit_handler(self):
        print('closing application')
        atexit.register(exit_handler(self))


# create main window and show it
if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = MainWindow()
    MainWindow.show()
    sys.exit(app.exec_())

Tab1.py

from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QMainWindow, QTabWidget, QWidget, QPushButton, QHBoxLayout, \
    QVBoxLayout, QGroupBox, QRadioButton, QTextEdit, QCheckBox, QInputDialog, QFileDialog, QProgressBar, QTableWidget, \
    QTableWidgetItem, QComboBox

import MainWindow

class Tab1(QMainWindow):

    def CreateTab1(tab1, parent=None):

        # reference number input box
        tab1.label_input_reference_number = QLabel(tab1)
        tab1.label_input_reference_number.setText('Reference Number')
        tab1.label_input_reference_number.setGeometry(25, 80, 115, 20)

        tab1.input_reference_number = QLineEdit(tab1)
        tab1.input_reference_number.setGeometry(170, 80, 215, 20)

        # add CheckGroupButton
        tab1.Button = QPushButton(tab1)
        tab1.Button.setText("Button")
        tab1.Button.setGeometry(385, 105, 100, 20)

Tab2.py

from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QMainWindow, QTabWidget, QWidget, QPushButton, QHBoxLayout, QGroupBox, QRadioButton, QTextEdit, QCheckBox, QInputDialog, QFileDialog, QProgressBar, QTableWidget, QTableWidgetItem

class Tab2(QMainWindow):

    def CreateTab2(tab2):

        # add button
        tab2.Button = QPushButton(tab2)
        tab2.Button.setText("Another button")
        tab2.Button.setGeometry(300, 585, 100, 20)

【问题讨论】:

"我不想使用布局" 这是一个糟糕的主意,尤其是考虑到您的代码:使用固定几何图形很少是正确的解决方案,因为布局是确保所有小部件都获得他们需要空间以保持 UI 可用。例如,一旦您调整窗口大小并使其小于 400 像素宽,按钮就会变得不可见。为窗口设置一个固定/最小大小对你没有多大帮助,因为你永远知道用户配置:如果用户有非常大的字体作为系统默认值,那么你所有小部件中的文本都会变成部分隐藏。 这不是唯一的问题(不包括蒂姆的回答所指出的问题),因为您似乎低估了 命名 对象的重要性。您将名称 MainWindow 用于 3 个非常不同的事物:类、其方法中的实例引用以及最后创建的实例;这是另一个可怕的想法,迟早会引起问题。然后,您将table_widget 命名为实际上包含 tab 小部件(因此,绝对不是表格)的小部件。您还创建了另一个 MainWindowWidget 实例,这是无用的,因为它没有被引用并得到 -> -> 立即销毁。然后你使用Tab 类的方法,就像它们是静态方法一样,这使得它们的存在毫无用处(并且它们的 QMainWindow 继承毫无意义,因为你可以对基本的 python 对象类做同样的事情)。还要注意widthheight 是所有Qt 小部件的现有动态属性,你不应该用静态值覆盖它们。最后,为了将来参考,请确保您只使用您提供的代码所必需的导入:有 8 个模块(9 个,带有 atexit)和 12 个对您的示例无用的类。 【参考方案1】:

你的问题在这里:

        self.tabs.addTab(self.tab1, "Tab1")
        self.tabs.addTab(self.tab2, "Tab2")
        self.tabs.addTab(self.tab2, "Tab3")

        # create first tab
        Tab1.Tab1.CreateTab1(self)
        Tab2.Tab2.CreateTab2(self)
        Tab3.Tab3.CreateTab3(self)

您的所有选项卡控件都归父级所有。 (另外,你有两次 tab2。)你想要:

        self.tabs.addTab(self.tab1, "Tab1")
        self.tabs.addTab(self.tab2, "Tab2")
        self.tabs.addTab(self.tab3, "Tab3")

        Tab1.Tab1.CreateTab1(tab1)
        Tab2.Tab2.CreateTab2(tab2)
        Tab3.Tab3.CreateTab3(tab3)

但是,这是一种奇怪的方法。你应该从 QWidget 派生 Tab1Tab2Tab3,然后这样做:

        self.tab1 = Tab1.Tab1()
        self.tab2 = Tab2.Tab2()
        self.tab3 = Tab3.Tab3()

这样,你就不需要奇怪的类方法来配置东西了。

【讨论】:

【参考方案2】:

原因如下:您传递给每个CreateTabi(tabi) 函数的tabi 变量每次都是同一个变量; selfMainWindow 中引用。这就是我要做的;而不是将self 传递到调用Tabi.Tabi.CreateTabi(self) 中,而是传递您之前存储的变量self.tabi。这样,单独的对象(不同的 selfMainWindow)正在接收单独的子小部件。

【讨论】:

以上是关于PyQt5 - 具有相同对象的选项卡的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5,将文本添加到选项卡不起作用

PyQt5 QTabWidget:如何在类和同一窗口中包含的选项卡之间切换?

Pyqt5右键单击并在新选项卡中打开

具有单个选项卡形式的多个表

JavaScript;具有相同来源的选项卡/窗口之间的通信[重复]

JavaScript;具有相同来源的选项卡/窗口之间的通信[重复]