KeypressEvent not working, How to correct it? - pyqt4

I am trying to get keypressevent work with the following code
import sys,
from PyQt4 import QtCore, QtGui
class Ui_MainWindow(QtGui.QWidget):
def __init__(self):
super(Ui_MainWindow, self).__init__()
def keyPressEvent(self, event):
print 'a'
def setupUi(self, MainWindow):
MainWindow.setObjectName(("MainWindow"))
MainWindow.resize(371, 345)
MainWindow.setMaximumSize(QtCore.QSize(401, 600))
MainWindow.setWindowIcon(QtGui.QIcon('icons/icon.png'))
screen = QtGui.QDesktopWidget().screenGeometry()
mysize = MainWindow.geometry()
hpos = ( screen.width() - mysize.width() ) / 2
vpos = ( screen.height() - mysize.height() ) / 2
MainWindow.move(hpos, vpos)
#some GUI
MainWindow.setCentralWidget(self.centralwidget)
cd=MainWindow.centralWidget()
cd.setFocusPolicy(QtCore.Qt.StrongFocus)
cd.setFocus()
self.actionHardware = QtGui.QAction(MainWindow)
self.actionHardware.setObjectName(("actionHardware"))
self.retranslateUi(MainWindow)
#COnnect odes
def retranslateUi(self, MainWindow):
#sime button text codes
if __name__=="__main__" :
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
The code was partially generated using QTDesigner. I noticed that replacing Mainwindow.show() by ui.show() enables keypressevent but at the cost of not showing any buttons i create in the Mainwindow central widget

It looks like the problem is in the way you are re-using the code output by Designer. You defined Ui_MainWindow.keyPressEvent, and created an instance "ui" of the class. However: "ui" is never directly incorporated into the GUI anywhere (ui.setupUi adds other widgets, but not itself, to MainWindow) and thus events are never delivered to ui.
My approach would look more like this:
class Ui_MainWindow(object): ## note this does not need to inherit QWidget
... ## and ideally, this code should not be changed
... ## after designer generates it
...
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def keyPressEvent(self, ev):
print "key press"
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
MainWindow = Window()
MainWindow.show()
sys.exit(app.exec_())

Related

pyqt signal from a window not changing the main window widgets

I can pass values between two windows using signal,
and I want the plain text change, while I press a button from another window.
but the insertPlainText and even text.show() are not working
I've tried sending the signal to the init part of the Mainwindow,
tried update, repaint, but none of them works.
appreciate for any of your help, thanks!
the search_send method in class SearchWindow to MainWindow method test_
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.tag_box.hide()
def test_(self, i): # -------problem here------------------
print(i) // <- value here were right
self.ui.tag_box.insertPlainText(i) # -------Plain Text does not change-------
self.ui.tag_box.show()# -------Plain Text does not show either--------------
class SearchWindow(QtWidgets.QMainWindow):
signal=pyqtSignal(str)
def __init__(self, endpoint=None, user=None, password=None, points_link=None):
super(SearchWindow, self).__init__()
self.ui = Ui_Search()
self.ui.setupUi(self)
self.ui.pushButton_2.clicked.connect(self.search_send)
def search_send(self): # -------problem here------------------
tag_list = [tag1,tag2, tag3]
otherClass = MainWindow()
self.signal.connect(otherClass.test_)
for k in tag_list:
self.signal.emit(k)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
sys.exit(app.exec_())
As we're unclear what Ui_Dialog contains, I can't tell what's wrong exactly, but can show you how Signal should be used.
This is example of Signal that's transferring text to Slot. Name may differ in PyQt5 - change accordingly.
from PySide2.QtWidgets import QWidget, QApplication, QPlainTextEdit, QTextEdit, QVBoxLayout
from PySide2.QtCore import Signal, Slot
import sys
class MainWindow(QWidget):
sig = Signal(str)
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Main")
self.layout = QVBoxLayout()
self.text = QTextEdit()
self.layout.addWidget(self.text)
self.setLayout(self.layout)
self.text.textChanged.connect(self.onChange)
def onChange(self):
self.sig.emit(self.text.toPlainText())
class SubWindow(QWidget):
def __init__(self, connect_target: MainWindow):
super(SubWindow, self).__init__()
self.setWindowTitle("Sub")
self.layout = QVBoxLayout()
self.text = QPlainTextEdit()
self.layout.addWidget(self.text)
self.setLayout(self.layout)
connect_target.sig.connect(self.onSignal)
#Slot(str)
def onSignal(self, text):
self.text.insertPlainText(text + '\r\n')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
window_sub = SubWindow(window)
window_sub.show()
sys.exit(app.exec_())
Anything inside Main will be inserted to QPlainTextEdit as you wanted.

Switching between windows PyQt designer

I have been trying to develop a software in PyQt5.
I have 3 windows : 1) login
2) dashboard
3) appointments
Now I can navigate properly from login -> dashboard -> appointments perfectly.
But when I press pushbutton for back from appointments, it doesn't come back to dashboard.
But if I go from dashboard->appointments , the pushbutton works for 1 time.
I have removed irrelevant lines from the code to make analysis simpler.
login window class :
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.MainWindow = MainWindow
def retranslateUi(self, MainWindow):
self.pushButton.clicked.connect(self.next)
def next(self):
ui = Ui_MainWindow2()
ui.setupUi(self.MainWindow)
self.MainWindow.show()
dashboard window class :
class Ui_MainWindow2(object):
def setupUi(self, MainWindow):
self.MainWindow = MainWindow
def retranslateUi(self, MainWindow):
self.pushButton.clicked.connect(self.next)
def next(self):
ui = Ui_MainWindow3()
ui.setupUi(self.MainWindow)
self.MainWindow.show()
appointment window class :
class Ui_MainWindow3(object):
def setupUi(self, MainWindow):
self.MainWindow = MainWindow
def retranslateUi(self, MainWindow):
self.pushButton.clicked.connect(self.back)
def back(self):
ui = Ui_MainWindow2()
ui.setupUi(self.MainWindow)
self.MainWindow.show()
Application starts from file login.py which has :
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
The forward navigation always work, the backward one keeps failing...
Any help or suggestions will be very welcome...
Turns out I was writing the next or back function slightly differently than it should have been. The next and back functions should have been like this :
def next(self):
self.window = QtWidgets.QMainWindow()
self.ui = Ui_MainWindow2()
self.ui.setupUi(self.window)
self.oldWindow.hide()
self.window.show()
where self.oldWindow is the reference to the original window of the class enclosing the function next. This is also same for the back function.

Function is not run when connecting Button to it in PyQt4

I m new to PyQt4 and having problems when trying to connect a button to a function.
I m using PyQt 4.11.4.
Neither the clicked.connect method nor the line in the comment below seemed to work.
from PyQt4 import QtGui, QtCore
import sys
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
def setupUi(self, Window):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(200, 200)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setGeometry(0,0,100,100)
MainWindow.setCentralWidget(self.centralwidget)
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(100, 50, 55, 20))
self.pushButton.setText("Run")
self.pushButton.clicked.connect(self.run)
#OR QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL('clicked()'),self.run)
def run(self):
print("ok")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
Window().setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
First of all, by placing statements directly after the __name__ == "__main__" test you introduce global variables. For instance the MainWindow variable is global and is subsequently altered in the Window.setupUi method. This is undesirable. It's better to create a main function and call only that. For example by changing those lines into this...
def main():
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
Window().setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
you will get a run-time error and thus notice something's wrong.
By the way, it is the convention in Python to start class names with an upper case character and objects with a lower case. Therefore, at first glance I thought that MainWindow was a class. It is, however, an object and should better be renamed to mainWindow. Notice how the StackOverflow syntax highlighting colors all identifiers that start with an capital letter light blue?
So, the issue with the signal is that you create two main window objects: first by MainWindow = QtGui.QMainWindow() and then on the next line by Window().setupUi(MainWindow). On that second line you call setupUi with the self parameter set to a temporary Window object, and the Window parameter set to a QtGui.QMainWindow object (MainWindow). It's not surprising that this doesn't work, it is actually a bit surprising it does something at all.
Finally, it is strongly recommended to use layouts in Qt to arrange the widgets. This makes the calls to setGeometry() superfluous. Adding widgets to a layout also set's their parent, so you don't need to do this separately then. I think you definitely should read the docs on layout management (except the last section on writing your own layout manager).
Apply all the advice above and you get something like this...
from PyQt4 import QtGui, QtCore
import sys
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self._setupUi()
def _setupUi(self):
self.resize(200, 200)
# the central widget is called my widget to prevent clashes with
# the centralWidget() function.
self.mainWidget = QtGui.QWidget()
self.setCentralWidget(self.mainWidget)
self.mainLayout = QtGui.QVBoxLayout()
self.mainWidget.setLayout(self.mainLayout)
self.pushButton = QtGui.QPushButton()
self.pushButton.setText("Run")
self.mainLayout.addWidget(self.pushButton)
self.pushButton.clicked.connect(self.run)
def run(self):
print("ok")
def main():
app = QtGui.QApplication(sys.argv)
mainWindow = Window()
mainWindow.setObjectName("mainWindow") # can be omitted.
mainWindow.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

How to avoid the child QMainWindow disappearing?

When I click the button, "ChildWindow" will flash and disappear. Then If I add the function exec_(), it will report an "AttributeError" because "QMainWindow" don't have this attribute.
How to modify the function "showChildWindow" so that it can work well? Thank you.
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("MainWindow Window!")
self.setGeometry(400, 400, 100, 100)
self.centerWidget = QtGui.QWidget()
self.setCentralWidget(self.centerWidget)
self.pushButton = QtGui.QPushButton("&Button")
layout = QtGui.QVBoxLayout()
layout.addWidget(self.pushButton)
self.centerWidget.setLayout(layout)
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("Child Window!")
def showChildWindow():
mw = MainWindow()
child_win = ChildWindow(mw)
child_win.show()
#child_win.exec_() #AttributeError: 'ChildWindow' object has no attribute 'exec_'
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
QtCore.QObject.connect(myapp.pushButton,QtCore.SIGNAL("clicked()"),showChildWindow)
sys.exit(app.exec_())
This program can work well.
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("MainWindow Window!")
self.setGeometry(400, 400, 100, 100)
self.centerWidget = QtGui.QWidget()
self.setCentralWidget(self.centerWidget)
pushButton = QtGui.QPushButton("&Button")
layout = QtGui.QVBoxLayout()
layout.addWidget(pushButton)
self.centerWidget.setLayout(layout)
QtCore.QObject.connect(pushButton,QtCore.SIGNAL("clicked()"),self.showChildWindow)
def showChildWindow(self):
self.child_win = ChildWindow(self)
self.child_win.show()
class ChildWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle("Child Window!")
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())
The real question appears to be: how do I access the main-window from other modules in my application?
My preferred general solution to this problem is to sub-class QApplication and add a simple accessor method, like this:
class Application(QtGui.QApplication):
def __init__(self):
QtGui.QApplication.__init__(self, sys.argv)
self._window = None
def window(self):
if self._window is None:
self._window = MainWindow()
return self._window
if __name__ == "__main__":
app = QtGui.qApp = Application()
app.window().show()
sys.exit(app.exec_())
With that in place, you can easily get access the methods of the main-window in other modules like this:
from PyQt4 import QtGui
QtGui.qApp.window().showChildWindow()
I had the same problem. The child QMainWindow would randomly disappear while interacting with the parent window.
This is the bad source code that causes this problem:
def showChildWindow(self):
child_win = ChildWindow()
child_win.show()
This is the good source code that fixes the problem:
def showChildWindow(self):
child_win = ChildWindow(self)
child_win.show()
When you instantiate the child window, make sure you pass the parent self.

PyQt keyPressEvent not triggered from QDialog

I have a simple example of of a dialog window that has the keyPressEvent method. However, no matter what is typed when the sub window has focus, the event is not triggered.
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import PyQt4.Qt
class KpeWindow(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
main = QVBoxLayout(self)
label = QLabel(self)
label.setText('Test the keyPressEvent')
self.adjustSize()
self.setLayout(main)
def keyPressEvent(self, event):
QMessageBox.warning(self, 'MDI', 'keyPressEvent')
super().keyPressEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('KeyPressEvent Test')
child = KpeWindow()
self.setCentralWidget(child)
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
The following code works:
class KpeWindow(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self,parent)
main = QVBoxLayout(self)
label = QLabel(self)
label.setText('Test the keyPressEvent')
main.addWidget(label)
self.adjustSize()
self.setLayout(main)
def keyPressEvent(self, event):
QMessageBox.warning(self, 'MDI', 'keyPressEvent')
self.parent().keyPressEvent(event)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle('KeyPressEvent Test')
main = QVBoxLayout(self)
child = KpeWindow(self)
child.setFocusPolicy(Qt.StrongFocus)
self.setFocusProxy(child)
main.addWidget(child)
child.setFocus(True)
self.adjustSize()
self.setLayout(main)
I am not sure which of my changes work, I suspect setFocusProxy. In general I would recommend using QWidget as the child, and putting things into layouts even when there are no siblings.
The keyPressEvent is sensitive to the focus policy. In your example, the event is going to the QMainWindow (if you move the keyPressEvent to there, it does receive key events).
Is there any reason to have a dialog within a window? If you launch the dialog in the usual way, using child.show(), child.exec_() instead of setCentralWidget, it shows in a separate window and captures the key event.

Resources