首页 > 解决方案 > PyQt5如何识别和抓取与其他组合框一起使用函数创建的QT组合框的数据

问题描述

我编写了一个脚本,它自动创建一个 QT“对象”,该对象由一个类别标签、一个带有可能属性的 combobox_1、一个按钮和一个用于列出所选属性的所有可用值的 combobox_2 组成。该脚本会根据需要创建尽可能多的这些“对象”。

对于每个“对象”,创建的按钮旨在获取 combobox_1 中的选定属性,并使用此信息从数据库中检索相关值并填充 combobx_2

现在我遇到的问题是,一旦组合框被创建,我就无法弄清楚如何引用它们。对于按钮,我使用 serve 函数来监听任何按钮的点击,这很好,但是我如何引用已经用函数创建的组合框。尽管它们都有不同的 setObjectName,但似乎没有引用该属性的方法,因此当我单击任何按钮时,它们都返回最后一个对象的组合框的值,而不是它们所附加的相关组合框的值.

这是前端脚本:

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(709, 357)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_4 = QtWidgets.QGridLayout()
        self.gridLayout_4.setObjectName("gridLayout_4")
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_4.addItem(spacerItem, 1, 1, 1, 1)
        self.VLayout_0 = QtWidgets.QVBoxLayout()
        self.VLayout_0.setObjectName("VLayout_0")
        self.HLayout_0 = QtWidgets.QHBoxLayout()
        self.HLayout_0.setObjectName("HLayout_0")
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.HLayout_0.addItem(spacerItem1)
        self.CB_L0 = QtWidgets.QComboBox(self.centralwidget)
        self.CB_L0.setObjectName("CB_L0")
        self.HLayout_0.addWidget(self.CB_L0)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
        self.pushButton.setSizePolicy(sizePolicy)
        self.pushButton.setMaximumSize(QtCore.QSize(40, 16777215))
        self.pushButton.setObjectName("pushButton")
        self.HLayout_0.addWidget(self.pushButton)
        spacerItem2 = QtWidgets.QSpacerItem(50, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.HLayout_0.addItem(spacerItem2)
        self.VLayout_0.addLayout(self.HLayout_0)
        spacerItem3 = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        self.VLayout_0.addItem(spacerItem3)
        self.gridLayout_4.addLayout(self.VLayout_0, 1, 0, 1, 1)
        self.PB_create_cb = QtWidgets.QPushButton(self.centralwidget)
        self.PB_create_cb.setObjectName("PB_create_cb")
        self.gridLayout_4.addWidget(self.PB_create_cb, 0, 1, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_4, 0, 0, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 709, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "search"))
        self.PB_create_cb.setText(_translate("MainWindow", "Create dropdown"))


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

这是后端示例(创建两个“对象”):

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QAction, QTableWidget, QTableWidgetItem, QVBoxLayout, QMessageBox, QDialog, QLineEdit, QPushButton, QMenu, QSizePolicy, QLabel,QTreeWidget,QTreeWidgetItem
from PyQt5.QtWidgets import (QApplication, QWidget, QToolTip, QPushButton, QMessageBox)
import sys
from test3 import *


class Run_script(QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):
        super(Run_script, self).__init__(parent)
        self.setupUi(self)
        print("Run script initizalised")

        self.PB_create_cb.clicked.connect(self.click_select)


    def create_V_0_object(self,List_attributes):
        V_list = []
        for i,x in enumerate(List_attributes):
            for k,v in x.items():

                if type(v) == dict:
                    for k1,v1 in v.items():
                        if type(v) == dict:
                            self.HLayout_1 = QtWidgets.QHBoxLayout()
                            self.HLayout_1.setObjectName("H_layout_1")

                            self.VLayout_0 = QtWidgets.QVBoxLayout()
                            self.VLayout_0.setObjectName("V_L2"+k+str(i))
                            self.Attr_label = QtWidgets.QLabel(self.centralwidget)
                            self.Attr_label.setObjectName(k)
                            self.Attr_label.setText(k)
                            self.VLayout_0.addWidget(self.Attr_label)
                            self.attr_list = []
                            for k1,v1 in v.items():

                                self.attr_list.append(k1)
                                print("K1 is "+str(k1))
                            self.comboBox = QtWidgets.QComboBox(self.centralwidget)
                            self.comboBox.setObjectName("CB_"+k)
                            self.comboBox.addItems(self.attr_list)
                            self.comboBox.setToolTip("CB_"+k)
                            self.VLayout_0.addWidget(self.comboBox)
                            self.comboBox1 = QtWidgets.QComboBox(self.centralwidget)
                            self.comboBox1.setObjectName("CB_l2_"+k)
                            self.comboBox1.setToolTip("CB_l2_"+k)
                            self.VLayout_0.addWidget(self.comboBox1)


                            self.pushButton = QtWidgets.QPushButton(self.centralwidget)
                            sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
                            sizePolicy.setHorizontalStretch(0)
                            sizePolicy.setVerticalStretch(0)
                            sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
                            self.pushButton.setSizePolicy(sizePolicy)
                            self.pushButton.setMaximumSize(QtCore.QSize(40, 16777215))
                            PB_name = "PB_"+str(k)
                            self.pushButton.setObjectName(PB_name)
                            self.pushButton.setToolTip("Search  " + str(PB_name))
                            self.pushButton.setText(PB_name)
                            self.pushButton.clicked.connect(self.buttonClicked)
                            self.HLayout_1.addLayout(self.VLayout_0)
                            self.HLayout_1.addWidget(self.pushButton)



                        else:
                            pass
                V_list.append(self.HLayout_1)

        return V_list

    def buttonClicked(self):
        sender = self.sender()
        cat_l_0 = sender.text()

        for i in range(self.VLayout_0.count()):
            name = self.VLayout_0.itemAt(i).widget().objectName()
            print("this is:",name)

    def click_select(self):

        self.selection = [{"Category1":{"Attr1": "test1","Attr2":"test2"}},{"Category2":{"Attr1":"test3","Attr2":"test4"}}]

        self.v = self.create_V_0_object(self.selection)

        self.create_horizontal_display(self.v)

    def deleteItemsOfLayout(self,layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.setParent(None)
                else:
                    self.deleteItemsOfLayout(item.layout())  

    def create_horizontal_display(self,vertical_layout_list):
        self.deleteItemsOfLayout(self.HLayout_0)
        for i,x in enumerate(vertical_layout_list):
            self.HLayout_0.addLayout(x)







if __name__ == '__main__':
    app = QApplication(sys.argv)
    prog = Run_script()
    prog.show()
    sys.exit(app.exec_())

创建对象只需按“创建下拉菜单”按钮

标签: pythonpyqtpyqt5

解决方案


你有很多不好的做法:

  • 在循环中创建的变量通常不会成为类的成员,因为它们是临时变量,所以不要使用它们,因为它们会被覆盖,因此在访问self.VLayout_0时总是会得到最后一个元素。

  • 另一个坏习惯是你想在一个地方做的所有事情,正如你所说的,“对象”除了数据之外都是相似的,所以你应该创建一个构建它的类,正如他们所说:分而治之。

您还有其他错误,但它们是次要的,更正上述您有以下内容:

from PyQt5 import QtCore, QtGui, QtWidgets
from test3 import Ui_MainWindow

class Widget(QtWidgets.QWidget):
    clicked = QtCore.pyqtSignal()
    def __init__(self, text, values, parent=None):
        super(Widget, self).__init__(parent)
        hlay = QtWidgets.QHBoxLayout(self)

        vlay = QtWidgets.QVBoxLayout()
        self.label = QtWidgets.QLabel(text)
        self.combobox_1 = QtWidgets.QComboBox()
        self.combobox_1.addItems(values.keys())
        self.combobox_2 = QtWidgets.QComboBox()
        vlay.addWidget(self.label)
        vlay.addWidget(self.combobox_1)
        vlay.addWidget(self.combobox_2)
        hlay.addLayout(vlay)

        self.button = QtWidgets.QPushButton(text)
        self.button.clicked.connect(self.clicked)
        hlay.addWidget(self.button)
        self.setFixedSize(self.sizeHint())

class Run_script(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Run_script, self).__init__(parent)
        self.setupUi(self)
        print("Run script initizalised")
        self.PB_create_cb.clicked.connect(self.click_select)


    def create_V_0_object(self, attributes):
        v_list = []
        for x in attributes:
            for key, value in x.items():
                w = Widget(key, value)
                w.clicked.connect(self.buttonClicked)
                v_list.append(w)
        return v_list

    def buttonClicked(self):
        w = self.sender()
        print(w.combobox_1.currentText())
        print(w.combobox_2.currentText())
        print(w.label.text())
        print(w.button.text())

    def click_select(self):
        selection = [{"Category1":{"Attr1": "test1","Attr2":"test2"}},{"Category2":{"Attr1": "test3", "Attr2": "test4"}}]
        v = self.create_V_0_object(selection)
        self.create_horizontal_display(v)

    def deleteItemsOfLayout(self,layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.setParent(None)
                else:
                    self.deleteItemsOfLayout(item.layout())  

    def create_horizontal_display(self, vertical_layout_list):
        self.deleteItemsOfLayout(self.HLayout_0)
        for i, x in enumerate(vertical_layout_list):
            self.HLayout_0.addWidget(x)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)
    prog = Run_script()
    prog.show()
    sys.exit(app.exec_())

推荐阅读