2017-10-17 51 views
1

在這裏,我有我的表窗口小部件,用戶將在稍後補項目:PyQt5:填充組合框與從表中的微件

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) 

這裏是我的其中包含一個組合框對話框窗口:

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) 

那麼,我該如何使用Table Widget中的項目完全填充comboBox_2? 我正在考慮某種循環,但不知道如何實現它。 我已經爲對話框窗口和表格窗口小部件類創建了類。

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) 

的完整代碼(不包括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

你試過我的回答嗎?它已經做到了你想要的。目前,它從*一個*表中填充兩個組合框,但可以很容易地更改爲每個表使用不同的表。另一個答案旨在做一些完全不同的事情,即用組合框填充表格中的所有項目,而不是一列。 – ekhumoro

+0

@ekhumoro感謝您的回答!是的,我做過了。但它沒有爲我第一次解決。但我看到你編輯它,所以我現在也試着嘗試。由於某種原因,第一次組合框未填滿。也許我把它整合錯了。 – akeg

回答

1

一條有效的途徑將數據傳遞到一個QComboBox是使用一個模型,這個QComboBox有方法setModel(),但這種情況下的不便之處在於,你只能從QTableWidget列獲取數據,解決不便的方式是使用代理模式轉換爲表格到一個列表:

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

編輯:

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

你的代碼打開了這兩個窗口,它完美地結合在一起,但是當我試圖將它包含在我的整個項目中時,它不起作用smh – akeg

+0

我添加了完整的代碼,所以你可以更好地理解問題的出處 – akeg

+0

@akeg我有已經糾正它,測試它並告訴我它是否適合你。 – eyllanesc

2

可以set the model在組合框從表插件的型號,然後assign a specific column的組合框使用。這會自動更新組合框,以便在表格小部件的第一列顯示任何項目,無論何時發生更改。排序過濾器可用於刪除任何空的項目。

爲了得到這個工作,你的代碼將需要看起來像這樣:

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)