动态QComboBox填充依赖于用户输入PyQt5

时间:2017-10-11 13:37:56

标签: python python-3.x pyqt pyqt5 qcombobox

我创建了QTableWidget并在前两列插入了组合框。第一列包含唯一记录(列表列表中的第一个元素)。我的目标是使这些组合框完全动态,即如果用户选择蝴蝶'在第一个组合框内,第二个组合框将提供PP'和' BR'供选择。

优化搜索甚至可以从其他方面起作用,即如果用户选择“KL'在第二个组合框中,第一个组合将自动填写“玩具”。

我尝试(使用pandas数据帧)根据用户选择成功过滤掉结果。但是,因此我想把这些结果放到合适的组合框中(没有成功)。

然后我尝试采用在此主题上发布的解决方案:How can I change the contents of one QComboBox depending on another QComboBox in PyQt5?并将其合并到我的代码中但没有成功。

下面是带有注释部分的代码:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from pandas import DataFrame

class Window(QMainWindow):

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

    def Table_of_widgets(self):

        rowCount = 20
        columnCount = 9

        self.table = QTableWidget()
        self.table.setColumnCount(columnCount)
        self.table.setRowCount(rowCount)
        self.table.setHorizontalHeaderLabels(['Section', 'Label', 'Product description', 'Picture', 'Product ID', "Amount", "Unit price", "Store", "Total price"])
        self.table.verticalHeader().hide()

        self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(4, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(5, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(6, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(7, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(8, QHeaderView.Stretch)

        self.table.showMaximized()

        list1 = [
        ['Butterfly','16/1/001','PP','Pepito Butterfly','350'],
        ['Butterfly','16/1/002','PP','Brown Butterfly','350'],
        ['Butterfly','16/1/003','PP','Blue Butterfly','350'],
        ['Butterfly','bra01','BR','White Butterfly','500'],
        ['Backpack','bra02','BR','Backpack-blue','1500'],
        ['Backpack','bra03','BR','Backpack-black','1250'],
        ['Toy','klv01','KL','Bear','200'],
        ['Toy','klv02','KL','Fish','500'],
        ['Toy','klv03','KL','Rabbit','400'],
        ['Toy','klv04','KL','Owl','450'],
        ]

        dataset = DataFrame(list1)
        fin = list(dataset[0].drop_duplicates())
        fin.insert(0,'')
        fin2 = list(dataset[2].drop_duplicates())
        fin2.insert(0,'')

        for i in range(rowCount):
            comboA = QComboBox()
            comboA.addItems(fin)
##            comboA.currentTextChanged.connect(self.onCurrentTextChanged)
            self.table.setCellWidget(i,0,comboA)

        for i in range(rowCount):
            comboB = QComboBox()
            comboB.addItems(fin2)         
            self.table.setCellWidget(i,1,comboB)

##    def onCurrentTextChanged(self, text):
##        self.comboB.clear()
##        elements = fin1
##        if isinstance(elements, list):
##            self.comboB.addItems(elements)
##        else:
##            self.comboB.addItem(elements)

if __name__ == "__main__":

    app = QApplication(sys.argv)
    app.setApplicationName('MyWindow')
    main = Window()
    sys.exit(app.exec_())

我认为我未能以正确的方式连接信号。谢谢你的任何建议!

编辑:

我试图尽可能精确,但也许还有一个不确定的空间。

以下是我所追求的更多信息:

默认情况下,所有的计算机都应设置为空值。如果用户在combo2中选择空白值,则combo1没有任何变化,如果用户在combo2中选择PP,则只有Butterfly(和空白)将出现在combo1中,如果用户在combo2中选择BR,则只有Butterfly和Backpack(和空白)将出现在combo1中。同样应该对combo1有效:如果用户在combo1中选择Butterfly,则只有BR和PP(和空白)应出现在组合2中,如果他在组合2中选择Backpack,则只会出现BR(和空白)

进一步编辑:

之前已达成目标(感谢@eyllanesc)。现在我计划从list1(qtablewidget中的产品描述列)添加第三列组合框提供第4个元素(即list1 [3])。为此,必须更改字典。在阅读了一些帖子(Access an arbitrary element in a dictionary in Python; Dictionaries are ordered in Python 3.6+)之后,我仍然无法形成所需的结构(在for循环中添加条目之前,createData可能为空):

d = {" ": [[" "], [" "]]}
d_inverse = {" ": [[" "], [" "]]}

def createData(key1, key2, key3, data):
    if key2 not in data[[" "], [" "]][0]:
        data[[" "], [" "]][0].append(key2)
        if key3 not in data[[" "], [" "]][1]:
            data[[" "], [" "]][1].append(key3)
    if key1 in data.keys():
        if key2 not in data[key1]:
            data[key1].append(key2)
            if key3 not in data[key1]:
                data[key1].append(key3)
    else:
        data[key1] = [" ", key2, key3]
    return data

for item in template:
    item1 = item[0]
    item2 = item[3]
    item3 = item[2]
    d = createData(item1, item2, item3, d)
    d_inverse = createData(item3, item2, item1, d_inverse)

1 个答案:

答案 0 :(得分:1)

必须完成的第一项任务是创建一个允许处理简单形式数据的数据结构,在这种情况下,使用包含列表的字典:

self.d = {" ": []}

for item in list1:
    combo1 = item[0]
    combo2 = item[2]
    if combo2 not in self.d[" "]:
        self.d[" "].append(combo2)

    if combo1 in self.d.keys():
        if combo2 not in self.d[combo1]:
            self.d[combo1].append(combo2)
    else:
        self.d[combo1] = []

输出:

{ 
   ' '         : ['PP', 'BR', 'KL'], 
   'Butterfly' : ['PP', 'BR'], 
   'Backpack'  : ['BR'], 
   'Toy'       : ['KL'] 
}

然后连接currentTextChanged的{​​{1}}信号,但是您还必须传递其他关联的QComboBox,因为使用了lambda函数。使用QComboBox方法阻止在信号之间生成循环。

blockSignals()