我需要将Qlabel
中的Qcombobox
更改为QStyledItemDelegate
。但是,当我单击标签时,组合框出现在QTableView
的最后可见行中。
我试图从基础表中获取currentIndex
,并通过sender().objectName ()
获取点击的来源。两者都是正确的,但是与我如何设置行无关,该组合仍然位于错误的行(最后一个)上。 Solution by CSS中的解决方案不适用于我。
如何将委托中的选定行设置为特定行以替换小部件?
工作示例:
from PyQt5.QtWidgets import QItemDelegate, QLabel, QStyledItemDelegate, QComboBox, QAbstractItemView, QTextEdit, \
QVBoxLayout, QMainWindow, QWidget, QApplication, QTableView
from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal, QModelIndex, QEvent, QVariant, QAbstractTableModel, QCoreApplication
class ClickLabel(QLabel):
clicked = pyqtSignal()
def mousePressEvent(self, event):
self.clicked.emit()
QLabel.mousePressEvent(self, event)
class dateDelegate2(QStyledItemDelegate):
def __init__(self, parent):
super (dateDelegate2, self).__init__ (parent)
def paint(self, painter, option, index):
if (
isinstance(self.parent(), QAbstractItemView)
and self.parent().model() is index.model()
):
self.parent().openPersistentEditor(index)
def createEditor(self, parent, option, index):
editor = QLabel(parent)
self.dateValue = QLabel()
self.dateValue.setFixedHeight(160)
self.dateValue.setAlignment(Qt.AlignTop)
self.dateValue.setEnabled(False)
self.dateValue.setStyleSheet ("QTextEdit{ border-width: 0px; border-style: solid; border-color: gray; color: blue; font-size: 12px }");
self.itemValue = ClickLabel()
self.itemValue.setFixedHeight(200)
self.itemValue.setStyleSheet ("QLabel{ border-width: 0px; border-style: solid; border-color: gray; color: blue; font: bold; font-size: 14px }");
self.itemValue.setAlignment(Qt.AlignTop)
self.itemValue.setObjectName('itemValue_' + str(index.row()))
self.itemValue.clicked.connect (lambda: self.directClick(index))
self.mainlayout = QVBoxLayout ()
self.mainlayout.addWidget(self.itemValue)
self.mainlayout.addWidget (self.dateValue)
editor.setLayout(self.mainlayout)
return editor
def setEditorData(self, editor, index):
dateString = str(index.data())
self.dateValue.setText(dateString)
self.itemValue.setText('itemValue_' + str(index.row()))
def setModelData(self, editor, model, index, rps_id):
pass
def inputComboChanged(self):
print("inputComboChanged:", self.inputCombo.currentIndex(), self.inputCombo.currentText())
def directClick(self, index):
fromObject = self.sender().objectName ()
fromRow = fromObject.split('_')[1]
print("directClick !!!", fromObject, fromRow)
delegateindex = self.parent().model().index(int(fromRow),0)
print("dindex:",delegateindex.row())
# Does not set to position
self.parent().setCurrentIndex (delegateindex)
# Does not help
self.parent().scrollTo (delegateindex)
self.inputCombo = QComboBox ()
self.inputCombo.addItems(['A1','A2','A3'])
self.inputCombo.setEditable (True)
self.inputCombo.currentIndexChanged.connect (self.inputComboChanged)
self.mainlayout.removeWidget (self.itemValue)
self.mainlayout.insertWidget (0, self.inputCombo, alignment=Qt.AlignTop)
class Model(QAbstractTableModel):
ActiveRole = Qt.UserRole + 1
def __init__(self, datain, headerdata, parent=None):
super().__init__()
self.arraydata = datain
self.headerdata = headerdata
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return QVariant(self.headerdata[section])
return QVariant()
def rowCount(self, parent=QModelIndex()):
if parent.isValid(): return 0
return len(self.arraydata)
def columnCount(self, parent=QModelIndex()):
if parent.isValid(): return 0
if len(self.arraydata) > 0:
return len(self.arraydata[0])
return 0
def flags(self, index):
return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def print_arraydata(self):
print(self.arraydata)
def insert_row(self, data, position, rows=1):
self.beginInsertRows(QModelIndex(), position, position + rows - 1)
for i, e in enumerate(data):
self.arraydata.insert(i+position, e[:])
self.endInsertRows()
return True
def remove_row(self, position, rows=1):
self.beginRemoveRows(QModelIndex(), position, position + rows - 1)
self.arraydata = self.arraydata[:position] + self.arraydata[position + rows:]
self.endRemoveRows()
return True
def append_row(self, data):
self.insert_row([data], self.rowCount())
class Main(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
# create table view:
self.tableview = self.createTable()
# create layout
layout = QVBoxLayout()
layout.addWidget(self.tableview)
# initializing layout
self.setGeometry(0, 0, 500, 500)
self.centralwidget = QWidget()
self.centralwidget.setLayout(layout)
self.setCentralWidget(self.centralwidget)
def createTable(self):
tv = QTableView()
tv.resizeRowsToContents()
# set header for columns:
header = ['Name', 'Type', 'var1', 'var2', 'var3']
tabledata = [[1,2,3,4],[11,12,13,14],[21,22,23,24],[31,32,33,34]]
tablemodel = Model(tabledata, header, self)
tv.setModel (tablemodel)
for row in range (tablemodel.rowCount ()):
tv.setRowHeight(row, 200)
tv.setItemDelegateForColumn(1, dateDelegate2(tv))
return tv
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())