PyQt Confusion with Inheritance - python

I try to organize my code and therefore put some stuff into modules.
I would like several variables,, such as a statusBar(), in the main code section to be altered by imported modules.
I made a quick minimal working example to show what I mean:
Here is my main.py:
from PyQt4 import QtGui
import module
import sys
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.statusBar().showMessage("Main window initalized")
module.Test()
def main():
app = QtGui.QApplication(sys.argv)
form = ApplicationWindow()
form.show()
app.exec_()
if __name__ == "__main__":
main()
Here is module.py:
from PyQt4 import QtGui
class Test(QtGui.QMainWindow):
def __init__(self):
super(Test, self).__init__()
print 'hello'
self.statusBar().showMessage("Test module called", 6000)
The code prints "hello" and does not throw me any error, so I assume the module is successfully imported and Test is initialized, but it does not alter the statusBar() in my ApplicationWindow somehow. How can I achieve that? It's probably a silly mistake, so sorry in advance for bothering you!

the Test class have to reference to the ApplicationWindow class.
self.statusBar().showMessage("Test module called", 6000) will set a message on the status bar for the window of Test (A window that is lost to the void since it is never made visible or assigned to any variable)
Passing an instance of ApplicationWindow to Test would be one way to do what you want. Test also does not need to inherit from QtGui.QMainWindow for this.
from PyQt4 import QtGui
import module
import sys
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.statusBar().showMessage("Main window initalized", 6000)
module.Test(self)
def main():
app = QtGui.QApplication(sys.argv)
form = ApplicationWindow()
form.show()
app.exec_()
if __name__ == "__main__":
main()
# module.py
class Test(object):
def __init__(self, parent):
print 'hello'
parent.statusBar().showMessage("Test module called", 6000)

Related

How to catch a Signal from QMainWindow class by another thread on PySide?

I have a MainWindow class which have a Gui application running on it and i want that every time i click on a button from my application a signal is emitted and caught by another thread. There is my example code (sorry for not posting my real code but it is real big now):
from PySide.QtGui import *
from PySide.QtCore import *
import sys
import mainGui #Gui file
class MainWindow(QMainWindow, mainGui.Ui_MainWindow):
mySignal = Signal()
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.newThread = workThread()
self.newThread.start()
#myButton is part of Gui application
self.myButton.clicked.connect(self.myfunction)
def myfunction(self):
self.mySignal.emit()
(...) #Other functions and methods
class workThread(QThread):
def __init__(self, parent=None):
super(workThread, self).__init__(parent)
#The problem:
MainWindow.mySignal.connect(self.printMessage)
def run(self):
(...)
def printMessage(self):
print("Signal Recived")
(...)
def main():
app = QApplication(sys.argv)
form = MainWindow()
form.show()
app.exec_()
if __name__=="__main__":
main()
... and i get the following error:
MainWindow.mySignal.connect(self.printMessage)
AttributeError: 'PySide.QtCore.Signal' object has no attribute 'connect'
There is any ideia how can i solve this?
Thanks in advance!
Signals are just like methods - they must be bound to instances. They won't work correctly if you try to access them directly via the class.
One way to fix the example is to pass the instance of MainWindow in as the parent of the thread, like so:
self.newThread = workThread(self)
...
parent.mySignal.connect(self.printMessage)

Show dialog window

Can anyone tell me why this code is not working? The Test4 class is my converted simple UI:
import sys
import Test4
from PyQt4 import QtGui, QtCore
class UiViewer(QtGui.QApplication, Test4.Ui_Dialog):
def __init__(self, parent=None):
return super(UiViewer, self).__init__(parent)
self.setupUi(self)
def main(self):
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
uiViewer = UiViewer()
uiViewer.main()
app.exec_()
first of all
you need to use
if __name__ == '__main__'
not
if name == 'main':
and also adding the Error Message and describing the behavior of the application when you run it will help trace the problem.
from your question, it can be any number of problems.
Your UiViewer class needs to inherit from the same class as the top-level widget in Qt Designer (presumably QDialog, in your case, but it could also be a QMainWindow or a QWidget):
class UiViewer(QtGui.QDialog, Test4.Ui_Dialog):
def __init__(self, parent=None):
super(UiViewer, self).__init__(parent)
self.setupUi(self)
And note that you must not put return before the super call, otherwise the __init__ function will exit at that point, meaning the rest of its code won't be executed (in particular, setupUi would not be called).

slots in class where main window has not been declared

The main window is declared in Class1. I am trying to create an object of Class2, create a widget( a push button) and connect it to a slot.
import sys
from PyQt4 import QtGui,QtCore
class Class2(object):
def __init__(self,parent):
return
def button(self,parent):
self.print_button=QtGui.QPushButton("print hello",parent)
self.print_button.show()
self.print_button.clicked.connect(self.print_hello)
def print_hello(self,parent):
print 'hello'
class Class1(QtGui.QMainWindow):
def __init__(self):
super(Class1, self).__init__()
self.welcomeScreen()
def welcomeScreen(self):
obj=Class2(self)
obj.button(self)
def main():
app = QtGui.QApplication(sys.argv)
mw = Class1()
mw.show()
sys.exit(app.exec_())
if __name__=='__main__':
main()
Now, the button is getting created but the slot is not working. How to deal with this problem?
Your print_hello takes 2 arguments, and you pass it only a one.
Try this:
self.print_button.clicked.connect(lambda: self.print_hello(self))

confusion about creation of tabs in PyQt

import sys
from PyQt4 import QtCore, QtGui
class Class2(object):
def __init__(self,parent):
self.welcomeScreen(self)
def welcomeScreen(self,parent):
print 'hello'
self.centralwidget=QtGui.QWidget(parent)
self.tabWidget=QtGui.QTabWidget(self.centralwidget)
self.tabWidget.setGeometry(QtCore.QRect(0,0,661,511))
self.tab=QtGui.QWidget()
self.lineEdit=QtGui.QLineEdit(self.tab)
self.tabWidget.addTab(self.tab,"")
self.tabWidget.show()
class Class1(QtGui.QMainWindow):
def __init__(self):
super(Class1, self).__init__()
self.func()
def func(self):
ex=Class2(self)
def main():
app = QtGui.QApplication(sys.argv)
mw = Class1()
mw.show()
sys.exit(app.exec_())
if __name__=='__main__':
main()
Ok. So during the development of a small course management system, I came across a problem wherein I need to create tabs in class other than the one where the main window is defined. The following program scales down my problem.
The problem is in the welcomeScreen(self, parent) function wherein I need to add a tab widget.
The error is: TypeError: QWidget(QWidget parent=None, Qt.WindowFlags flags=0): argument 1 has unexpected type 'Class2'
this line:
self.welcomeScreen(self)
should be
self.welcomeScreen(parent)
You are effectively passing the Class2 object to welcomeScreen twice.
self.welcomeScreen(b) is equivalent to Class2.welcomeScreen(self, b)

PyQt4 multithreading using QThread

There is an endless block when xml.etree.ElementTree.fromstring() function is called in the QThread. Also lots of other calls makes the QThread blocked like multiprocessing.Process().
Important to say that it is a pure block, no exception or break.
Here is the code (a little edited but same principle as the source):
from PyQt4.QtGui import *
from Ui_mainwindow import Ui_MainWindow
import sys
import xml.etree
class Bruton(QThread):
def __init__(self, mw):
super(Bruton, self).__init__(mw)
self.mw = mw
def run(self):
print("This message I see.")
tree = xml.etree.ElementTree.fromstring("<element>text</element>")
print("But this one never.")
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.init_bruton()
# When the form is shown...
def showEvent(self, arg1):
self.bruton.start()
def init_bruton(self):
self.bruton = Bruton(self)
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
The code as posted doesn't actually run, but with a couple minor changes it runs and works fine. Here is the code with modifications:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
import xml.etree.ElementTree
class Bruton(QThread):
def __init__(self, mw):
super(Bruton, self).__init__(mw)
self.mw = mw
def run(self):
print("This message I see.")
tree = xml.etree.ElementTree.fromstring("<element>text</element>")
print("But this one never.")
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.init_bruton()
# When the form is shown...
def showEvent(self, arg1):
self.bruton.start()
def init_bruton(self):
self.bruton = Bruton(self)
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
And here is the output:
$ python test.py
This message I see.
But this one never.
This is with Python 2.6.6, PyQt4 4.8.3, on Debian Unstable.
Can you try it in your environment and see if my modified example works for you? If so, you are on the road to a solution for your real code. =)
The code I've shown here is shortened (the source is divided to two files and __ini__.py). I noticed that the main module must be the module that starts the QApplication. So I added app.exec_() to the __init__.py which is the main module of my program.

Categories

Resources