accessing QtGui objects created by pyQt - python

So I'm quit new to working with UI in python. I'm not really grasping a core concept and i think this simple question will help flip on the light switch.
As seen in the code snippet below, I imported a ui file made in Qt. This ui has a pushbutton on it. How do I make a click event on that button? I have gone through tutorials on how to code a button and use it. I understand that. It is the question of how to access the objects and manipulate the objects that are created by the ui file. What i really want to do is see how to perform a function (or instantiate a class or whatever) when a button is clicked. that function being one that i wrote. baby steps though. any answers and elaborations would be appreciated.
import sys
from PyQt4 import QtGui, uic, QtCore
class MyWindow(QtGui.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
uic.loadUi('myWidget.ui', self)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MyWindow()
sys.exit(app.exec_())
like i said. very simple question but I'm just not really grasping the core concept here. thanks you.

self.ui=uic.loadUi('curveViewer.ui', self)
#where `your_pushbutton` is the button name specified in your .ui file:
self.ui.your_pushbutton.clicked.connect(self.onBtnClicked)
or just:
uic.loadUi('curveViewer.ui', self)
self.your_pushbutton.clicked.connect(self.onBtnClicked)
then define method onBtnClicked inside your class MyWindow:
def onBtnClicked():
print 'pushbutton clicked'
see New-style Signal and Slot Support
btw, it's better to remove self.show(), and make it:
window = MyWindow()
window.show()

Related

PyQt4: Difference between QtCore.QCoreApplication.instance().quit and self.close?

I've been doing a lot of research and have been unable to come up with anything describing this particular line of code in PyQt4. Like many others learning PyQt, I've been following zetcode's PyQt4 tutorial. I'm still somewhat of a beginner in Python, but I'm doing my best to understand each line of code as I go through here, and one thing has me stumped:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
qbtn = QtGui.QPushButton('Quit', self)
qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I understand everything except this line:
qbtn.clicked.connect(QtCore.QCoreApplication.instance().quit)
Can someone explain what exactly is going on here, specifically with instance().quit? I know that obviously it quits the program, I just don't understand what the code is actually doing and why. The only info I've been able to dig up on this is that instance() "returns a pointer to the application's QCoreApplication (or QApplication) instance", but this doesn't really help me understand (maybe I'm just not experienced enough, I don't know).
Additionally, is there a functional difference between the above line of code and this:
qbtn.clicked.connect(self.close)
I found this thread which kind of touches on this whole topic, but the only response that mentions self.close as a possible alternative was downvoted with no explanation. Any help or guidance would be much appreciated, thank you!
qbtn.clicked is the signal emitted by the button.
QCoreApplication.instance() is the main application object.
So it's connecting the button signal to the quit slot of the application.
In your second example the button will just close the window that owns the button. If the application has more than one window, or doesn't automatically quit on last window close, it will still be running.

using qt with custom loop in python

I have been experimenting around with using QT in python3 and figured out how to make a simple .ui file and import it directly into a python program. However I have to use python QT app while I would like to have my own custom loop in order to be able to add things to it. So what I have now is:
import sys
from PyQt4 import QtCore, QtGui, uic
class MyWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.desktop = uic.loadUi('mytest.ui')
self.desktop.show()
if __name__ == '__main__':
app = QtGui.QApplication.instance()
window = MyWindow()
sys.exit(app.exec_())
I've played around a bit with PGU where I have been able to do this with what would be
while True:
window.loop()
in the main which allows me to put in my own extra code that is unrelated to the GUI without dealing with multiple threads. However I have been unable find some equivalent to "loop" in qt and searching for "qt custom loop/update/blit python" hasn't found anything relevant besides suggestions to add a 0 second timer to my app and place extra code there which seems... inelegant to me. I would like to import a GUI into my app rather then building my app around a GUI.
Edit: Here is my updated code taking Phyatt's answer into account for anyone else looking for the same answer I was.
import sys
from PyQt4 import QtGui, QtCore, uic
class TestApp(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = uic.loadUi('mytest.ui')
self.ui.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
win = TestApp()
app.processEvents()
while True:
app.processEvents()
Instead of using your own custom loop, the more common way to do that is to have a timer event scheduled on the Qt loop, or to launch another thread.
If you still really wanted to use your own loop, you need to manually call QApplication.processEvents() in your loop and it probably should work.
http://qt-project.org/doc/qt-4.8/qcoreapplication.html#processEvents
http://doc.qt.io/qt-5/qtimerevent.html#details
MyWindow.start(100) # start the built in timer event for that QObject 10 times a second
And then in MyWindow put def timerEvent and it should work.
Hope that helps.

Initialization completed event in QT4 GUI

I have a QT4 and python 2.4 based GUI. The user starts using it by opening a file. In addition to explicit browsing, I would like to allow the user to specify a file to open as a command line argument. I am looking for some event in the QMainWindow (or wherever) that would allow me to detect when the application completed its initialization and is ready for user interaction at which point I could automatically open the file and populate the widgets. So far I could not find anything better than overriding showEvent which is not exactly it because the main window is still not visible at this point. It might be okay but I am looking for a proper way to do this. In some other UI toolkits that I have used in the past that would be something like “main form layout completed” event that would signal that the UI is safe to deal with. Is there something similar in QT4? I am running this on Linux if that matters.
You insights are greatly appreciated.
You don't need an event here. It is guaranteed that everything is loaded after __init__() and show() have run, so you can just put your code for the file opening after that.
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setupUI()
self.show()
# normal __init__ done
if len(sys.argv) > 1:
with open(sys.argv[1]) as f:
# do stuff with file
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

Briefly flash a picture

I'm trying to modify a program written using pyQt (specifically, Anki). I want the program to briefly flash a picture (stored as a file on my hard drive) and then continue running normally.
This code will be inserted at some arbitrary point in the program. This is an ad-hoc single-user patch to an existing program - it does not need to be fast or elegant or easily-maintained.
My problem is that I know very little about pyQt. Do I need to define an entire new "window", or can I just run some sort of "notification" function with an image inside it?
QSplashScreen will be useful for this. It is mainly used for displaying certain image/text while a program loads, but your case also looks ideal for this. You can close it with clicking on it, or additionally you can set a timer to auto-close it after some time.
Here is a simple example with a dialog that has one button. When pressed it'll show the image and close after 2 seconds:
import sys
from PyQt4 import QtGui, QtCore
class Dialog(QtGui.QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
layout = QtGui.QVBoxLayout()
self.setLayout(layout)
self.b1 = QtGui.QPushButton('flash splash')
self.b1.clicked.connect(self.flashSplash)
layout.addWidget(self.b1)
def flashSplash(self):
# Be sure to keep a reference to the SplashScreen
# otherwise it'll be garbage collected
# That's why there is 'self.' in front of the name
self.splash = QtGui.QSplashScreen(QtGui.QPixmap('/path/to/image.jpg'))
# SplashScreen will be in the center of the screen by default.
# You can move it to a certain place if you want.
# self.splash.move(10,10)
self.splash.show()
# Close the SplashScreen after 2 secs (2000 ms)
QtCore.QTimer.singleShot(2000, self.splash.close)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = Dialog()
main.show()
sys.exit(app.exec_())

minimal example qtreeview for pyqt and the qt designer

I am trying to get a minimal example for an application designed by the qt designer with pyqt involving a QTreeView to work
1) i can start the app this way but if i push the butten, no entry in the TreeView widget is shown, i do not get any error message, and the layout looks fine, is there some kind of update method?
if you answer, please be specific, as i am still a beginner with qt and much of the documentation is written with c++ examples, and i only have some experience with basic c and python
from PyQt4 import uic, QtGui, QtCore
(Ui_MainWindow, QMainWindow) = uic.loadUiType('main_window.ui')
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.model = QtGui.QStandardItemModel()
self.connect(self.ui.pushButton_NeuesMoebel, QtCore.SIGNAL('clicked()'), self.add_item)
def add_item(self):
t = self.ui.lineEdit_Moebel.text()
if len(t) > 0:
item = QtGui.QStandardItem(t)
self.model.appendRow(item)
self.ui.lineEdit_Moebel.clear()
else:
self.ui.statusBar.showMessage('error: no text in Moebel')
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
2) additionally, is there a cleaner way to directly use the *.ui file than this, to sort of directly subclass the MainWindow of the that file? the ui stuff seems a bit messy
3) for example it would be nicer to have the add_item method in a subclass of the window created by the *.ui file, are we supposed to use the intermediate step of translating the *.ui file to a *.py file?
You just forgot to set the model on your QTreeView. Right now the tree view has no model so it never sees the data update:
def __init__(self, parent=None):
....
self.ui.treeView.setModel(self.model)
Also as a suggestion, save yourself some typing and use the new-style signal/slot connections that are more pythonic and don't make you type out signatures:
self.ui.pushButton_NeuesMoebel.clicked.connect(self.add_item)
I just came across this question and am really glad I did. It caused me to look into using the uic module, which I've been ignoring. In all the years that I've used pyqt I've always generated a .py file from the designer .ui file, and then importing the generated file as a module.
Using uic instead to directly load the .ui file saves a step and simplifies things quite a bit. It's easy to do.
So yes, in answer to question #2 there's a simpler way than calling the ui stuff:
from PyQt4 import uic, QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self,parent)
uic.loadUi('main_window.ui',self)
....

Categories

Resources