QComboBox editor showPopup incorrect placment of listview
-
I have a custom delegate that has a QComboBox as an editor for a tableview. I would like the ComboBox to auto expand and show the list view when the user double clicks the cell. Currently its double click to initiate the editor and then another click to expand to show the pop up.
I found the ComboBox has a .showPopup(), but when I use this, it provides the behavior of only using two clicks to expand the editor BUT always places the popup under the first cell upon the first edit event of the cell.
Is the creatEditor() the wrong place to call the showPopup? Or should I use some signal or editHint instead? Feels like Qt doesn't have all the information it needs and places the popup under the first cell
On windows 10, Qt 5.13
from PySide2 import QtGui, QtCore, QtWidgets import sys class CustomTableDelegate(QtWidgets.QStyledItemDelegate): def __init__(self, parent=None): super(CustomTableDelegate, self).__init__(parent) def createEditor(self, parent, option, index): """Create the ComboBox editor view.""" if index.column() == 0: editor = QtWidgets.QComboBox(parent) editor.addItems(['v001', 'v002', 'v003']) # !! this causes the pop up in incorrect place editor.showPopup() editor.activated.connect(self.commitAndCloseEditor) return editor def setEditorData(self, editor, index): """Set the ComboBox's current index.""" value = index.data(QtCore.Qt.DisplayRole) i = editor.findText(value) if i == -1: i = 0 editor.setCurrentIndex(i) def commitAndCloseEditor(self): editor = self.sender() self.commitData.emit(editor) self.closeEditor.emit(editor, QtWidgets.QStyledItemDelegate.NoHint) def setModelData(self, editor, model, index): """Set the table's model's data when finished editing.""" value = editor.currentText() model.setData(index, value) if __name__ == '__main__': app = QtWidgets.QApplication([]) data = [["v001", "stuff", "fixing source", '2020-01-14', ''], ["v002", "more stuff", "currently broken", '2020-06-30', ''], ["v003", "too much stuff", "scaling issues", '2020-02-08', ''], ["v088", "still missing stuff", "not coment", '2020-11-13', ''], ] table_view = QtWidgets.QTableView() table_view.setItemDelegate(CustomTableDelegate(table_view)) model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(['version', 'file', 'comment', 'date', '']) table_view.setModel(model) for r in range(len(data)): for c in range(5): model.setItem(r, c, QtGui.QStandardItem(data[r][c])) table_view.show() sys.exit(app.exec_())
-
@Denni-0
Sorry does your code have the event to trigger the dropdow instead of the .showPopup?Also you decorated the commitAndCloseEditor(), what is the purpose of that? and did you mean to use "@Slot" instead? I thought @pyqtslot is a pyqt5 decorator.
https://www.learnpyqt.com/blog/pyqt5-vs-pyside2/Cheers
-
no worries,
So I was able to try an event filter and test if a HoverEnter event happened, Then trigger the show pop up. Seems to solve the placement issue, not sure if this is the proper way of handling this,but gets the job done so far.
from PySide2 import QtGui, QtCore, QtWidgets import sys class CustomTableDelegate(QtWidgets.QStyledItemDelegate): def __init__(self, parent=None): super(CustomTableDelegate, self).__init__(parent) def createEditor(self, parent, option, index): """Create the ComboBox editor view.""" if index.column() == 0: editor = QtWidgets.QComboBox(parent) editor.addItems(['v001', 'v002', 'v003']) editor.installEventFilter(self) editor.activated.connect(self.commitAndCloseEditor) return editor def setEditorData(self, editor, index): """Set the ComboBox's current index.""" value = index.data(QtCore.Qt.DisplayRole) i = editor.findText(value) if i == -1: i = 0 editor.setCurrentIndex(i) def commitAndCloseEditor(self): editor = self.sender() self.commitData.emit(editor) self.closeEditor.emit(editor, QtWidgets.QStyledItemDelegate.NoHint) def setModelData(self, editor, model, index): """Set the table's model's data when finished editing.""" value = editor.currentText() model.setData(index, value) def eventFilter(self, p_object, event): if event.type() == QtCore.QEvent.Type.HoverEnter: p_object.showPopup() return True else: return False if __name__ == '__main__': app = QtWidgets.QApplication([]) data = [["v001", "stuff", "fixing source", '2020-01-14', ''], ["v002", "more stuff", "currently broken", '2020-06-30', ''], ["v003", "too much stuff", "scaling issues", '2020-02-08', ''], ["v088", "still missing stuff", "not coment", '2020-11-13', ''], ] table_view = QtWidgets.QTableView() table_view.setItemDelegate(CustomTableDelegate(table_view)) model = QtGui.QStandardItemModel() model.setHorizontalHeaderLabels(['version', 'file', 'comment', 'date', '']) table_view.setModel(model) for r in range(len(data)): for c in range(5): model.setItem(r, c, QtGui.QStandardItem(data[r][c])) table_view.show() sys.exit(app.exec_())