I'm dynamically creating creating a list of QPushButtons in a vertical layout. I'm currently using the "click" signal for a function. But I would like to use the right mouse button for an additional function. Ex. print the tooltip of that QPushButton that the mouse is over by right clicking.
but = QtGui.QPushButton()
but.setText(cur);but.setCheckable(True)
but.setStyleSheet(_fromUtf8("text-align:right;background-color: rgb(50, 50, 50);"))
but.setToolTip(longName + "." + cur)
I'm looking over at the "QMouseEvent", "setMouseTracking", "mousePressEvents". But I'm not sure how to properly use them to get my desired result.
I would also be open to a custom signal for a QPushButton on "right-click".
Usually, the right mouse click is connected to the context menu. With
but.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
but.customContextMenuRequested.connect(handle_right_click)
you can connect a handler, which could be used for the right mouse click.
If you'd like to have a pure right mouse click action, you should extend QPushButton and override mousePressEvent(self, event) and mouseReleaseEvent(self, event). Then you need to set the button's ContextMenuPolicy to QtGui.Qt.PreventContextMenu to ensure their delivery:
The widget does not feature a context menu, and in contrast to NoContextMenu, the handling is not deferred to the widget's parent. This means that all right mouse button events are guaranteed to be delivered to the widget itself through QWidget::mousePressEvent(), and QWidget::mouseReleaseEvent().
You can check the mouse buttons in your handler for the clicked signal:
but.clicked.connect(self.buttonClicked)
...
def buttonClicked(self):
if QtGui.qApp.mouseButtons() & QtCore.Qt.RightButton:
print(self.sender().toolTip())
The mouse button constants can be OR'd together, allowing you to test for different combinations of them. So the above code will detect that the right button is held down while the left button is clicked.
You can also do a similar thing with the keyboard modifiers:
if QtGui.qApp.keyboardModifiers() & QtCore.Qt.ControlModifier:
print('ctrl+click')
Related
Im just try to use PyQt5 for my robot GUI. im little bit confuse how to use momentary push button which should giving true value when it pressed down and false value when it unpressed. fyi im using python for this.
im already try to use "setCheckable" to detecting its state, but it make the button toggled (not momentary). is there any other methode that i can implement?
The clicked signal is always emitted after the mouse button is released in the button rectangle. That's the common convention for a "click event" of buttons in almost any reasonable UI toolkit.
If you want to know when the button is pressed or released, then you can connect to the pressed and released signals.
Be aware, though, that the common convention above also considers that if the user leaves the button while the mouse button is still pressed, the button becomes "unpressed" as well, and becomes pressed again if the mouse goes back inside its geometry while the same mouse button is still pressed. This means that if you connect to those signals and the user "leaves" the button with the mouse button still pressed and gets back to it, you might get inconsistent results depending on your needs.
If you are interested in the basic "just when mouse button was pressed" and "mouse button released at last" state, no matter if the user released the mouse button outside of the widget, then the only option is to override the mouse button handlers and use a custom signal:
from PyQt5 import QtCore, QtWidgets
class IgnoreClickPosButton(QtWidgets.QPushButton):
pressedState = QtCore.pyqtSignal(bool)
def mousePressEvent(self, event):
super().mousePressEvent(event)
if event.button() == QtCore.Qt.LeftButton:
self.pressedState.emit(True)
def mouseReleaseEvent(self, event):
super().mouseReleaseEvent(event)
if event.button() == QtCore.Qt.LeftButton:
self.pressedState.emit(False)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
btn = IgnoreClickPosButton()
btn.pressedState.connect(lambda p: print('pressed', p))
btn.show()
sys.exit(app.exec_())
I want to implement a drag and drop functionality between two custom widgets. My understanding from this question is that I cannot use the built-in drag and drop functionality that e.g. buttons would provide, but that I need to implement mouseReleaseEvent and mousePressEvent handlers manually.
My specific goal is as follows: I have widgets of type Widget1 and Widget2, and I want that when Widget1 is dragged onto Widget2, a certain action is performed. I therefore implemented the mousePressEvent of Widget1 and the mouseReleaseEvent of Widget2.
class Widget1(QWidget):
...
def mousePressEvent(self, event):
print("Press")
class Widget2(QWidget):
...
def mouseReleaseEvent(self, event):
print("Release")
While "Press" is printed whenever I click on Widget1, "Release" is printed only after clicking on Widget2. That is, the release event is called for the same item that was clicked. How do I execute an action for the widget that the mouse was over at release?
I'm making a user-interface in PYQT 5. It includes a QGroupBox containing several QRadioButton. When there is a toggled event I check the buttons and do some stuff. The problem is that there are two toggled events because one button is toggled on and one off so my code is always running twice.
I have been looking for an event from the QGroupBox instead. That should only happen once instead of twice when i toggle a radiobutton.
def __init__(self):
self.radioButton1.toggled.connect(self.update_stimulus)
self.radioButton2.toggled.connect(self.update_stimulus)
self.radioButton3.toggled.connect(self.update_stimulus)
def update_stimulus(self):
if self.radioButton1.isChecked():
print('1')
if self.radioButton2.isChecked():
print('2')
if self.radioButton3.isChecked():
print('3')
# Do stuff based on button positions
I tried using
self.groupBox.toggled.connect(self.update_stimulus)
But that only works if the groupbox itself is toggled. Is there any way to get a signal from the groupbox when one of the radiobuttons changes or do I have to find some way of doing it with the indivdual signals from the radiobuttons?
As #ekhumoro explains, you can add the checked parameter to the function and do your processing only if it's True:
def update_stimulus(self, checked):
if not checked:
return
if self.radioButton1.isChecked():
print('1')
if self.radioButton2.isChecked():
print('2')
if self.radioButton3.isChecked():
print('3')
Keep in mind, though, that if you want to have different radio button "groups" within the same groupbox, none of this will work properly as they will all be considered as part of the same single group: all Qt buttons (widgets that inherit QAbstractButton: QPushButton, QToolButton, QCheckBox and QRadioButton) have an autoExclusive property which is off by default except from radio buttons. This property makes all button that belong to the same parent widget automatically exclusive.
If you need different groups within the same parent, the solution is to use a QButtonGroup, which extends the exclusive functionality by limiting the membership of each button to a specific group.
def __init__(self):
# ...
self.buttonGroupA = QtWidgets.QButtonGroup()
self.buttonGroupA.addButton(self.radioButton1)
self.buttonGroupA.addButton(self.radioButton2)
self.buttonGroupA.addButton(self.radioButton3)
self.buttonGroupA.buttonToggled[QtWidgets.QAbstractButton, bool].connect(self.update_stimulusA)
self.buttonGroupB = QtWidgets.QButtonGroup()
self.buttonGroupB.addButton(self.radioButton4)
self.buttonGroupB.addButton(self.radioButton5)
self.buttonGroupB.addButton(self.radioButton6)
self.buttonGroupB.buttonToggled[QtWidgets.QAbstractButton, bool].connect(self.update_stimulusB)
def update_stimulusA(self, btn, checked):
if not checked:
return
# do something with group A
def update_stimulusB(self, btn, checked):
if not checked:
return
# do something with group B
Creation of a button group is also possible from Designer: just select at least two buttons that will be members of the same group, right click on one of them, go to the "Assign to button group" sub menu and select "New button group". To add a button to an existing group, just use the same context menu and choose the group you want to add that button to.
I am developing an app.I would like there to be an option to zoom in and out. to do this I would like to have the program get when the control key is clicked and the mouse is being scrolled at the same time, and zoom accordingly(scroll up for zoom in, and scroll down for zoom out) I've been doing a lot of searching and reading,but only found ways to get a control press and a mouse click-event, not a mouse scroll-event. I also found a way to get a mouse scroll but couldn't get it to work with just control press. - and to ignore all other presses.
Could anyone suggest something to help me???
It depends a bit on the structure of your application.
One way to get scroll-events is to add a wheelEvent handler to your Widget
def wheelEvent(self, QWheelEvent):
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ControlModifier:
# do your processing
Another approach could be to install an eventFilter in the component where you want to intercept the scroll-events by
component.viewport().installEventFilter(self)
(maybe you have to install the event filter on the component itself iso on the viewport).
and self has an eventFilter function like
def eventFilter(self, qobject, event):
if (event.type() == QtCore.QEvent.Wheel) :
modifiers = QtGui.QApplication.keyboardModifiers()
if modifiers == QtCore.Qt.ControlModifier:
#do some scaling stuff
return True
return False
else:
# standard event processing
return False
Hope this helps.
I'm trying to schedule a mouse press event for a QComboBox. I was wondering if there is any way to schedule a mouse press event on the initial QComboBox click -- the click that brings up the list of items to select. I've already used the currentIndexChanged(int) signal to call a function once the user selects one of the items from the drop down menu, but I'm trying to refresh my QComboBox list with new entries once the user clicks on it. (I have a feeling that this approach may be misguided, but I guess that's another question.)
I've tried making a QComboBox subclass with def mousePressEvent(self, e), but it doesn't seem to do anything. I've also tried def mousePressEvent(self, e) in the QtGui.QWidget class that holds my QComboClass object but, unsurprisingly, that only captures mouse presses for the QtGui.QWidget.
Your current approach is misguided. Even if you could get it working, it would fail whenever the list was opened via the keyboard.
The correct way to do this is to override showPopup:
class ComboBox(QtGui.QComboBox):
def showPopup(self):
self.insertItem(0, 'Added')
super(ComboBox, self).showPopup()