i am trying to capture the key_tab event, but no luck. i realized that it only works if there are no other widgets so the cursor has no where to go only then can i get the event to return. here is a simplified code sample.
class MyCombo(QComboBox):
def __init__(self, parent=None):
super(MyCombo, self).__init__(parent)
self.setEditable(True)
def keyPressEvent(self, event):
if (event.type() == QEvent.KeyPress) and (event.key() == Qt.Key_Tab):
print "tab pressed"
elif event.key() == Qt.Key_Return:
print "return pressed"
else:
QComboBox.keyPressEvent(self, event)
class Form_1(QDialog):
def __init__(self, parent=None):
super(Form_1, self).__init__(parent)
self.combo = MyCombo()
self.line = QLineEdit()
layout = QVBoxLayout()
layout.addWidget(self.combo)
layout.addWidget(self.line)
self.setLayout(layout)
app = QApplication(sys.argv)
form = Form_1()
form.show()
app.exec_()
if i comment out the following two lines
self.line = QLineEdit()
layout.addWidget(self.line)
then it works fine, because there is only one widget left on the form.
where am i going wrong?
Cheers, Joe
Apparently the Key_Tab press event is never passed to any handler but to the setFocus() so in order to intercept the Key_Tab event, we need to implement the event() method itself.
so here is the new code:
class MyCombo(QComboBox):
def __init__(self, parent=None):
super(MyCombo, self).__init__(parent)
self.setEditable(True)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Return:
print "return pressed"
else:
QComboBox.keyPressEvent(self, event)
def event(self, event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
print "tab pressed"
return False
return QWidget.event(self, event)
class Form_1(QDialog):
def __init__(self, parent=None):
super(Form_1, self).__init__(parent)
self.combo = MyCombo()
self.line = QLineEdit()
layout = QVBoxLayout()
layout.addWidget(self.combo)
layout.addWidget(self.line)
self.setLayout(layout)
Related
How can I detect mouse clicks in QWebEngineView widget?
I tried this but doesn't work:
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.view.installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == event.MouseButtonPress:
print ("Widget click")
return super(QtWidgets.QMainWindow, self).eventFilter(obj, event)
Assuming that the view is the QWebEngineView object and you want to track its mouse event then you should use the focusProxy which is an internal widget that handles these types of events. On the other hand you must correctly apply inheritance.
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MyWin, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.view.focusProxy().installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.ui.view.focusProxy() and event.type() == event.MouseButtonPress:
print("Widget click")
return super(MyWin, self).eventFilter(obj, event)
I want to execute other command on click and double click. When doubleclick is executed, click does not want to be executed.
from PySide2 import QtWidgets, QtCore, QtGui
class TestView(QtWidgets.QTableView):
custom_clicked = QtCore.Signal(QtCore.QModelIndex)
custom_double_clicked = QtCore.Signal(QtCore.QModelIndex)
def __init__(self, parent=None):
super(TestView, self).__init__(parent=parent)
self.timer = QtCore.QTimer(self)
self.timer.setInterval(250)
self.timer.setSingleShot(True)
self.timer.timeout.connect(self.timeout)
self.click_number = 0
def mousePressEvent(self, event):
super(TestView, self).mousePressEvent(event)
if event.button() == QtCore.Qt.LeftButton:
self.index = self.indexAt(event.pos())
self.click_number += 1
if not self.timer.isActive():
self.timer.start()
def timeout(self):
if self.click_number < 2:
self.custom_clicked.emit(self.index)
elif self.click_number > 1:
self.custom_double_clicked.emit(self.index)
self.click_number = 0
def click_command(index):
print "single", index
def double_click_command(index):
print "double", index
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
tableView = TestView()
model = QtGui.QStandardItemModel()
item = QtGui.QStandardItem()
item.setData("test", QtCore.Qt.DisplayRole)
model.setItem(0, item)
tableView.setModel(model)
tableView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
tableView.custom_clicked[QtCore.QModelIndex].connect(click_command)
tableView.custom_double_clicked[QtCore.QModelIndex].connect(double_click_command)
tableView.show()
sys.exit(app.exec_())
This code works well when there is no item.
However, it will break if you double-click the item.
Timer seems to be the cause, but I'm looking for a reason.
To detect the double click you should only use the mouseDoubleClickEvent so you only have to detect that it was not pressed a second time in a certain time:
class TestView(QtWidgets.QTableView):
custom_clicked = QtCore.Signal(QtCore.QModelIndex)
custom_double_clicked = QtCore.Signal(QtCore.QModelIndex)
def __init__(self, parent=None):
super(TestView, self).__init__(parent)
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.timeout)
self.timer.setInterval(
QtGui.QGuiApplication.styleHints().mouseDoubleClickInterval()
)
self.timer.setSingleShot(True)
def mousePressEvent(self, event):
super(TestView, self).mousePressEvent(event)
if event.button() == QtCore.Qt.LeftButton:
self.index = self.indexAt(event.pos())
self.timer.start()
def mouseDoubleClickEvent(self, event):
super(TestView, self).mouseDoubleClickEvent(event)
if event.button() == QtCore.Qt.LeftButton:
index = self.indexAt(event.pos())
self.custom_double_clicked.emit(index)
self.timer.stop()
def timeout(self):
self.custom_clicked.emit(self.index)
I want mouse events to reach the appropriate QGraphicsItem but they get no further than the QGraphicsView.
I have reduced my code to 41 lines, commented out event handlers but to no avail. It is either handled by QGraphicsView if that has a handler or, if not, is not caught at all.
I'm sure I'm missing something obvious but I can't see it.
from PyQt5.QtWidgets import *
class MyFrame(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.setScene(QGraphicsScene())
self.scene().addItem(Group())
def mouseReleaseEvent(self, event):
print('in QGraphicsView')
return QGraphicsView.mouseReleaseEvent(self, event)
class Group(QGraphicsItemGroup):
def __init__(self, parent=None):
super().__init__()
item = MyEllipse(0, 0, 20, 20)
self.addToGroup(item)
def mouseReleaseEvent(self, event):
print('in QGraphicsItemGroup')
return QGraphicsItemGroup.mouseReleaseEvent(self, event)
class MyEllipse(QGraphicsEllipseItem):
def mouseReleaseEvent(self, event):
print('in QGraphicsEllipseItem')
return QGraphicsEllipseItem.mouseReleaseEvent(self, event)
if __name__ == '__main__':
app = QApplication([])
f = MyFrame()
f.show()
app.exec_()
mouseReleaseEvent is called if and only if the event that the mousePressEvent handles is accepted, so with the following code the event will arrive at QGraphicsItemGroup:
class Group(QGraphicsItemGroup):
def __init__(self, parent=None):
super().__init__()
item = MyEllipse(0, 0, 20, 20)
self.addToGroup(item)
def mousePressEvent(self, event):
QGraphicsItemGroup.mousePressEvent(self, event)
event.accept()
def mouseReleaseEvent(self, event):
print('in QGraphicsItemGroup')
QGraphicsItemGroup.mouseReleaseEvent(self, event)
But as #ekhumoro points out, the QGraphicsItemGroup acts as a single element so events are not transported to the items they handle.
If you want to detect when the item is pressed you can use the following method:
class Group(QGraphicsItemGroup):
def __init__(self, parent=None):
super().__init__()
self._item = MyEllipse(0, 0, 20, 20)
self.addToGroup(self._item)
def mousePressEvent(self, event):
QGraphicsItemGroup.mousePressEvent(self, event)
event.accept()
def mouseReleaseEvent(self, event):
print('in QGraphicsItemGroup')
if self._item.mapToParent(self._item.boundingRect()).containsPoint(event.pos(), Qt.OddEvenFill):
print("_item")
QGraphicsItemGroup.mouseReleaseEvent(self, event)
I have a list widget which I need to drag items from it to another list widget. After enabling dragging by
self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
I can not drag select any more. I figured it's related to mousePressEvent. How can I reimplement it to enable dragging selection at the right side of the blank area of the list widget?
my code
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt, QString
import sys
import os
class ThumbListWidget(QtGui.QListWidget):
_rows_to_del = []
def __init__(self, type, parent=None):
super(ThumbListWidget, self).__init__(parent)
self.setIconSize(QtCore.QSize(124, 124))
self.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setAcceptDrops(True)
self._dropping = False
self.setSelectionRectVisible(True)
self.connect(self, QtCore.SIGNAL("dropped"), self.items_dropped)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
super(ThumbListWidget, self).dragEnterEvent(event)
def dragMoveEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
else:
super(ThumbListWidget, self).dragMoveEvent(event)
def dropEvent(self, event):
if event.mimeData().hasUrls():
event.setDropAction(QtCore.Qt.CopyAction)
event.accept()
links = []
for url in event.mimeData().urls():
links.append(str(url.toLocalFile()))
self.emit(QtCore.SIGNAL("dropped"), links)
else:
if event.source() is self:
event.setDropAction(QtCore.Qt.MoveAction)
else:
event.setDropAction(QtCore.Qt.CopyAction)
self._dropping = True
super(ThumbListWidget, self).dropEvent(event)
self._dropping = False
def rowsInserted(self, parent, start, end):
if self._dropping:
self.emit(QtCore.SIGNAL("dropped"), (start, end))
super(ThumbListWidget, self).rowsInserted(parent, start, end)
def dataChanged(self, start, end):
if self._dropping:
for row in range(start.row(), end.row() + 1):
index = self.indexFromItem(self.item(row))
shot = index.data().toString()
print len(self.findItems(shot, Qt.MatchExactly))
if len(self.findItems(shot, Qt.MatchExactly)) > 1:
self._rows_to_del.append(row)
self._rows_to_del.reverse()
for row in self._rows_to_del:
self.takeItem(row)
self._rows_to_del = []
def items_dropped(self, arg):
start, end = arg
print range(start, end + 1)
for row in range(start, end + 1):
item = self.item(row)
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
item.setCheckState(Qt.Checked)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Space:
if self.selectedItems():
new_state = Qt.Unchecked if self.selectedItems()[0].checkState() else Qt.Checked
for item in self.selectedItems():
if item.flags() & Qt.ItemIsUserCheckable:
# print 'set new state:', new_state
item.setCheckState(new_state)
self.reset()
elif event.key() == Qt.Key_Delete:
for item in self.selectedItems():
self.takeItem(self.row(item))
class Dialog_01(QtGui.QMainWindow):
def __init__(self):
super(QtGui.QMainWindow, self).__init__()
self.listItems = {}
myQWidget = QtGui.QWidget()
myBoxLayout = QtGui.QVBoxLayout()
myQWidget.setLayout(myBoxLayout)
self.setCentralWidget(myQWidget)
self.listWidgetA = ThumbListWidget(self)
for i in range(12):
QtGui.QListWidgetItem('Item ' + str(i), self.listWidgetA)
all_items = self.listWidgetA.findItems(QString('*'), Qt.MatchWrap | Qt.MatchWildcard)
for item in all_items:
item.setFlags(item.flags() & ~Qt.ItemIsUserCheckable)
myBoxLayout.addWidget(self.listWidgetA)
self.listWidgetB = ThumbListWidget(self)
self.listWidgetA.setAcceptDrops(False)
myBoxLayout.addWidget(self.listWidgetB)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog_1 = Dialog_01()
dialog_1.show()
dialog_1.resize(480, 320)
sys.exit(app.exec_())
gyfcat of current look or
If I comment out that line, I'll be able to drag select as the following screen cast shows.
gyfcat of desired look or
I have a QGraphicsScene and I will display a contextmenu. But nothing happend.
Here is my Code:
class graphicsScene(QtGui.QGraphicsScene):
def __init__ (self, parent = None):
super(graphicsScene, self).__init__ (parent)
def contextMenuEvent(self, event):
self.popMenu = QtGui.QMenu()
self.popMenu.addAction(QtGui.QAction('test0', None))
self.popMenu.addAction(QtGui.QAction('test1', None))
self.popMenu.addSeparator()
self.popMenu.addAction(QtGui.QAction('test2', None))
self.popMenu.exec_(event.globalPos())
def mousePressEvent(self, event):
super(graphicsScene, self).mousePressEvent(event)
pos = event.scenePos()
item = self.itemAt(pos)
if event.button() == QtCore.Qt.LeftButton:
#do something
elif event.button() == QtCore.Qt.RightButton:
self.contextMenuEvent(event)
I have no idea how to fix this problem.
Thank you for your help!!!
This may help:
class Table(QtGui.QGraphicsView):
def __init__(self, parent=None):
super(Table, self).__init__(parent)
self.setScene(QtGui.QGraphicsScene())
self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
def contextMenuEvent(self, event):
menu = QtGui.QMenu()
menu.addAction('sample')
menu.exec_(event.globalPos())