Is the a way to check a QCheckBox with a key press? - python

I'm working in PyQt5 and would like to be able check/uncheck a QCheckBox on a key prespress like with a QPushButton. I've checked the documentation and Google but cannot find a way to do this.

You have to overwrite the keyPressEvent method and call the nextCheckState() method to change the state of the QCheckBox:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class CheckBox(QtWidgets.QCheckBox):
def keyPressEvent(self, event):
if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
self.nextCheckState()
super(CheckBox, self).keyPressEvent(event)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = CheckBox("StackOverflow")
w.show()
sys.exit(app.exec_())

Related

Multiple key register event PyQT5

I have a program programming with Pyqt5 in which I would like to register some keys simoultaneously;for example, up+right to go to the upper diagonal.
The problem is that with the pressEvent only accept the first key.
Also I use QPygletWidget, but I can not register the push_handlers event from pyglet to PyQt5.
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
def keyPressEvent(self, e, autorep=False):
# print(e.key)
# self.widget.key_pressed = e.key()
print(e.key())
# self.widget.key_pressed = None
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_()) ```
Unfortunately QKeySequence doesn't work for sequences that don't contain CTRL.
You can use keyPressEvent and keyReleaseEvent to keep track what keys is currently pressed and not released yet.
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self._keys = {Qt.Key_Up: False, Qt.Key_Right: False}
def keyPressEvent(self, event):
if event.key() in [Qt.Key_Up, Qt.Key_Right]:
self._keys[event.key()] = True
if self._keys[Qt.Key_Up] and self._keys[Qt.Key_Right]:
self.onUpRight()
def keyReleaseEvent(self, event):
if event.key() in [Qt.Key_Up, Qt.Key_Right]:
self._keys[event.key()] = False
def onUpRight(self):
print("onUpRight")
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Be aware that if hold a key longer than some threshold (a second I guess) it sends sequences of keyPressEvent keyReleaseEvent as if you repeatedly pressed a button, so onUpRight will be called multiple times.

If click Eyes icon Show/Hide password (QPushButton)

I'm trying to create a function in a register and login form using QLineEdit to show and hide password if click a QPushButton. I'm a beginner in Python, I'm just trying to do it but it's very hard... My attempt is not good because if I click the eye button the password is shown, but if click again to hide it does not work.
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QPushButton, QLineEdit
import sys
import pymysql
pymysql.install_as_MySQLdb()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('MainWindow.ui', self)
self.eyepass_show()
self.eyepass_hide()
self.btn_show_pwd.clicked.connect(self.eyepass_hide)
self.btn_show_pwd.clicked.connect(self.eyepass_show)
def eyepass_show(self):
self.line_password.setEchoMode(QLineEdit.Normal)
print('show pass')
def eyepass_hide(self):
self.line_password.setEchoMode(QLineEdit.Password)
print('hide pass')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
form password hide/show eye:
is hiding password is show but if click again to hide not work
Instead of creating two separate methods as eyepass_show and eyepass_hide, you can create a single function and toggle the visibility. Also, you are trying to connect the same signal twice to two different methods by self.btn_show_pwd.clicked.connect(self.eyepass_hide)and self.btn_show_pwd.clicked.connect(self.eyepass_show)
Try something like this:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QPushButton, QLineEdit
import sys
import pymysql
pymysql.install_as_MySQLdb()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('MainWindow.ui', self)
self.eyepass_show()
self.eyepass_hide()
self.btn_show_pwd.clicked.connect(self.toggleVisibility)
def toggleVisibility(self):
if self.line_password.echoMode()==QLineEdit.Normal:
self.line_password.setEchoMode(QLineEdit.Password)
else:
self.line_password.setEchoMode(QLineEdit.Normal)
# self.btn_show_pwd.clicked.connect(self.eyepass_hide)
# self.btn_show_pwd.clicked.connect(self.eyepass_show)
#
# def eyepass_show(self):
# self.line_password.setEchoMode(QLineEdit.Normal)
# print('show pass')
#
# def eyepass_hide(self):
# self.line_password.setEchoMode(QLineEdit.Password)
# print('hide pass')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
Another possibility is to add a checkable QAction to the QLineEdit and connect to the toggled (or triggered) signal.
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('MainWindow.ui', self)
icon = QtGui.QIcon('eye-icon.png')
self.showPassAction = QtWidgets.QAction(icon, 'Show password', self)
self.line_password.addAction(
self.showPassAction, QtWidgets.QLineEdit.TrailingPosition)
self.showPassAction.setCheckable(True)
self.showPassAction.toggled.connect(self.showPassword)
def showPassword(self, show):
self.line_password.setEchoMode(
QtWidgets.QLineEdit.Normal if show else QtWidgets.QLineEdit.Password)
If you want to show the password only when the mouse is pressed, then don't connect to the toggled signal, but find the child QToolButton for that action and connect to the pressed and released instead. In this case, the action doesn't need to be checkable.
self.line_password.addAction(
self.showPassAction, QtWidgets.QLineEdit.TrailingPosition)
showPassButton = self.line_password.findChild(QtWidgets.QAbstractButton)
showPassButton.pressed.connect(lambda: self.showPassword(True))
showPassButton.released.connect(lambda: self.showPassword(False))
One of the great things about PyQt5 is that it will automatically connect signals to methods for you. If you have a button named <mybutton> and a method in your app named on_<mybutton>_clicked, the the loadUi will automatically connect. So the pattern is
on_<widget_name>_<signal>
If we apply this to your problem, you should make your show/hide button a toggle button. In Qt Designer, set the checkable property to True (or do btn_show_pwd.clicked.setChecked(True))
The code:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QPushButton, QLineEdit
import sys
#import pymysql
#pymysql.install_as_MySQLdb()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self, maxWidth=None):
super(MyWindow, self).__init__()
uic.loadUi('test1.ui', self)
self.line_password.setEchoMode(QLineEdit.Password)
def on_btn_show_pwd_toggled(self, checked):
if checked:
self.line_password.setEchoMode(QLineEdit.Password)
else:
self.line_password.setEchoMode(QLineEdit.Normal)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())

KeyPressEvent without Focus

I am programming a simple GUI, that will open a opencv window at a specific point. This window has some very basic keyEvents to control it. I want to advance this with a few functions. Since my QtGui is my Controller, I thought doing it with the KeyPressedEvent is a good way. My Problem is, that I cannot fire the KeyEvent, if I am active on the opencv window.
So How do I fire the KeyEvent, if my Gui is out of Focus?
Do I really need to use GrabKeyboard?
The following code reproduces my Problem:
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.Qt import Qt
import cv2
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.first = True
def openselect(self):
im = cv2.imread(str('.\\images\\Steine\\0a5c8e512e.jpg'))
self.r = cv2.selectROI("Image", im)
def keyPressEvent(self, event):
if event.key() == Qt.Key_Space and self.first:
self.openselect()
self.first = False
print('Key Pressed!')
if __name__ == '__main__':
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
The keyPressEvent method is only invoked if the widget has the focus so if the focus has another application then it will not be notified, so if you want to detect keyboard events then you must handle the OS libraries, but in python they already exist libraries that report those changes as pyinput(python -m pip install pyinput):
import sys
from PyQt5 import QtCore, QtWidgets
from pynput.keyboard import Key, Listener, KeyCode
class KeyMonitor(QtCore.QObject):
keyPressed = QtCore.pyqtSignal(KeyCode)
def __init__(self, parent=None):
super().__init__(parent)
self.listener = Listener(on_release=self.on_release)
def on_release(self, key):
self.keyPressed.emit(key)
def stop_monitoring(self):
self.listener.stop()
def start_monitoring(self):
self.listener.start()
class MainWindow(QtWidgets.QWidget):
pass
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
monitor = KeyMonitor()
monitor.keyPressed.connect(print)
monitor.start_monitoring()
window = MainWindow()
window.show()
sys.exit(app.exec_())

PyQt - Add right click to a widget

I am using PyQt and I want to add a right click to a widget, but I can't find any code on this subject online.
How can you do it ?
You just have to override the methods that take care of it.
In this case you will override the mousePressEvent, have a look on this and see if it makes sense and works for what you need.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
def mousePressEvent(self, QMouseEvent):
if QMouseEvent.button() == Qt.LeftButton:
print("Left Button Clicked")
elif QMouseEvent.button() == Qt.RightButton:
#do what you want here
print("Right Button Clicked")
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MyWidget()
mw.show()
sys.exit(app.exec_())
Another good way to do that would be installing a event filter in your object and overriding its eventFilter. Inside that method you would make what you want. Remember you can always make use of pyqtSignal for good practices and call another object to make the job, not overloading the method with a lot of logic.
Here is another small example:
import sys
from PyQt5.QtCore import QEvent
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QWidget
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.installEventFilter(self)
def eventFilter(self, QObject, event):
if event.type() == QEvent.MouseButtonPress:
if event.button() == Qt.RightButton:
print("Right button clicked")
return False
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MyWidget()
mw.show()
sys.exit(app.exec_())
Note: Remember that this last example will receive ALL KIND OF EVENTS, so you will have to be careful and make sure it's the one you want and not runtime breaking your app calling methods of your event that doesn't exist because it's not of that kind. For example if you call event.button() without making sure before that it is a QEvent.MouseButtonPress your app would break of course.
There are other ways to do that, these are the most known ones.
I have come up with a pretty simple way of doing this and works perfectly. In the ControlMainWindow class add the following to initialise the Context menu policy as CustomeContextMenu where listWidget_extractedmeters will be the name of your QListWidget:
self.listWidget_extractedmeters.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.listWidget_extractedmeters.connect(self.listWidget_extractedmeters,QtCore.SIGNAL("customContextMenuRequested(QPoint)" ), self.listItemRightClicked)
Then in the ControlMainwindow class the following functions allow you to add context menu items and to call a funtion that performs some functionality:
def listItemRightClicked(self, QPos):
self.listMenu= QtGui.QMenu()
menu_item = self.listMenu.addAction("Remove Item")
self.connect(menu_item, QtCore.SIGNAL("triggered()"), self.menuItemClicked)
parentPosition = self.listWidget_extractedmeters.mapToGlobal(QtCore.QPoint(0, 0))
self.listMenu.move(parentPosition + QPos)
self.listMenu.show()
def menuItemClicked(self):
currentItemName=str(self.listWidget_extractedmeters.currentItem().text() )
print(currentItemName)

PyQt5 & Qt Designer: why the second form displays a bad thing?

I can't make form1 to make parent object like it needs to be.
And all content in second form align to left-top corner and i have no way to make it work fine. May be someone know what i can do with this. Thank you!
How it looks in Qt Designer:
But how it looks really:
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QMainWindow, QApplication
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# Set up the user interface from Designer.
uic.loadUi("mw.ui", self)
uic.loadUi("form1.ui", self.mn_general)
# Connect up the buttons.
self.pushButton.clicked.connect(self.BtnClck)
self.show()
def BtnClck(self):
print('Hello StackOverflow')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainWindow()
sys.exit(app.exec_())

Categories

Resources