I am working with Python 3.6 and pyqt 4.11. I have two QTreeViews stacked in a Widget, both of them display some batch jobs so each step can expand to show all functions. I want to be able to double click on one line of the tree view and generate a pop up dialogue where I can edit the parameters of the function I double clicked on.
If I connect the double click signal without capturing the position:
self.connect(self.QTreeView, QtCore.SIGNAL('mouseDoubleClickEvent()'),print('OK'))
it works and OK is printed.
However as soon as I try to catch the cursor position nothing happens anymore. I have tried both to connect the whole widget and the treeView to a simple test function. It doesn't work at all, not even OK gets printed.
self.connect(self.QTreeView, QtCore.SIGNAL('mouseDoubleClickEvent(const QPoint &)'),self.showDlg)
def showDlg (self, point):
print ('OK')
treeidx=self.treeview.indexAt(point)
print (treeidx)
A ContextMenu is triggered by right click on the whole Widget and it works
self.QTreeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.connect(self.QTreeWidget, QtCore.SIGNAL('customContextMenuRequested(const QPoint &)'), self.customMyContextMenu)
But double clicking on the same Widget gives no result
self.connect(self.QTreeWidget, QtCore.SIGNAL('mouseDoubleClickEvent(const QPoint &)'),self.showDlg)
I would like to use the pointer position to know in what leaf of the tree view the changes have to happen, I thought
treeview.indexAt(point)
would be the way to do that, but since my simple function doesn't get called at all, there must be some other problem I don't see.
I find it strange that in your first code is printed "OK", what returns to me is an error because connect also expects a callable, but print('OK') returns None that is not a callable. Besides, mouseDoubleClickEvent
is not a signal but an event which reaffirms my strangeness.
Instead you have to use the doubleClicked
signal that returns the QModelIndex
associated with the item, and to get the position you have to use the QCursor::pos()
next to mapFromGlobal()
of the viewport()
of QTreeView
. You must also use the new connection syntax.
from PyQt4 import QtCore, QtGui
def create_model(parent):
model = QtGui.QStandardItemModel(parent)
for i in range(3):
parent_item = QtGui.QStandardItem("Family {}".format(i))
for j in range(3):
child1 = QtGui.QStandardItem("Child {}".format(i * 3 + j))
child2 = QtGui.QStandardItem("row: {}, col: {}".format(i, j + 1))
child3 = QtGui.QStandardItem("row: {}, col: {}".format(i, j + 2))
parent_item.appendRow([child1, child2, child3])
model.appendRow(parent_item)
return model
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._tree_view = QtGui.QTreeView()
self._tree_view.setModel(create_model(self))
self._tree_view.expandAll()
lay = QtGui.QVBoxLayout(self)
lay.addWidget(self._tree_view)
self._tree_view.doubleClicked.connect(self.on_doubleClicked)
@QtCore.pyqtSlot("QModelIndex")
def on_doubleClicked(self, ix):
print(ix.data())
gp = QtGui.QCursor.pos()
lp = self._tree_view.viewport().mapFromGlobal(gp)
ix_ = self._tree_view.indexAt(lp)
if ix_.isValid():
print(ix_.data())
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
PySide Version:
from PySide import QtCore, QtGui
def create_model(parent):
model = QtGui.QStandardItemModel(parent)
for i in range(3):
parent_item = QtGui.QStandardItem("Family {}".format(i))
for j in range(3):
child1 = QtGui.QStandardItem("Child {}".format(i * 3 + j))
child2 = QtGui.QStandardItem("row: {}, col: {}".format(i, j + 1))
child3 = QtGui.QStandardItem("row: {}, col: {}".format(i, j + 2))
parent_item.appendRow([child1, child2, child3])
model.appendRow(parent_item)
return model
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._tree_view = QtGui.QTreeView()
self._tree_view.setModel(create_model(self))
self._tree_view.expandAll()
lay = QtGui.QVBoxLayout(self)
lay.addWidget(self._tree_view)
self._tree_view.doubleClicked.connect(self.on_doubleClicked)
@QtCore.Slot("QModelIndex")
def on_doubleClicked(self, ix):
print(ix.data())
gp = QtGui.QCursor.pos()
lp = self._tree_view.viewport().mapFromGlobal(gp)
ix_ = self._tree_view.indexAt(lp)
if ix_.isValid():
print(ix_.data())
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())