example python python-3.x pyqt pyqt5 qcombobox

python - example - pyqt combobox get value



Relleno dinĂ¡mico de QComboBox dependiente de la entrada del usuario PyQt5 (1)

Creé QTableWidget y en las primeras dos columnas inserté comboboxes. La primera columna contiene registros únicos (primeros elementos de la lista de listas). Mi objetivo es hacer que estos cuadros combinados sean completamente dinámicos, es decir, si el usuario selecciona ''Mariposa'' dentro del primer cuadro combinado, el segundo cuadro combinado ofrecerá ''PP'' y ''BR'' para su selección.

Refinar la búsqueda debería funcionar incluso desde el otro lado, es decir, si el usuario selecciona ''KL'' en el segundo cuadro combinado, entonces el primero automáticamente completará ''Juguete''.

Intenté (usando el marco de datos de pandas) filtrar los resultados según la selección del usuario con éxito. Sin embargo, en consecuencia, quería poner estos resultados en el cuadro combinado apropiado (sin éxito).

Luego traté de adoptar la solución publicada en este hilo: ¿Cómo puedo cambiar el contenido de un QComboBox dependiendo de otro QComboBox en PyQt5? e incorporarlo en mi código sin éxito.

A continuación, se muestra el código con secciones comentadas que no funcionan:

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

Creo que no pude conectar la señal de manera adecuada. Gracias por cualquier sugerencia!

Editar:

Traté de ser lo más preciso posible, pero tal vez todavía había un espacio para la incertidumbre.

Aquí hay más información de lo que estoy buscando:

Todas las comboxes se deben establecer en valores en blanco de forma predeterminada. Si el usuario selecciona en combo2 valor en blanco, nada cambia para combo1, si el usuario selecciona PP en combo2, solo Mariposa (y en blanco) aparecerá en combo1, si el usuario selecciona BR en combo2, solo Mariposa y Mochila (y en blanco) aparecerán en combo1 . Lo mismo debe ser válido para combo1: si el usuario selecciona Mariposa en combo1, solo BR y PP (y en blanco) deben aparecer en el combo 2, si elige Mochila en combo1 solo aparecerá BR (y en blanco)

Edición adicional:

Se alcanzó un objetivo previamente establecido (gracias a @eyllanesc). Ahora planeo agregar una tercera columna de cuadros combinados que ofrezcan el cuarto elemento (es decir, lista1 [3]) de la lista1 (columna de descripción del producto dentro de qtablewidget). Para eso el diccionario debe ser cambiado. Después de leer algunas publicaciones ( acceder a un elemento arbitrario en un diccionario en Python ; los diccionarios se ordenan en Python 3.6+ ) sigo sin formar la estructura necesaria (quizás createData esté vacío antes de que se agreguen las entradas dentro de for):

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)


La primera tarea que debe hacerse es crear una estructura de datos que permita manejar los datos de forma simple, en este caso se usa un diccionario que contiene listas:

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] = []

Salida:

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

A continuación, conecte las señales QComboBox de QComboBox , pero también debe pasar el otro QComboBox asociado para que se utilice la función lambda. con el método blockSignals() que se genere un ciclo entre las señales.

class Window(QMainWindow): [...] def Table_of_widgets(self): [...] list1 = [...] self.d = {" ": [" "]} self.d_inverse = {" ": [" "]} def createData(key1, key2, data): if key2 not in data[" "]: data[" "].append(key2) if key1 in data.keys(): if key2 not in data[key1]: data[key1].append(key2) else: data[key1] = [" ", key2] return data for item in list1: item1 = item[0] item2 = item[2] self.d = createData(item1, item2, self.d) self.d_inverse = createData(item2, item1, self.d_inverse) for i in range(rowCount): comboA = QComboBox() comboB = QComboBox() comboA.addItems(self.d.keys()) comboB.addItems(self.d[comboA.currentText()]) self.table.setCellWidget(i, 0, comboA) self.table.setCellWidget(i, 1, comboB) comboA.currentTextChanged.connect(lambda text, row=i: self.onComboACurrentTextChanged(text, row)) comboB.currentTextChanged.connect(lambda text, row=i: self.onComboBCurrentTextChanged(text, row)) def updateCombox(self, combo1, combo2, item1, item2): text = combo1.currentText() combo1.blockSignals(True) combo2.blockSignals(True) combo1.clear() combo2.clear() combo2.addItems(item1[text]) combo2.setCurrentIndex(1 if text != " " else 0) combo1.addItems(item2[combo2.currentText()]) combo1.setCurrentText(text) combo1.blockSignals(False) combo2.blockSignals(False) def onComboACurrentTextChanged(self, text, row): comboA = self.table.cellWidget(row, 0) comboB = self.table.cellWidget(row, 1) self.updateCombox(comboA, comboB, self.d, self.d_inverse) def onComboBCurrentTextChanged(self, text, row): comboA = self.table.cellWidget(row, 0) comboB = self.table.cellWidget(row, 1) self.updateCombox(comboB, comboA, self.d_inverse, self.d)