How to intercept a mouse signal in a QComboBox - python

I have a custom combo box placed on a QDialog widget, and I can not catch any of the mouse signals. I sub classed QComboBox to intercept two signals not provided by QComboBox: LostFocusEvent and mouseDobleClickEvent. LostFocusEvent works well but the combo is not firing the mouse events. I need three signals on the combo box and only one suitable is provided.
I tried to set combo.grabMouse(), disregarding the documentation warnings, and the combo.doubleClicked start working, but all other widgets connected through signals start behaving erratically.
Also tried combo.view().doubleClick.connect with similar results. Also I tried other mouse events with similar results (Press- Release- etc)
Finally, I tried to to use event instead of QMouseEvent in the comboBox sub class, but it's intercepted by the focusOutEvent slot.
Mouse event work on QPushButtons including double click on QTableView widgets
Using Windows 8 Python 3.7 PyQt5.
`class Agreement(QDialog):
def __init__(self,db, address, parent=None):
super().__init__(parent= None)
self.parent = parent
.......................................
def setUi(self):
.....................................
self.comboSupplier = ComboFocus.FocusCombo(self)
self.comboSupplier.setMaximumSize(220,30)
self.comboSupplier.setEditable(True)
#self.comboSupplier.grabMouse()
self.comboSupplier.activated.connect(self.supplierChange)
self.comboSupplier.focusLost.connect(self.supplierFocusLost)
self.comboSupplier.doubleClicked.connect(self.editContact)
...........................................
def supplierChange(self):
try:
row = self.comboSupplier.currentIndex()
idx = self.comboSupplier.model().index(row,0)
self.supplierId = self.comboSupplier.model().data(idx)
self.agreementTitle[0] = self.comboSupplier.currentText()
self.setAgreementTitle()
self.okToSave[2] = int(self.supplierId)
self.okSaving()
except TypeError as err:
print('supplierChange' + type(err).__name__ + ' ' + err.args[0])
#pyqtSlot()
def editContact(self):
try:
c = Contacts(self.db,self.comboSupplier.currentText(),
APM.OPEN_EDIT_ONE, self.supplierId,parent=self)
c.show()
c.exec()
except Exception as err:
print(type(err).__name__, err-args)
#pyqtSlot(ComboFocus.FocusCombo)
def supplierFocusLost(self, combo):
try:
self.setFocusPolicy(Qt.NoFocus)
name = combo.currentText()
if combo.findText(name) > -1:
return
........................................
class FocusCombo(QComboBox):
focusLost = pyqtSignal(QComboBox)
focusGot = pyqtSignal(QComboBox)
doubleClicked = pyqtSignal(QComboBox)
def __init__(self, parent = None):
super().__init__(parent)
self.parent = parent
def mouseDoubleClickEvent(self,event=QMouseEvent.MouseButtonDblClick):
print("double click detected")
self.doubleClicked.emit(self)
def focusOutEvent(self, event):
if event.gotFocus():
self.focusGot.emit(self)
elif event.lostFocus():
self.focusLost.emit(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
cb = FocusCombo()
cb.show()
app.exec_()
sys.exit(app.exec_())
I'd like to double click on the comboBox to open a widget to edit the contact attributes on the fly.

When you set QLineEdit to editable, a QLineEdit is added, so to track your events you must use an eventFilter:
from PyQt5 import QtCore, QtGui, QtWidgets
class FocusCombo(QtWidgets.QComboBox):
focusLost = QtCore.pyqtSignal(QtWidgets.QComboBox)
focusGot = QtCore.pyqtSignal(QtWidgets.QComboBox)
doubleClicked = QtCore.pyqtSignal(QtWidgets.QComboBox)
def setEditable(self, editable):
super(FocusCombo, self).setEditable(editable)
if self.lineEdit() is not None:
self.lineEdit().installEventFilter(self)
def eventFilter(self, obj, event):
if obj is self.lineEdit():
if event.type() == QtCore.QEvent.MouseButtonDblClick:
self.doubleClicked.emit(self)
"""elif event.type() == QtCore.QEvent.MouseButtonPress:
print("press")
elif event.type() == QtCore.QEvent.MouseButtonRelease:
print("release")"""
return super(FocusCombo, self).eventFilter(obj, event)
def mouseDoubleClickEvent(self,event):
print("double click detected")
self.doubleClicked.emit(self)
super(FocusCombo, self).mouseDoubleClickEvent(event)
def focusOutEvent(self, event):
if event.gotFocus():
self.focusGot.emit(self)
elif event.lostFocus():
self.focusLost.emit(self)
super(FocusCombo, self).focusOutEvent(event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
cb = FocusCombo()
cb.addItems(list("abcdef"))
cb.setEditable(True)
cb.doubleClicked.connect(print)
cb.show()
sys.exit(app.exec_())

Related

QWidget cannot catch ESCAPE, BACKSPACE or C-x key press events

I am catching key press events by overriding the KeyPressEvent method of my class, inheriting from QWidget, but I cannot see key press events for the ESCAPE and BACKSPACE keys, as well as C-x or again C-c. I can see key release events though. Who catches them ?
class KeyCaptureWidget(QWidget):
# init…
def keyPressEvent(self, event):
key = event.key()
logging.info("key press: {}".format(key))
def keyReleaseEvent(self, event):
key_code = event.key()
logging.info("key release: {}".format(key_code))
The difference between C-x and say C-b is the following:
pressing C-b prints: control is pressed, b is pressed, b is released, control is released.
pressing C-x prints: control is pressed, [nothing], x is released, control is released.
In my QWidget, I use a QVBoxLayout to which I put two QWebEngine views. I tried to override the key press method of the QWebEngineView, but they don't seem to catch anything (and this is the behaviour I expected).
def __init__(self):
self.qtwindow = KeyCaptureWidget()
self.layout = QVBoxLayout()
self.view1 = QWebEngineView() # or a custom one to override keyPressEvent
# self.view2 = the same
self.layout.addWidget(self.view1)
self.layout.addWidget(self.view2)
self.qtwindow.setLayout(self.layout)
self.qtwindow.show()
I tried to catch these with event filters on my QWidget class but again, no luck: I see only a key release for ESC or BACKSPACE.
def __init__(self):
super().__init__()
self.installEventFilter(self)
def eventFilter(self, source, event):
logging.info("event filter: {}".format(event))
if event.type() == QEvent.KeyPress:
logging.info(" event filter key PRESS")
if event.type() == QEvent.KeyRelease:
logging.info(" event filter key RELEASE")
return True
How can I catch them ? Thank you.
Events do not necessarily propagate among all widgets, if a widget consumes it then it will no longer propagate to the parent. In the case of the keyboard events will only be consumed first by the widget that has the focus, in your case QWebEngineView consumes them before and prevents it from being projected in other widgets. If you want to hear events from the keyboard of a window then you must use the QShortcuts, and for that you must create a QShortcut:
Ctrl + C: QtGui.QKeySequence("Ctrl+C")
Ctrl + X: QtGui.QKeySequence("Ctrl+X")
Esc: QtGui.QKeySequence("Escape")
Backspace: QtGui.QKeySequence("Backspace")
Considering the above, the solution is:
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.m_view1 = QtWebEngineWidgets.QWebEngineView()
self.m_view2 = QtWebEngineWidgets.QWebEngineView()
self.m_view1.load(QtCore.QUrl("https://stackoverflow.com/questions/56890831"))
self.m_view2.load(QtCore.QUrl("https://doc.qt.io/"))
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.m_view1)
lay.addWidget(self.m_view2)
QtWidgets.QShortcut(
QtGui.QKeySequence("Ctrl+C"), self, activated=self.on_Ctrl_C
)
QtWidgets.QShortcut(
QtGui.QKeySequence("Ctrl+X"), self, activated=self.on_Ctrl_X
)
QtWidgets.QShortcut(
QtGui.QKeySequence("Escape"), self, activated=self.on_Escape
)
QtWidgets.QShortcut(
QtGui.QKeySequence("Backspace"), self, activated=self.on_Backspace
)
#QtCore.pyqtSlot()
def on_Ctrl_C(self):
print("Ctrl+C")
#QtCore.pyqtSlot()
def on_Ctrl_X(self):
print("Ctrl+X")
#QtCore.pyqtSlot()
def on_Escape(self):
print("Escape")
#QtCore.pyqtSlot()
def on_Backspace(self):
print("Backspace")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

How to find out to which window the focus was passed on for a "WindowDeactivate" event?

By installing an event filter, it is possible to see if a window has been activated/deactivated (QtCore.QEvent.WindowActivate, QtCore.QEvent.WindowDeactivate).
class SomeWidget(QtWidgets.QWidget, object):
# ...
def __init__(self):
# ...
self.installEventFilter(self)
# ...
def eventFilter(self, object, event):
if event.type() == QtCore.QEvent.WindowDeactivate:
print('Window was deactivated.')
if event.type() == QtCore.QEvent.WindowActivate:
print('Window was activated.')
Is it possible to find out A) to which other window (of the same application) the focus was passed on, and B) whether the entire application was inactivated (that is: none of the windows is active)?
I wish the solution to be "minimal invasive" in that sense that I don't have to install event filters in all of my candidate windows. Is it possible to spy out other windows from within the current widget?
I'm interested in this information because I would like to capture some usage metrics for my application.
If you want to monitor the status of the windows you can use the notify method of QApplication:
from PyQt5 import QtCore, QtWidgets
class Application(QtWidgets.QApplication):
def notify(self, obj, event):
if event.type() == QtCore.QEvent.WindowDeactivate:
print("{} was deactivated:".format(obj))
if event.type() == QtCore.QEvent.WindowActivate:
print("{} was activated.".format(obj))
return super().notify(obj, event)
if __name__ == "__main__":
import sys
app = Application(sys.argv)
windows = []
for _ in range(3):
w = QtWidgets.QWidget()
w.show()
windows.append(w)
sys.exit(app.exec_())
Using the previous method I have implemented a signal that sends the activated window with the function QApplication::activeWindow():
from PyQt5 import QtCore, QtWidgets
class Application(QtWidgets.QApplication):
activateChanged = QtCore.pyqtSignal(QtWidgets.QWidget)
def __init__(self, l):
super().__init__(l)
self._window_activate = None
def notify(self, obj, event):
if event.type() == QtCore.QEvent.WindowDeactivate:
QtCore.QTimer.singleShot(0, self.on_timeout)
if event.type() == QtCore.QEvent.WindowActivate:
QtCore.QTimer.singleShot(0, self.on_timeout)
return super().notify(obj, event)
def on_timeout(self):
if self._window_activate != QtWidgets.QApplication.activeWindow():
self._window_activate = QtWidgets.QApplication.activeWindow()
self.activateChanged.emit(self._window_activate)
if __name__ == "__main__":
import sys
app = Application(sys.argv)
app.activateChanged.connect(print)
windows = []
for _ in range(5):
w = QtWidgets.QWidget()
w.show()
windows.append(w)
sys.exit(app.exec_())

How do I make a context menu for each item in a QListWidget?

I'm working on a QGIS plugin, where the UI is made with PyQt. I have a QListWidget and a function that fills it. I'd like to add a context menu for each item with only one option: to open another window.
I'm having trouble searching for info, since most of it works only on PyQt4 and I'm using version 5. The QListWidget that I want to add a context menu on is ds_list_widget. Here's some of the relevant code.
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'dialog_base.ui'))
class Dialog(QDialog, FORM_CLASS):
def __init__(self, parent=None):
...
self.p_list_widget = self.findChild(QListWidget, 'projects_listWidget')
self.p_list_widget.itemClicked.connect(self.project_clicked)
self.ds_list_widget = self.findChild(QListWidget, 'datasets_listWidget')
self.ds_list_widget.itemClicked.connect(self.dataset_clicked)
...
def project_clicked(self, item):
self.fill_datasets_list(str(item.data(Qt.UserRole)))
self.settings.setValue('projectIdValue', str(item.data(Qt.UserRole)))
def fill_datasets_list(self, project_id):
self.ds_list_widget.clear()
dataset_list = self.anotherClass.fetch_dataset_list(project_id)
for dataset in dataset_list:
#Query stuff from remote
...
item = QListWidgetItem(ds_name, self.ds_list_widget)
item.setIcon(self.newIcon(ds_img))
item.setData(Qt.UserRole, ds_id)
self.ds_list_widget.addItem(item)
self.ds_list_widget.setIconSize(self.iconSize)
Since your list-widget is created by Qt Designer, it is probably easiest to install an event-filter on it and trap the context-menu event. With that in place, the rest is quite straightforward - here is a simple demo:
import sys
from PyQt5 import QtCore, QtWidgets
class Dialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__()
self.listWidget = QtWidgets.QListWidget()
self.listWidget.addItems('One Two Three'.split())
self.listWidget.installEventFilter(self)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.listWidget)
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.ContextMenu and
source is self.listWidget):
menu = QtWidgets.QMenu()
menu.addAction('Open Window')
if menu.exec_(event.globalPos()):
item = source.itemAt(event.pos())
print(item.text())
return True
return super(Dialog, self).eventFilter(source, event)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Dialog()
window.setGeometry(600, 100, 300, 200)
window.show()
sys.exit(app.exec_())
PS:
You should also note that code like this:
self.p_list_widget = self.findChild(QListWidget, 'projects_listWidget')
is completely unnecessary. All the widgets from Qt Designer are automatically added as attributes to the form class using the object-name. So your code can be simplified to this:
self.projects_listWidget.itemClicked.connect(self.project_clicked)
self.datasets_listWidget.itemClicked.connect(self.dataset_clicked)
there is no need to use findChild.
In addition to the answer above, you can also set multiple QAction() submenu items to do multiple things. As you would a normal menu.
One way is to edit your eventFilter so that menu.exec() becomes a variable:
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.ContextMenu and source is self.listWidget):
menu = QtWidgets.QMenu()
open_window_1 = QAction("Open Window 1")
open_window_2 = QAction("Open Window 2")
menu.addAction(open_window_1)
menu.addAction(open_window_2)
menu_click = menu.exec(event.globalPos())
try:
item = source.itemAt(event.pos())
except Exception as e:
print(f"No item selected {e}")
if menu_click == open_window_1 :
print("Opening Window 1...")
# Your code here
if menu_click == open_window_2 :
print("Opening Window 2...")
# Your code here
# and so on... You can now add as many items as you want
return True
return super(Dialog, self).eventFilter(source, event)

Update a QLineEdit on a WheelEvent when scroll bar is already set

I'm trying to update a QLineEdit when I do a wheel move on the mouse and if I press a number on the keyboard at the same time. Unfortunatly, I don't see a mouse wheel event for QLineEdit widget so I don't understand how I can set a signal to each QLineEdit. The other issue I have is as the QLineEdit are already in a scroll bar environment, I cannot detect all wheel event because the scroll is done first.
For instance with this code:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.centralTabs= QTabWidget()
self.setCentralWidget(self.centralTabs)
self.setFixedWidth(200)
self.setFixedHeight(200)
#tab Model selection
self.tab_ModelSelect = QWidget()
self.centralTabs.addTab(self.tab_ModelSelect,"Label")
self.groupscrolllayouttest = QHBoxLayout() ####
self.groupscrollbartest = QGroupBox() ####
self.mainHBOX_param_scene = QVBoxLayout()
for i in range(10):
LineEdit = QLineEdit(str(i))
LineEdit.setFixedWidth(200)
self.mainHBOX_param_scene.addWidget(LineEdit)
self.installEventFilter(self)
scroll = QScrollArea()
widget = QWidget(self)
widget.setLayout(QVBoxLayout())
widget.layout().addWidget(self.groupscrollbartest)
scroll.setWidget(widget)
scroll.setWidgetResizable(True)
self.groupscrollbartest.setLayout(self.mainHBOX_param_scene)
self.groupscrolllayouttest.addWidget(scroll)
self.tab_ModelSelect.setLayout(self.groupscrolllayouttest)
def eventFilter(self, widget, event):
if (event.type() == QEvent.Wheel) :
# get which key is pressed
# if the key is a number, put the number in 'num' variable
# get on which QLineEdit the wheel was make
# set the text of that QLineEdit to previous value +- num
event.ignore()
return QWidget.eventFilter(self, widget, event)
def main():
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
# ex.showMaximized()
ex.show()
sys.exit(app.exec_( ))
if __name__ == '__main__':
main()
I tried to something with wheelevent but as mention, I don't enter in this function because the scroll bar is activated first. I tried to test if the wheel event happend on a QLineEdit but I even struggle to do that...
What I'm seeking to do is when I do a wheelevent with the mouse on a QlineEdit with the '5' key pressed, I want increase or decrease the QLineEdit text by 5 according to the direction of the mouse wheel.
I red some post with eventfilter (as How to get Click Event of QLineEdit in Qt?) but I don't understand how does this work.
In my eventFilter function, I need to do several step:
# get which key is pressed
# if the key is a number, put the number in 'num' variable
# get on which QLineEdit the wheel was make
# set the text of that QLineEdit to previous value +- num
but I don't know how to make them. In particular getting the pressed key and knowing on which QlineEdit the wheel was made.
If you wish that all QLineEdit have that behavior then it is appropriate that you create your own class and overwrite the necessary events, to avoid that when you move the scroll when the pointer is inside the QLineEdit and pressing an established key, we accept the event so that it does not propage.
Another recommendation is not to use the 5 key since this is a text that QLineEdit can handle causing problems, for this you can use the SHIFT key:
class LineEdit(QLineEdit):
KEY = Qt.Key_Shift
def __init__(self, *args, **kwargs):
QLineEdit.__init__(self, *args, **kwargs)
self.isKeyPressed = False
def keyPressEvent(self, event):
if event.key() == LineEdit.KEY:
self.isKeyPressed = True
QLineEdit.keyPressEvent(self, event)
def keyReleaseEvent(self, event):
if event.key() == LineEdit.KEY:
self.isKeyPressed = False
QLineEdit.keyReleaseEvent(self, event)
def wheelEvent(self, event):
if self.isKeyPressed:
delta = 1 if event.angleDelta().y() > 0 else -1
fn = self.font()
fn.setPointSize(fn.pointSize() + delta)
self.setFont(fn)
event.accept()
The complete example:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
class LineEdit(QLineEdit):
KEY = Qt.Key_Shift
def __init__(self, *args, **kwargs):
QLineEdit.__init__(self, *args, **kwargs)
self.isKeyPressed = False
def keyPressEvent(self, event):
if event.key() == LineEdit.KEY:
self.isKeyPressed = True
QLineEdit.keyPressEvent(self, event)
def keyReleaseEvent(self, event):
if event.key() == LineEdit.KEY:
self.isKeyPressed = False
QLineEdit.keyReleaseEvent(self, event)
def wheelEvent(self, event):
if self.isKeyPressed:
delta = 1 if event.angleDelta().y() > 0 else -1
fn = self.font()
fn.setPointSize(fn.pointSize() + delta)
self.setFont(fn)
event.accept()
class SurfViewer(QMainWindow):
def __init__(self, parent=None):
super(SurfViewer, self).__init__()
self.parent = parent
self.centralTabs= QTabWidget()
self.setCentralWidget(self.centralTabs)
self.setFixedWidth(200)
self.setFixedHeight(200)
#tab Model selection
self.tab_ModelSelect = QWidget()
self.centralTabs.addTab(self.tab_ModelSelect,"Label")
self.groupscrolllayouttest = QHBoxLayout() ####
self.groupscrollbartest = QGroupBox() ####
self.mainHBOX_param_scene = QVBoxLayout()
for i in range(10):
le = LineEdit(str(i))
le.setFixedWidth(200)
self.mainHBOX_param_scene.addWidget(le)
self.installEventFilter(self)
scroll = QScrollArea()
widget = QWidget(self)
widget.setLayout(QVBoxLayout())
widget.layout().addWidget(self.groupscrollbartest)
scroll.setWidget(widget)
scroll.setWidgetResizable(True)
self.groupscrollbartest.setLayout(self.mainHBOX_param_scene)
self.groupscrolllayouttest.addWidget(scroll)
self.tab_ModelSelect.setLayout(self.groupscrolllayouttest)
def main():
app = QApplication(sys.argv)
ex = SurfViewer(app)
ex.setWindowTitle('window')
# ex.showMaximized()
ex.show()
sys.exit(app.exec_( ))
if __name__ == '__main__':
main()

Implementing keyPressEvent in QWidget

I have a QDialog window that has a continue button. The continue button is the default button because whenever I press the enter key, the continue button is pressed. I discovered something strange: when I press the enter key three times, the continue button presses three times. However, when I press it a fourth time, the whole window closes. I have a cancel button right below the continue button that closes the window, but I don't make the cancel button the default button or anything.
I wanted to override the keyPressEvent so that whenever I'm in the window, the enter button will always be connected to the continue button.
This is what I have right now:
class ManualBalanceUI(QtGui.QWidget):
keyPressed = QtCore.pyqtSignal()
def __init__(self, cls):
super(QtGui.QWidget, self).__init__()
self.window = QtGui.QDialog(None, QtCore.Qt.WindowSystemMenuHint)
self.ui = uic.loadUi('ManualBalanceUI.ui', self.window)
self.keyPressed.connect(self.on_key)
def keyPressEvent(self, event):
super(ManualBalanceUI, self).keyPressEvent(event)
self.keyPressed.emit(event)
def on_key(self, event):
if event.key() == QtCore.Qt.Key_Enter and self.ui.continueButton.isEnabled():
self.proceed() # this is called whenever the continue button is pressed
elif event.key() == QtCore.Qt.Key_Q:
self.window.close() # a test I implemented to see if pressing 'Q' would close the window
def proceed(self):
...
...
However, this doesn't seem to be doing anything right now. Pressing 'Q' doesn't close the window, and I can't really tell if the 'enter' key is working or not.
I looked at this question beforehand: PyQt Connect to KeyPressEvent
I also reviewed all the documentation on SourceForge. Any help would be greatly appreciated!
You can do two ways and one is simply re implement keyPressevent with out any fancy work. Like this
from PyQt4 import QtCore, QtGui
import sys
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.show()
def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_Q:
print "Killing"
self.deleteLater()
elif event.key() == QtCore.Qt.Key_Enter:
self.proceed()
event.accept()
def proceed(self):
print "Call Enter Key"
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Or as you tried with signals, in your case you where missing to implement this signal properly, here is updated version.
class Example(QtGui.QWidget):
keyPressed = QtCore.pyqtSignal(QtCore.QEvent)
def __init__(self):
super(Example, self).__init__()
self.setGeometry(300, 300, 250, 150)
self.show()
self.keyPressed.connect(self.on_key)
def keyPressEvent(self, event):
super(Example, self).keyPressEvent(event)
self.keyPressed.emit(event)
def on_key(self, event):
if event.key() == QtCore.Qt.Key_Enter and self.ui.continueButton.isEnabled():
self.proceed() # this is called whenever the continue button is pressed
elif event.key() == QtCore.Qt.Key_Q:
print "Killing"
self.deleteLater() # a test I implemented to see if pressing 'Q' would close the window
def proceed(self):
print "Call Enter Key"
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
If you're looking at this in 2019, and If Achayan's method does not work for you then check a couple things :
1) Is the keyPressEvent overridden in a child of the main window or main widget? The child's function will override the methods on the parent (at least when using a QMainWindow with setCentralWidget). If this is the case, then the signal might not be emitted like you expect
2) Do you have a widget that handles key inputs differently than QWidget? For example, if the focus is in a QTextEdit object, then key inputs will not be sent to keyPressEvent. Shift focus to another widget
For example, observe the output of the following :
class myDialog(QtWidgets.QDialog):
keyPressed = QtCore.pyqtSignal(QtCore.QEvent)
def __init__(self, parent=None):
super(myDialog, self).__init__(parent)
self.keyPressed.connect(self.on_key)
leftGroupBox = QtWidgets.QGroupBox('A Group Label')
text = QtWidgets.QTextEdit('Enter some text')
layout = QtWidgets.QVBoxLayout()
layout.addWidget(text)
leftGroupBox.setLayout(layout)
rightGroupBox = QtWidgets.QGroupBox('Label Options')
label1 = QtWidgets.QCheckBox('ahu')
layout = QtWidgets.QVBoxLayout()
layout.addWidget(label1)
rightGroupBox.setLayout(layout)
# Create the main layout
mainLayout = QtWidgets.QGridLayout()
mainLayout.addWidget(leftGroupBox)
mainLayout.addWidget(rightGroupBox)
self.setLayout(mainLayout)
def keyPressEvent(self, event):
# keyPressEvent defined in child
print('pressed from myDialog: ', event.key())
# self.keyPressed.emit(event) # Emit is hidden in child
def on_key(self, event):
print('event received # myDialog')
if event.key() == QtCore.Qt.Key_0:
print(0)
class MainWindow(QtWidgets.QMainWindow):
keyPressed = QtCore.pyqtSignal(QtCore.QEvent)
def __init__(self):
super(MainWindow, self).__init__()
self.keyPressed.connect(self.on_key)
self.setCentralWidget(myDialog())
self.show()
def keyPressEvent(self, event):
super(MainWindow, self).keyPressEvent(event)
print('pressed from MainWindow: ', event.key())
self.keyPressed.emit(event)
def on_key(self, event):
print('event received # MainWindow')
if event.key() == QtCore.Qt.Key_0:
print(0)
if __name__ == '__main__':
ex = MainWindow()
Output # console : (no event is received #myDialog OR MainWindow)
pressed from myDialog: 48
For Achayan's answer, I succeeded with the code.
It may be the enter key and the return key.
Try Key_Enter and Key_Return. They are different on my keyboard.
QtCore.QObject.connect(self.ui.search_box, QtCore.SIGNAL("textChanged()"), self.fucn1)
Whenever text is changed in search_box function fucn1 is called.
Works for pyqt4

Categories