2013-07-12 8 views
5

Próbuję wyświetlić pole kombi w mojej tabeli, dzięki czemu można ustawić wybrany indeks z modelu tabeli, tak jak w przypadku innych komórek w tabeli. Złożyłem to razem z innych przykładów, ale nadal nie mogę zrozumieć, jak działa interakcja, aby ustawić wybrany indeks QComboBox.PyQt - Jak ustawić QComboBox w widoku tabeli przy użyciu QItemDelegate

Jest to najprostszy przykład, jaki mogę wymyślić, aby zademonstrować problem. Czy ktoś może zademonstrować, jak ustawić indeks automatycznie z danych modelu? A także, jak używać sygnału "currentIndexChanged", który wydaje się odpalać niemal nieprzerwanie za każdym razem, gdy zostanie przemalowany? Dzięki.

# The following tells SIP (the system that binds Qt's C++ to Python) 
# to return Python native types rather than QString and QVariant 
import sip 
sip.setapi('QString', 2) 
sip.setapi('QVariant', 2) 


from PyQt4 import QtCore, QtGui 

class TableModel(QtCore.QAbstractTableModel): 
    """ 
    A simple 5x4 table model to demonstrate the delegates 
    """ 
    def rowCount(self, parent=QtCore.QModelIndex()): return 5 
    def columnCount(self, parent=QtCore.QModelIndex()): return 4 

    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if not index.isValid(): return None 
     if not role==QtCore.Qt.DisplayRole: return None 
     return "{0:02d}".format(index.row()) 


class ComboDelegate(QtGui.QItemDelegate): 
    """ 
    A delegate that places a fully functioning QComboBox in every 
    cell of the column to which it's applied 
    """ 
    def __init__(self, parent): 

     QtGui.QItemDelegate.__init__(self, parent) 

    def paint(self, painter, option, index): 

     self.combo = QtGui.QComboBox(self.parent()) 
     self.connect(self.combo, QtCore.SIGNAL("currentIndexChanged(int)"), self.parent().currentIndexChanged) 

     li = [] 
     li.append("Zero") 
     li.append("One") 
     li.append("Two") 
     li.append("Three") 
     li.append("Four") 
     li.append("Five") 

     self.combo.addItems(li) 

     if not self.parent().indexWidget(index): 
      self.parent().setIndexWidget(
       index, 
       self.combo 
      ) 

class TableView(QtGui.QTableView): 
    """ 
    A simple table to demonstrate the QComboBox delegate. 
    """ 
    def __init__(self, *args, **kwargs): 
     QtGui.QTableView.__init__(self, *args, **kwargs) 

     # Set the delegate for column 0 of our table 
     # self.setItemDelegateForColumn(0, ButtonDelegate(self)) 
     self.setItemDelegateForColumn(0, ComboDelegate(self)) 

    @QtCore.pyqtSlot() 
    def currentIndexChanged(self, ind): 
     print "Combo Index changed {0} {1} : {2}".format(ind, self.sender().currentIndex(), self.sender().currentText()) 

if __name__=="__main__": 
    from sys import argv, exit 

    class Widget(QtGui.QWidget): 
     """ 
     A simple test widget to contain and own the model and table. 
     """ 
     def __init__(self, parent=None): 
      QtGui.QWidget.__init__(self, parent) 

      l=QtGui.QVBoxLayout(self) 
      self._tm=TableModel(self) 
      self._tv=TableView(self) 
      self._tv.setModel(self._tm) 
      l.addWidget(self._tv) 

    a=QtGui.QApplication(argv) 
    w=Widget() 
    w.show() 
    w.raise_() 
    exit(a.exec_()) 

Odpowiedz

17

Niepoprawnie używasz metody paint. Powinno być używane, gdy chcesz zmienić zachowanie wyświetlania widoku. Również tworzenie nowego widgetu za każdym razem, gdy chcesz go pomalować, jest bardzo kosztowne. Ale chcesz zmienić sposób edycji, więc musisz zmienić całą logikę programu.

Zobacz fixed code. Poniżej przedstawię zmiany.

1. Przede wszystkim musimy ustawić pierwszą kolumnę do edycji. Można to zrobić przez reimplementing QAbstractItemModel::flags:

def flags(self, index): 
    if (index.column() == 0): 
     return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled 
    else: 
     return QtCore.Qt.ItemIsEnabled 

2. Domyślnie edytor element jest tworzony, gdy użytkownik wykonuje podwójne kliknięcie na element. Jeśli chcesz, aby pokazać wszystkie comboboxes domyślnie, można użyć openPersistentEditor:

for row in range(0, self._tm.rowCount()): 
    self._tv.openPersistentEditor(self._tm.index(row, 0)) 

pamiętać, że należy również otwarte edytory dla nowo utworzonych komórek (jeśli występują).

3. Teraz wróciliśmy do naszego delegata. Musimy wdrożyć createEditor metodę, która będzie automatycznie wywoływana przez widoku, gdy edytor jest proszony o komórce:

def createEditor(self, parent, option, index): 
    combo = QtGui.QComboBox(parent) 
    li = [] 
    li.append("Zero") 
    li.append("One") 
    li.append("Two") 
    li.append("Three") 
    li.append("Four") 
    li.append("Five") 
    combo.addItems(li) 
    self.connect(combo, QtCore.SIGNAL("currentIndexChanged(int)"), 
       self, QtCore.SLOT("currentIndexChanged()")) 
    return combo 

Zauważ, że connect jest poniżej append s ponieważ musimy unikać currentIndexChanged sygnały na inicjalizacji.

4. Wykonaj setEditorData metodę, która będzie wywoływana przez widok, gdy dane modelu zostały zmienione. Będzie również wywoływana raz, gdy zostanie zainicjowany edytor.

def setEditorData(self, editor, index): 
    editor.blockSignals(True) 
    editor.setCurrentIndex(int(index.model().data(index))) 
    editor.blockSignals(False) 

Znowu chcemy uniknąć sygnały, które nie są spowodowane przez użytkownika, więc używamy blockSignals.

5. w gnieździe po prostu emitują commitData sygnał, który spowoduje, że widok wezwać setModelData naszego delegata:

@QtCore.pyqtSlot() 
def currentIndexChanged(self): 
    self.commitData.emit(self.sender()) 

6. Wdrożenie setModelData metody:

def setModelData(self, editor, model, index): 
    model.setData(index, editor.currentIndex()) 

7. Twój model musi zmiana danych wsparcia.Więc powinniśmy wdrożyć setData metodę modelu:

def setData(self, index, value, role=QtCore.Qt.DisplayRole): 
    print "setData", index.row(), index.column(), value 
    # todo: remember the data 
+0

Dodałem kontynuacji pytanie o modelu danych [tutaj] (http://stackoverflow.com/questions/17697352/pyqt-implement-a-qabstracttablemodel -for-display-in-qtableview) zamiast zbytnio rozszerzać to pytanie. – drexiya

+0

Kolejne pytanie uzupełniające [tutaj] (http://stackoverflow.com/questions/17748546/pyqt-column-of-checkboxes-in-a-qtableview) dotyczące dodawania kolumny pól wyboru do widoku. – drexiya

Powiązane problemy