I wrote an app to calculate amount of money by enter amount of coins and bank notes to calculate total value. I can jump to next text field using 'tab' key but I would rather to use 'enter' key. How can I set 'enter' instead of default 'tab' key for moving to next QLineEdit field ?
You have to override the event() method so that when it detects the KeyPress event and the keys are Enter then call focusNextPrevChild():
import sys
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
for i in range(10):
le = QtWidgets.QLineEdit()
lay.addWidget(le)
def event(self, event):
if event.type() == QtCore.QEvent.KeyPress:
if event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
self.focusNextPrevChild(True)
return super().event(event)
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
Related
If I press any key, nothing will happen. How to implement it? And I notice if I pressed some key, (at first time/Very Beggning/first character), it take some more time to display that pressed Character in textbox.How to resolve it?
from PyQt5 import QtWidgets,QtCore,QtGui
class MyKey(QtWidgets.QWidget):
def __init__(self):
super(). __init__()
self.setWindowTitle(" My Key Board")
self.ui()
def ui(self):
self.tb = QtWidgets.QLineEdit()
self.vb = QtWidgets.QVBoxLayout()
self.vb.addWidget(self.tb)
self.setLayout(self.vb)
def keyPressEvent(self, e):
print("key pressed")
print(e.key())
if type(e) == QtGui.QKeyEvent:
if e.key() == QtCore.Qt.Key_A:
print("ypu pressed 'A'")
if __name__ == "__main__":
import sys
myapp = QtWidgets.QApplication(sys.argv)
mywindow = MyKey()
mywindow.show()
sys.exit(myapp.exec_())
In Qt the KeyPressEvent is only sent to the widget that has the focus and if it consumes it then the event is not sent to the parent widgets otherwise the parent widget is also notified.
In this case, the QLineEdit is the widget that has the focus and consumes the events that have text, numbers and some special keys, so the parent widgets will not be notified in those cases. There are other keys that are not consumed by QLineEdit such as F2, Escape, etc that are received by the parent widget.
If you want to listen to a special key or combination of keys then you must use a QShortcut but because the OP wants to listen to all the events then a possible solution is to install an eventfilter to the QWindow associated with the window that if it receives the keyboard event when the window has the focus no matter which widget has the focus.
from PyQt5 import QtWidgets, QtCore, QtGui
class MyKey(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle(" My Key Board")
self.ui()
def ui(self):
self.tb = QtWidgets.QLineEdit()
vb = QtWidgets.QVBoxLayout(self)
vb.addWidget(self.tb)
def handle_key_press(self, key, text):
if key == QtCore.Qt.Key_A:
print("ypu pressed 'A'")
class KeyHelper(QtCore.QObject):
key_pressed = QtCore.pyqtSignal(int, str)
def __init__(self, window):
super().__init__(window)
self._window = window
self.window.installEventFilter(self)
#property
def window(self):
return self._window
def eventFilter(self, obj, event):
if obj is self._window and event.type() == QtCore.QEvent.KeyPress:
self.key_pressed.emit(event.key(), event.text())
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
myapp = QtWidgets.QApplication(sys.argv)
mywindow = MyKey()
mywindow.show()
helper = KeyHelper(mywindow.windowHandle())
helper.key_pressed.connect(mywindow.handle_key_press)
sys.exit(myapp.exec_())
I am trying to build a hover Dialog but i am stuck at the interaction between QComboBox selection and QDialog's leaveEvent. it looks like when i try to click on combobox to select something, it triggers a leaveEvent which then hides my QDialog. Why is this happening? What can i try to ensure that the Dialog is only hidden when I move my mouse outside of the Dialog?
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
class hoverDialog(QDialog):
def __init__(self, parent=None):
super().__init__()
self.setAttribute(Qt.WA_DeleteOnClose)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.v = QVBoxLayout()
self.combobox = QComboBox()
self.combobox.addItems(['Work-around','Permanent'])
self.textedit = QPlainTextEdit()
self.v.addWidget(self.combobox)
self.v.addWidget(self.textedit)
self.setLayout(self.v)
#self.setMouseTracking(True)
def leaveEvent(self, event):
self.hide()
return super().leaveEvent(event)
class Table(QWidget):
def __init__(self, parent=None):
super().__init__()
self.label4 = QLabel()
self.label4.setText("hover popup")
self.label4.installEventFilter(self)
self.checkbox1 = QCheckBox()
self.pushButton3 = QPushButton()
self.pushButton3.setText('Generate')
self.pushButton3.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
self.pushButton3.clicked.connect(self.buttonPressed)
self.hbox5 = QHBoxLayout()
self.hbox5.addWidget(self.checkbox1)
self.hbox5.addWidget(self.label4)
self.hbox5.addWidget(self.pushButton3)
self.vbox1 = QVBoxLayout()
self.vbox1.addLayout(self.hbox5)
self.setLayout(self.vbox1)
self.autoResolve = hoverDialog(self)
def eventFilter(self, obj, event):
if obj == self.label4 and event.type() == QtCore.QEvent.Enter and self.autoResolve.isHidden():
self.onHovered()
return super().eventFilter(obj, event)
def onHovered(self):
pos = QtGui.QCursor.pos()
self.autoResolve.move(pos)
self.autoResolve.show()
def buttonPressed(self):
if self.checkbox.isChecked():
print('do something..')
if __name__ == '__main__':
app = QApplication(sys.argv)
form = Table()
form.show()
app.exec_()
Looking at the sources, I believe that the origin of the problem is in Qt's behavior whenever a new popup widget is shown.
I cannot guarantee this at 100%, but in any case the simplest solution is to hide the widget only if the combo popup is not shown:
def leaveEvent(self, event):
if not self.combobox.view().isVisible():
self.hide()
Note that your approach is not really perfect: since the dialog could be shown with a geometry that is outside the current mouse position, it will not be able to hide itself until the mouse actually enters it. You should probably filter FocusOut and WindowDeactivate events also.
How to fire mouse click event on clicking in year option for QCalendarWidget.
onclick of year(2012),
i want to print some text using pyqt5
Can anyone help. Thanks in advance/
The first thing is to obtain the QSpinBox that shows the year using findChildren, then it is to detect the mouse event but as this solution points out it is not possible so a workaround is to detect the focus event:
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.calendar_widget = QtWidgets.QCalendarWidget()
self.setCentralWidget(self.calendar_widget)
self.year_spinbox = self.calendar_widget.findChild(
QtWidgets.QSpinBox, "qt_calendar_yearedit"
)
self.year_spinbox.installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.year_spinbox and event.type() == QtCore.QEvent.FocusIn:
print(self.year_spinbox.value())
return super().eventFilter(obj, event)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I want to get the value of the cell of a QTableView when the user presses Tab or when the user puts a value into the cell and presses Enter.
So I wrote the following code - but only I get the value when I click in the cell, not when pressing Tab or Enter.
def table_config(self):
setHeaders = ("CANTIDAD", "UNIDAD", "DESCRIPCION", "PRECIO UNITARIO", "PRECIO TOTAL")
self.tableWidget.setHorizontalHeaderLabels(setHeaders)
self.tableWidget.wordWrap()
self.tableWidget.alternatingRowColors()
self.tableWidget.clicked.connect(self.dataCell)
def dataCell(self, item):
data = item.data() # I got the value of the cell only when i clicked in it.
print(data)
One possible solution is to override the keyPressEvent method and filter by the key pressed:
from PyQt5 import QtCore, QtGui, QtWidgets
class TableWidget(QtWidgets.QTableWidget):
def keyPressEvent(self, event):
super().keyPressEvent(event)
if event.key() in (
QtCore.Qt.Key_Tab,
QtCore.Qt.Key_Return,
QtCore.Qt.Key_Enter,
):
it = self.currentItem()
print(it)
if it is not None:
print(it.text())
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.tableWidget = TableWidget(6, 6)
for i in range(3):
for j in range(2):
it = QtWidgets.QTableWidgetItem("{}-{}".format(i, j))
self.tableWidget.setItem(i, j, it)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.tableWidget)
lay.addWidget(QtWidgets.QLineEdit())
lay.addWidget(QtWidgets.QSpinBox())
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
I’m using PyQt5 and Python 3.6. I want to use the ENTER (or RETURN) key for dual purposes.
If the user enters text into the combo box and then hits the ENTER key, then I want the text from the combo box to be appended to a list. In all other situations, I want the ENTER key to serve as a shortcut for a push button.
I can’t find the correct decision for how the handle when ENTER is pressed. Here is a code sample. I’m looking to a decision in the returnDecision(self) function (toward the bottom of the script).
import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QShortcut
from PyQt5.QtWidgets import QComboBox
from PyQt5.QtGui import QKeySequence
from PyQt5.QtCore import Qt, QSize
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
btn = QPushButton('Button', self)
btn.move(100, 50)
btn.clicked.connect(self.btnPrint)
self.comboBox = QComboBox(self)
self.comboBox.setEditable(True)
self.comboBox.move(100, 150)
self.comboBox.setMinimumSize(QSize(150, 0))
self.comboBox.setEditText("Initial Text")
self.comboBox.editTextChanged.connect(self.cboxPrint)
enter = QShortcut(QKeySequence(Qt.Key_Return), self)
enter.activated.connect(self.returnDecision)
self.textList = []
self.show()
def btnPrint(self):
print("Button was pressed")
def btnAction(self):
print("RETURN pressed when NOT editing combo box")
self.btnPrint()
def cboxPrint(self):
print(self.comboBox.currentText())
def cboxAction(self):
print("RETURN pressed when editing combo box")
self.textList.append(self.comboBox.currentText())
print(self.textList)
def returnDecision(self):
if ENTER KEY WAS PRESSED WHILE EDITING COMBO BOX:
self.cboxAction()
else:
self.btnAction()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Any suggestions?
One way to solve this is to use a custom subclass of the QComboBox and override the keyPressEvent method. Then also implement a keyPressEvent in your widget and handle each differently.
class CustomCombo(QtWidgets.QComboBox):
enter_pressed = QtCore.pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Return:
self.enter_pressed.emit()
else:
QtWidgets.QComboBox.keyPressEvent(self, event)
# if the key is not return, handle normally
class Example(QWidget):
def __init__(self):
# Code here
self.combo_box = CustomCombo(self)
self.combo_box.enter_pressed.connect(self.cboxAction)
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Return:
self.btnAction()