我需要一个带有QListView
按钮的QComboBox
,但是因为写代表是一个巨大的痛苦。我选择了QTableView
,因为每行都会有相同的按钮。我唯一的问题是我似乎无法从clicked
内捕获QComboBox
信号。
我附上一个mwe来说明我的意思:
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_())
答案 0 :(得分:2)
您可以使用以下信号触发组合框中的单击:
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)
或者,如果您只需要在点击或键盘输入更改所选项目时进行检测:
combo.currentIndexChanged.connect(lambda: print('Click Combo'))
答案 1 :(得分:2)
通过使用视图的mousePressEvent
和combo.activated
信号(感谢PRMoureu),我发现了一种非优雅的方法。我张贴它以防任何人都可以使用它。
#!/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_())