I created QTableWidget and in first two columns inserted comboboxes. The first column contains unique records (first elements from list of lists). My aim is to make these combo boxes fully dynamic, i.e. if the user selects 'Butterfly' within the first combobox, the second combobox will offer 'PP' and 'BR' for selection.
Refining the search should work even from other side, i.e. if user selects 'KL' in the second combobox, then the first one will automaticaly fill in 'Toy'.
I tried (using pandas dataframe) to filter out the results based upon user selection with success. However, consequently I wanted put these results into appropriate combobox (with no success).
Then I tried to adopt solution posted on this thread: How can I change the contents of one QComboBox depending on another QComboBox in PyQt5? and incorporate it into my code with no success.
Here below is the code with commented sections that do not work:
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_())
I think I failed to connect the signal in a proper way. Thanks for any suggestion!
Edit:
I tried to be as precise as possible but perhaps there still was a space for uncertainty.
Here is further information what I am after:
All comboxes should be set to blank values by default. If user selects in combo2 blank value, nothing changes for combo1, if user selects PP in combo2, only Butterfly (and blank) will appear in combo1, if user selects BR in combo2, only Butterfly and Backpack (and blank) will appear in combo1. The same should be valid for combo1: if user selects Butterfly in combo1, only BR and PP (and blank) should appear in combo 2, if he chooses Backpack in combo1 only BR (and blank) will appear
Further Edit:
Previously stated goal was reached (thanks to @eyllanesc). Now I plan to add third column of comboboxes offering 4th element (i.e. list1[3]) from list1 (product description column within qtablewidget). For that the dictionary must be changed. After reading some posts (Access an arbitrary element in a dictionary in Python; Dictionaries are ordered in Python 3.6+) I still fail to form the structure that is needed (maybe createData is empty before entries are added within for loop):
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)