2017-08-08 3 views
2

Ich brauche eine QListView mit Tasten für eine QComboBox, aber seit Delegaten schreiben ist ein großer Schmerz. Ich habe mich stattdessen für eine QTableView entschieden, da es für jede Zeile immer die gleichen Tasten gibt. Mein einziges Problem ist, dass ich nicht das clicked Signal von innerhalb der QComboBox fangen kann.Klick-Signal in QTableView die Ansicht von QComboBox

angebracht ich einen MWe zu veranschaulichen, was ich meine:

from PyQt5.QtCore import QModelIndex, Qt, QAbstractTableModel, QVariant 
from PyQt5.QtWidgets import QApplication, QComboBox, QTableView, QWidget, QVBoxLayout 


class Model(QAbstractTableModel): 
    def data(self, index, role=Qt.DisplayRole): 
     if role == Qt.DisplayRole: 
      col = index.column() 
      if col == 0: 
       return str(index.row()) 
      elif col == 1: 
       return '✎' 
      elif col == 2: 
       return '✘' 
     return QVariant() 

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

    def rowCount(self, parent=QModelIndex()): 
     return 5 


if __name__ == '__main__': 
    import sys 

    app = QApplication(sys.argv) 
    model = Model() 

    main = QWidget() 
    layout = QVBoxLayout(main) 

    view = QTableView() 
    view.clicked.connect(lambda _: print('Click Table')) # Works fine 
    view.setModel(model) 
    layout.addWidget(view) 

    combo = QComboBox() 
    combo.setModel(model) 
    combo.setView(QTableView()) 
    combo.view().clicked.connect(lambda _: print('Click Combo')) # Does'nt show 
    layout.addWidget(combo) 

    main.resize(500, 300) 
    main.show() 
    sys.exit(app.exec_()) 

Antwort

2

Sie das folgende Signal verwenden, um einen Klick in der Combobox auslösen:

view = QTableView() 
view.clicked.connect(lambda: print('Click Table')) # Works fine 
view.setModel(model) 
layout.addWidget(view) 

combo = QComboBox() 
combo.setModel(Model()) 
combo.setView(QTableView()) 

combo.activated.connect(lambda: print('Click Combo')) # Works fine too 
layout.addWidget(combo) 

Oder wenn Sie brauchen nur zu erkennen, wenn ein Klick oder eine Tastatureingabe ändert den ausgewählten Artikel:

combo.currentIndexChanged.connect(lambda: print('Click Combo')) 
+0

Vielen Dank für Ihre Antwort. Das scheint die richtige Richtung zu sein. Wie bekomme ich den Index des Klicks? 'combo.activated.connect (lambda ind: drucken (f'Click Combo {ind} '))' gibt mir nur die Zeile, aber nicht die Spalte. –

2

Ich fand einen nicht-eleganten Weg zu Achi Eve dies mit der der Ansicht und der combo.activated Signal (Danke PRMoureu). Ich poste es für den Fall, dass irgendjemand es benutzen kann.

#!/usr/bin/env python3 

from PyQt5.QtCore import QModelIndex, Qt, QAbstractTableModel, QVariant 
from PyQt5.QtWidgets import QApplication, QComboBox, QTableView, QWidget, QVBoxLayout 


class Model(QAbstractTableModel): 
    DATA = ['0', '1', '2', '3', '4'] 

    def data(self, index, role=Qt.DisplayRole): 
     if role == Qt.DisplayRole: 
      col = index.column() 
      if col == 0: 
       return self.DATA[index.row()] 
      elif col == 1: 
       return '✎' 
      elif col == 2: 
       return '✘' 
     return QVariant() 

    def callback(self, row, col): 
     print(f'Clicked {row}:{col}') 

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

    def rowCount(self, parent=QModelIndex()): 
     return 5 


class Table(QTableView): 
    BUTTON_SIZE = 20 
    click_col_index = 0 

    def __init__(self, parent=None): 
     super().__init__(parent) 
     self.horizontalHeader().hide() 
     self.verticalHeader().hide() 

    def resizeEvent(self, event): 
     super().resizeEvent(event) 

     self.setColumnWidth(0, self.width() - 2 * self.BUTTON_SIZE) 
     self.setColumnWidth(1, self.BUTTON_SIZE) 
     self.setColumnWidth(2, self.BUTTON_SIZE) 

    def mousePressEvent(self, event): 
     x = event.localPos().x() 
     width = self.columnWidth(0) 
     self.click_col_index = max([0, (x - width + self.BUTTON_SIZE) // self.BUTTON_SIZE]) 


class SignalMixer: 
    def __init__(self, model, view, combo): 
     self.model = model 
     self.view = view 
     self.combo = combo 

     self.combo.activated.connect(self.clicked) 

    def clicked(self, row): 
     if self.view.click_col_index: 
      self.model.callback(row, self.view.click_col_index) 


if __name__ == '__main__': 
    import sys 

    app = QApplication(sys.argv) 
    model = Model() 

    main = QWidget() 
    layout = QVBoxLayout(main) 

    view = QTableView() 
    view.clicked.connect(lambda _: print('Click Table')) 
    view.setModel(model) 
    layout.addWidget(view) 

    combo = QComboBox() 
    combo.setModel(model) 
    combo.setView(Table()) 
    layout.addWidget(combo) 

    mixer = SignalMixer(model, combo.view(), combo) 

    main.resize(500, 300) 
    main.show() 
    sys.exit(app.exec_())