2017-10-17 4 views
1

Hier ich meine Tabelle Widget habe, dass der Benutzer später füllen:PyQt5: Füllen Sie Combo-Boxen mit Elementen aus einem Tisch-Widget

class Ui_Form(object): 
    def setupUi(self, Form): 
     Form.setObjectName("Form") 
     Form.resize(238, 260) 
     self.tableWidget = QtWidgets.QTableWidget(Form) 
     self.tableWidget.setGeometry(QtCore.QRect(10, 10, 221, 241)) 
     self.tableWidget.setObjectName("tableWidget") 
     self.tableWidget.setColumnCount(2) 
     self.tableWidget.setRowCount(7) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(0, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(1, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(2, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(3, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(4, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(5, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setVerticalHeaderItem(6, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setHorizontalHeaderItem(0, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setHorizontalHeaderItem(1, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setItem(0, 0, item) 
     item = QtWidgets.QTableWidgetItem() 
     self.tableWidget.setItem(0, 1, item) 

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

Und hier ist mein Dialogfenster, das eine Combobox enthält:

class Ui_Dialog(object): 
    def setupUi(self, Dialog): 
     Dialog.setObjectName("Dialog") 
     Dialog.resize(281, 176) 
     self.comboBox = QtWidgets.QComboBox(Dialog) 
     self.comboBox.setGeometry(QtCore.QRect(90, 10, 71, 22)) 
     self.comboBox.setObjectName("comboBox") 
     self.comboBox.addItem("") 
     self.comboBox_2 = QtWidgets.QComboBox(Dialog) 
     self.comboBox_2.setGeometry(QtCore.QRect(10, 10, 71, 22)) 
     self.comboBox_2.setObjectName("comboBox_2") 
     self.comboBox_2.addItem("") 
     self.dateTimeEdit = QtWidgets.QDateTimeEdit(Dialog) 
     self.dateTimeEdit.setGeometry(QtCore.QRect(10, 60, 194, 22)) 
     self.dateTimeEdit.setObjectName("dateTimeEdit") 
     self.label_2 = QtWidgets.QLabel(Dialog) 
     self.label_2.setGeometry(QtCore.QRect(10, 40, 91, 16)) 
     self.label_2.setObjectName("label_2") 
     self.lineEdit = QtWidgets.QLineEdit(Dialog) 
     self.lineEdit.setGeometry(QtCore.QRect(150, 110, 113, 20)) 
     self.lineEdit.setObjectName("lineEdit") 
     self.label_3 = QtWidgets.QLabel(Dialog) 
     self.label_3.setGeometry(QtCore.QRect(150, 90, 121, 16)) 
     self.label_3.setObjectName("label_3") 
     self.lineEdit_2 = QtWidgets.QLineEdit(Dialog) 
     self.lineEdit_2.setGeometry(QtCore.QRect(10, 110, 113, 20)) 
     self.lineEdit_2.setObjectName("lineEdit_2") 
     self.label_4 = QtWidgets.QLabel(Dialog) 
     self.label_4.setGeometry(QtCore.QRect(10, 90, 111, 16)) 
     self.label_4.setObjectName("label_4") 
     self.pushButton = QtWidgets.QPushButton(Dialog) 
     self.pushButton.setGeometry(QtCore.QRect(150, 140, 111, 23)) 
     self.pushButton.setObjectName("pushButton") 
     self.pushButton_2 = QtWidgets.QPushButton(Dialog) 
     self.pushButton_2.setGeometry(QtCore.QRect(10, 140, 111, 23)) 
     self.pushButton_2.setObjectName("pushButton_2") 

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

Also, wie fülle ich die ComboBox_2 genau, mit Elementen aus Table Widget? Ich denke über eine Art Zyklus nach, weiß aber nicht, wie ich das realisieren soll. Ich habe bereits Klassen für die Dialogfenster- und Tabellen-Widget-Klasse erstellt.

class Dialog(QtWidgets.QDialog, Ui_Dialog): 
    def __init__(self, parent=None): 
     QtWidgets.QDialog.__init__(self, parent) 
     self.setupUi(self) 
     # cancel 
     self.pushButton_2.clicked.connect(self.reject) 
     # accept 
     self.pushButton.clicked.connect(self.accept) 
     self.dateTimeEdit.setDisplayFormat("d/M/yy hh:mm") 

class Masters(QtWidgets.QDialog,Ui_Form): 
    def __init__(self, parent=None): 
     QtWidgets.QDialog.__init__(self, parent) 
     self.setupUi(self) 

Voll Code (ohne gui)

class Dialog(QtWidgets.QDialog, Ui_Dialog): 
    def __init__(self, parent=None): 
     QtWidgets.QDialog.__init__(self, parent) 
     self.setupUi(self) 
     # cancel 
     self.pushButton_2.clicked.connect(self.reject) 
     # accept 
     self.pushButton.clicked.connect(self.accept) 
     self.dateTimeEdit.setDisplayFormat("d/M/yy hh:mm") 

    def data(self): 
     master = self.comboBox_2.currentText() 
     service = self.comboBox.currentText() 
     name = self.lineEdit_2.text() 
     contact_number = self.lineEdit.text() 
     time = self.dateTimeEdit.time() 
     return master, service, name, contact_number, time 

    class Services(QtWidgets.QDialog,Ui_SForm): 
     def __init__(self, parent=None): 
      QtWidgets.QDialog.__init__(self, parent) 
      self.setupUi(self) 

class Masters(QtWidgets.QDialog,Ui_Form): 
    def __init__(self, parent=None): 
     QtWidgets.QDialog.__init__(self, parent) 
     self.setupUi(self) 

class Table2ListProxyModel(QtCore.QAbstractProxyModel): 
    def __init__(self, parent=None): 
     QtCore.QAbstractProxyModel.__init__(self, parent) 
     self.mapping = [] 

    def setSourceModel(self, sourceModel): 
     sourceModel.dataChanged.connect(lambda: self.fixModel()) 
     QtCore.QAbstractProxyModel.setSourceModel(self, sourceModel) 
     self.fixModel() 

    def mapFromSource(self, sourceIndex): 
     if sourceIndex.isValid(): 
      key = self.mapping.index((sourceIndex.row(), sourceIndex.column())) 
      return self.index(key, 0) 
     return QtCore.QModelIndex() 

    def mapToSource(self, proxyIndex): 
     if proxyIndex.isValid(): 
      r, c = self.mapping[proxyIndex.row()] 
      return self.sourceModel().index(r, c) 
     return QtCore.QModelIndex() 

    def rowCount(self, parent=QtCore.QModelIndex()): 
     return len(self.mapping) 

    def columnCount(self, parent=QtCore.QModelIndex()): 
     return 1 

    def index(self, row, column, parent=QtCore.QModelIndex()): 
     return self.createIndex(row, column) 

    def parent(self, child): 
     return QtCore.QModelIndex() 

    def fixModel(self): 
     self.layoutAboutToBeChanged.emit() 
     self.mapping = [] 
     for c in range(self.sourceModel().columnCount()): 
      for r in range(self.sourceModel().rowCount()): 
       ix = self.sourceModel().index(r, c) 
       data = self.sourceModel().data(ix) 
       if data is not None and data != "": 
        self.mapping.append((r, c)) 
     self.layoutChanged.emit() 

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): 
    def __init__(self, parent=None): 
     QtWidgets.QMainWindow.__init__(self, parent) 
     self.setupUi(self) 
     self.addclient.clicked.connect(self.onAddClient) 
     self.uslugi.clicked.connect(self.AddService) 
     self.mastera.clicked.connect(self.AddMaster) 

    def AddService(self): 
     services = Services(self) 
     services.show() 

    def AddMaster(self): 
     masters = Masters(self) 
     masters.show() 

    def onAddClient(self): 
     dialog = Dialog(self) 
     if dialog.exec_() == QtWidgets.QDialog.Accepted: 
      master, service, name, contact_number, time = dialog.data() 
      row = int(QtCore.QTime(8, 0).secsTo(time)/(30*60)) 
      if row >= 0: 
       for k, text in enumerate([master, service, name, contact_number]): 
       self.tableWidget.setItem(row, k+1, QtWidgets.QTableWidgetItem(text)) 




if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    dialog = Dialog() 
    master = Masters() 
    proxy = Table2ListProxyModel() 
    proxy.setSourceModel(master.tableWidget.model()) 
    dialog.comboBox_2.setModel(proxy) 
    w = MainWindow() 
    w.show() 
    sys.exit(app.exec_()) 
+0

Haben Sie meine Antwort versucht? Es macht schon genau das, was du willst. Im Moment füllt es beide Kombinationsfelder aus * einer * Tabelle, aber das kann leicht geändert werden, um für jede eine andere Tabelle zu verwenden. Die andere Antwort ist entworfen, um etwas ganz anderes zu tun, nämlich die Combo-Box mit * all * den Elementen aus der Tabelle zu füllen, anstatt einer Spalte. – ekhumoro

+0

@ekhumoro Danke für Ihre Antwort! Ja, habe ich. Aber es hat nicht zum ersten Mal für mich geklappt. Aber ich sehe, dass du es editierst, also versuche ich es jetzt auch. Die ersten Comboboxen füllten sich aus irgendeinem Grund nicht. Vielleicht habe ich es falsch eingeordnet. – akeg

Antwort

1

Eine robuste Möglichkeit, Daten zu einem QComboBox passieren wird, ein Modell zu verwenden, denn diese QComboBox die Methode setModel() hat, aber ein Nachteil für diesen Fall ist, dass Sie nur die Daten aus einer Spalte von QTableWidget bekommen können, eine Möglichkeit, diese Unannehmlichkeiten zu lösen ist, einen Proxy verwendet das Modell als Tabelle in eine Liste zu konvertieren:

class Table2ListProxyModel(QAbstractProxyModel): 
    def __init__(self, parent=None): 
     QAbstractProxyModel.__init__(self, parent) 
     self.mapping = [] 

    def setSourceModel(self, sourceModel): 
     sourceModel.dataChanged.connect(lambda: self.fixModel()) 
     QAbstractProxyModel.setSourceModel(self, sourceModel) 
     self.fixModel() 

    def mapFromSource(self, sourceIndex): 
     if sourceIndex.isValid(): 
      key = self.mapping.index((sourceIndex.row(), sourceIndex.column())) 
      return self.index(key, 0) 
     return QModelIndex() 

    def mapToSource(self, proxyIndex): 
     if proxyIndex.isValid(): 
      r, c = self.mapping[proxyIndex.row()] 
      return self.sourceModel().index(r, c) 
     return QModelIndex() 

    def rowCount(self, parent=QModelIndex()): 
     return len(self.mapping) 

    def columnCount(self, parent=QModelIndex()): 
     return 1 

    def index(self, row, column, parent=QModelIndex()): 
     return self.createIndex(row, column) 

    def parent(self, child): 
     return QModelIndex() 

    def fixModel(self): 
     self.layoutAboutToBeChanged.emit() 
     self.mapping = [] 
     for c in range(self.sourceModel().columnCount()): 
      for r in range(self.sourceModel().rowCount()): 
       ix = self.sourceModel().index(r, c) 
       data = self.sourceModel().data(ix) 
       if data is not None and data != "": 
        self.mapping.append((r, c)) 
     self.layoutChanged.emit() 


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): 
    def __init__(self, parent=None): 
     QtWidgets.QMainWindow.__init__(self, parent) 
     self.setupUi(self) 
     self.addclient.clicked.connect(self.onAddClient) 
     self.uslugi.clicked.connect(self.AddService) 
     self.mastera.clicked.connect(self.AddMaster) 
     self.masters = Masters(self) 
     proxy = Table2ListProxyModel() 
     proxy.setSourceModel(self.masters.tableWidget.model()) 
     self.dialog = Dialog(self) 
     self.dialog.comboBox_2.setModel(proxy) 

    def AddMaster(self): 
     self.masters.show() 

    def AddService(self): 
     services = Services(self) 
     services.show() 

    def onAddClient(self): 
     if self.dialog.exec_() == QtWidgets.QDialog.Accepted: 
      master, service, name, contact_number, time = self.dialog.data() 
      row = int(QtCore.QTime(8, 0).secsTo(time)/(30 * 60)) 
      if row >= 0: 
       for k, text in enumerate([master, service, name, contact_number]): 
        self.tableWidget.setItem(row, k + 1, QtWidgets.QTableWidgetItem(text)) 


if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    w = MainWindow() 
    w.show() 
    sys.exit(app.exec_()) 

Edit:

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): 
    def __init__(self, parent=None): 
     QtWidgets.QMainWindow.__init__(self, parent) 
     self.setupUi(self) 
     self.addclient.clicked.connect(self.onAddClient) 
     self.mastera.clicked.connect(self.AddMaster) 
     self.masters = Masters(self) 
     self.services = Services(self) 
     self.dialog = Dialog(self) 

     proxy = QtCore.QSortFilterProxyModel() 
     proxy.setSourceModel(self.masters.tableWidget.model()) 
     proxy.setFilterRegExp(".*\S.*") 
     self.dialog.comboBox_2.setModel(proxy) 

     proxy2 = QtCore.QSortFilterProxyModel() 
     proxy2.setFilterRegExp(".*\S.*") 
     proxy2.setSourceModel(self.services.tableWidget.model()) 
     self.dialog.comboBox.setModel(proxy2) 
     self.dialog.comboBox.setModelColumn(1) 

    def AddService(self): 
     self.services.show() 

    def AddMaster(self): 
     self.masters.show() 

    def onAddClient(self): 
     if self.dialog.exec_() == QtWidgets.QDialog.Accepted: 
      master, service, name, contact_number, time = self.dialog.data() 
      row = int(QtCore.QTime(8, 0).secsTo(time)/(30 * 60)) 
      if row >= 0: 
       for k, text in enumerate([master, service, name, contact_number]): 
        self.tableWidget.setItem(row, k + 1, QtWidgets.QTableWidgetItem(text)) 


if __name__ == '__main__': 
    app = QtWidgets.QApplication(sys.argv) 
    w = MainWindow() 
    w.show() 
    sys.exit(app.exec_()) 
+0

Ihr Code öffnet diese zwei Fenster und es funktioniert perfekt zusammen, aber wenn ich versuchte, es in meinem ganzen Projekt aufzunehmen, funktioniert es nicht smh – akeg

+0

Ich habe den vollständigen Code hinzugefügt, so dass Sie besser verstehen, wo das Problem ist – akeg

+0

@akeg ich habe habe es schon korrigiert, teste es und sag mir, ob es für dich funktioniert. – eyllanesc

2

Sie können set the model auf der Combo-Box zum Modell aus der Tabelle-Widget, und dann assign a specific column für die Combo-Box zu verwenden. Dadurch wird das Kombinationsfeld automatisch aktualisiert, um anzuzeigen, welche Elemente sich in der ersten Spalte des Tabellen-Widgets befinden, wenn es sich ändert. Ein Sortierfilter kann verwendet werden, um leere Objekte zu entfernen.

Um dies zu Arbeit zu erhalten, müssen Sie den Code so etwas wie folgt aussehen:

class Dialog(QtWidgets.QDialog, Ui_Dialog): 
    def __init__(self, parent=None): 
     QtWidgets.QDialog.__init__(self, parent) 
     ... 
     # set the model 
     model = QtCore.QSortFilterProxyModel(self) 
     model.setSourceModel(parent.tableWidget.model()) 
     model.setFilterRegExp('.*\S.*') 
     model.setFilterKeyColumn(1) 
     model.setDynamicSortFilter(True) 
     self.comboBox_2.setModel(model) 
     self.comboBox_2.setModelColumn(1) 
     model.sort(1, QtCore.Qt.AscendingOrder) 
Verwandte Themen