I am quite new in Python and TRYING to make a PyQt4 app, where I am embedding PyQtGraph in it. I've got this PyQtGraph live plotter that works fantastically:
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import random
app = QtGui.QApplication([])
p = pg.plot()
curve = p.plot()
data = [0]
def updater():
data.append(random.random())
curve.setData(data) #xdata is not necessary
timer = QtCore.QTimer()
timer.timeout.connect(updater)
timer.start(0)
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
For embedding in a bigger PyQt4 app, I need a layout for including a pyqtgraph.PlotWidget(). For that matter I set a centralWidget in my MainWindow. I create a button, that should start plotting just as the previous code does, but just nothing happens when I call the updater function through the plotter function:
import sys
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
login_widget = LoginWidget(self)#to say where the button is
login_widget.button.clicked.connect(self.plotter)
self.central_widget.addWidget(login_widget)
def plotter(self):
self.data =[0]
timer = QtCore.QTimer()
timer.timeout.connect(self.updater)
timer.start(0)
def updater(self):
self.data.append(random.random())
plot.setData(self.data)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
global plot
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
plot = pg.PlotWidget()
layout.addWidget(plot)
self.setLayout(layout)
if __name__ == '__main__':
app = QtGui.QApplication([])
window = MainWindow()
window.show()
app.exec_()
Is nothing happening because I have to thread?
There are several things to consider in the code.
First, going in the same direction as #luddek's answer, you need to keep track of your variables. If you define a variable inside a class method and this class method finished executing, the variable is lost. Also it is not visible from the outside.
It is therefore a good idea to use instance variables,
self.plot instead of plot
self.timer instead of timer
self.login_widget instead of login_widget
(also, I would not recomment using global in a PyQt programm, although it is valid code)
Next, PlotWidget does not have a setData method. Plotting the data to the PlotItem's plot is a little more involved:
pg.PlotWidget() has a PlotItem which you can get via .getPlotItem(). Then you need to invoke plot() on it, which returns the actual curve you want to add data to. In the example below I introduced the new variable self.curve to which you can add the data via self.curve.setData(self.data)
Here is the complete working code.
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
self.login_widget = LoginWidget(self)
self.login_widget.button.clicked.connect(self.plotter)
self.central_widget.addWidget(self.login_widget)
def plotter(self):
self.data =[0]
self.curve = self.login_widget.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1]+0.2*(0.5-random.random()) )
self.curve.setData(self.data)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
if __name__ == '__main__':
app = QtGui.QApplication([])
window = MainWindow()
window.show()
app.exec_()
updater() is not called because the timer is removed by the garbage collector.
You need to keep a reference somewhere to the timer. You could for example create the reference in __init__
def __init__(self, parent=None):
...
self.timer = QtCore.QTimer()
Related
I found some code on here that shows an example of how you can get the window to resize when the widget is hidden, and it works for me. Here is the code:
from PyQt4 import QtCore, QtGui
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
super(MainWindow, self).__init__()
self.button = QtGui.QPushButton('Show/Hide')
self.button.setCheckable(True)
self.frame = QtGui.QFrame()
self.frame.setFixedHeight(100)
self.layout = layout = QtGui.QVBoxLayout()
layout2 = QtGui.QVBoxLayout()
self.setLayout(layout)
self.frame.setLayout(layout2)
layout.addWidget(self.button)
layout.addWidget(self.frame)
layout.addStretch(1)
layout2.addWidget(QtGui.QLabel('Yoyoyo'))
self.button.toggled.connect(self.clickAction)
def startup(self):
self.show()
sys.exit(self.app.exec_())
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.resizeMe)
def resizeMe(self):
self.resize(self.minimumSizeHint())
if __name__ == "__main__":
myApp = MainWindow()
myApp.startup()
I then tried to modify this to match my existing code by separating the mainWindow class and the widget class. Here is the code that does that.
from PySide import QtGui,QtCore
import sys
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.w = testW(self)
self.setCentralWidget(self.w)
self.show()
class testW(QtGui.QWidget):
def __init__(self,parent):
super(testW,self).__init__()
self.parent = parent
self.button = QtGui.QPushButton('Show/Hide')
self.button.setCheckable(True)
self.button.setChecked(True);
self.frame = QtGui.QFrame()
self.frame.setFixedHeight(100)
self.layout = layout = QtGui.QVBoxLayout()
layout2 = QtGui.QVBoxLayout()
self.setLayout(layout)
self.frame.setLayout(layout2)
layout.addWidget(self.button)
layout.addWidget(self.frame)
layout.addStretch(1)
layout2.addWidget(QtGui.QLabel('Yoyoyo'))
self.button.toggled.connect(self.clickAction)
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.resizeMe)
def resizeMe(self):
self.resize(self.minimumSizeHint())
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myApp = MainWindow()
sys.exit(app.exec_())
#time.sleep(1)
Running the first code does what I want it to. After I hide the widget, the window resizes to the correct size. The second implementation of the code does not shrink and expand the window when I hide and show the widget. Is this because the MainWindow is in a separate class?
Use size policies for your widgets. For your example you can change UI creation code as follows:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.w = testW(self)
self.w.setSizePolicy(
QtWidgets.QSizePolicy.MinimumExpanding,
QtWidgets.QSizePolicy.MinimumExpanding
)
self.setCentralWidget(self.w)
self.show()
Please note new setSizePolicy call which say Qt layout engine how to change the size of your widget according to its content.
Unfortunately QMainWindow does not respect sizeHint automatically, but it is calculated properly, so you can adjustSize manually:
def clickAction(self):
checked = self.button.isChecked()
if checked:
self.frame.show()
else:
self.frame.hide()
QtCore.QTimer.singleShot(0, self.parent.adjustSize)
You do not need to resize your widget itself, because it will be resized according to the policy. Even sizeHint will be calculated automatically so you need only to call adjustSize of QMainWindow.
PS: I used PySide2 instead of PySide so the imports are different a little bit:
from PySide2 import QtWidgets, QtCore
As a continuation of the question I got solved here some days ago, I've got a PyQt4 GUI which embeds two PyQtGraph's PlotWidgets, which each set/update data from an threaded randomly-appending array triggered by a button. It works beautifully, and the GUI is responsive. But there comes a point, where the graphs stop showing the updates inside their respective PlotWidgets, and I have to minimize/maximize to see the updates drawn inside the PlotWidgets. The code looks like:
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
def __init__(self, curve, parent=None):
super(MyThread, self).__init__(parent=parent)
self.curve = curve
self.data = [0]
app.processEvents()#increases the time the drawings are shown
def run(self):
app.processEvents() #increases the time the drawings are shown
while True:
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.curve.setData(self.data, downsample=10) #crashes without
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
app.processEvents()
def plotter(self):
self.curve = self.plot.getPlotItem().plot()
myThread = MyThread(self.curve, self)
myThread.start()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
global app
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Any clue or workaround for what I can do for not having to maximize/minimize in order to get the updates in the GUI will make me incredibly glad.
Following the advice from #ImportanceOfBeingErnest in the answer below, I attempted following the Python Wiki to connect the GUI and the thread with signals and slots as:
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.data = [0]
def run(self):
while True:
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.emit(SIGNAL("output(data)"), self.data)
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
self.myThread = MyThread()
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
self.connect(self.myThread, SIGNAL("output(data)"), self.plotter)
def plotter(self, data):
self.curve = self.plot.getPlotItem().plot()
self.curve.setData(data, downsample=10)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
But that gives me the error:
"in self.connect(self.myThread, SIGNAL("output(data)"), self.plotter)
NameError: name 'SIGNAL' is not defined"
By reading a question from 4 years ago, I substitute SIGNAL by QtCore.SIGNAL to get the following error:
"in self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter)
TypeError: C++ type 'data' is not supported as a slot argument type"
Then by ingnoring the TypeError as:
try:
self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter)
except TypeError:
pass
The GUI starts, but when I finally click the button and connect to the self.plotter function I get the following error:
"in plotter
self.curve.setData(data, downsample=10)
File "C:\Users\iyv\AppData\Local\Programs\Python\Python34_64\lib\site-
packages\pyqtgraph\graphicsItems\PlotDataItem.py", line 381, in setData
raise Exception('Invalid data type %s' % type(data))
Exception: Invalid data type <class 'bool'>"
I am pretty confused. Should I contact PyQtGraph? Any help gratefully welcomed.
You need to keep the GUI and the thread separate. They must not share any GUI object like the plot widget in this case!
I'm not sure if you need threading since your data is not very big and is only updated 10 times a second. But if you decide to use it, only use signals and slots to communicate between thread and GUI.
Below is a modified version of your program which uses threading and works fine. It uses the new style signals and slots. This is hopefully easier to understand, because you can just use object as datatype.
Two things hat make no sense in your program are:
you redefine self.curve in the plotting slot.
you call the plotting slot when pressing the button. Instead a button press should start the thread.
I have corrected them.
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
signal = QtCore.pyqtSignal(object)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.data = [0]
def __del__(self):
self.exiting = True
self.wait()
def run(self):
while True:
self.data.append(random.random())
self.signal.emit(self.data)
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
self.myThread = MyThread()
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.curve = self.plot.getPlotItem().plot()
self.button.clicked.connect(self.start)
def plotter(self, data):
self.curve.setData(data)
def start(self):
self.myThread.start()
self.myThread.signal.connect(self.plotter)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
First of all sorry for the lenght. I want to explain my problem as good as possible. I am quite new to Python and trying to make a plotting app using PyQtGraph embedded in PyQt4. Some days ago I got a really nice answer to my plotting problem, and my next step is to have two PyQtGraphs plot Widgets simoultaneously plotting in the same PyQt4's CentralWidget. By the same approach as in the link described, both plots work fine, but the GUI gets unresponsive. For overcoming this, I am aiming to use QThread, and for that, I need to have my plotting functions in different classes. But I am messing with my variables, and can't see how:
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
self.login_widget = LoginWidget(self)
self.login_widget.button.clicked.connect(Plots.plotter)
self.central_widget.addWidget(self.login_widget)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
class Plots(MainWindow):
def print(self):
print('hello World')
def plotter(self):
self.data = [0]
self.curve = self.login_widget.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1]+0.2*(0.5-random.random()))
self.curve.setData(self.data)
if __name__ == '__main__':
app = QtGui.QApplication([])
window = MainWindow()
window.show()
app.exec_()
That gives me an error at Plots.plotter:
self.data = [0]
AttributeError: 'bool' object has no attribute 'data'
If in the MainWindow class I substitute the 'button.connect' argument with Plots.print, it works fine. So I can see there is something wrong with the fact that I make an LoginWidget object in MainWindow, and then Plots inherits from MainWindow, calling that same LoginWidget object again.
I have tried a proposed solution where the father (MainWindow) does not access the methods of the children (Plots). But if, from Plots, I want to call the class where I aim placing my thread in, I get the same error again....
import sys
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
self.login_widget = LoginWidget(self)
self.central_widget.addWidget(self.login_widget)
class Plots(MainWindow):
def __init__(self, parent=None):
super(Plots, self).__init__(parent=parent)
self.login_widget.button.clicked.connect(MyThread.plotter)
class MyThread(MainWindow):
def __init__(self, parent=None):
super(Aname, self).__init__(parent=parent)
def print(self):
print('hello World')
def plotter(self):
self.data = [0]
self.curve = self.login_widget.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1]+0.2*(0.5-random.random()))
self.curve.setData(self.data)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = Plots()
w.show()
sys.exit(app.exec_())
In inheritance the father should not access the methods of the children, It is better to inherit and implement new methods that have nothing to do with the parent in the child class.
Timer Version
import random
import sys
import pyqtgraph as pg
from PyQt4 import QtGui, QtCore
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
def plotter(self):
self.data = [0]
self.curve = self.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.curve.setData(self.data)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I am trying to create a toolbar that can be modified to change actions on the fly.
However signals are not being sent when I add actions from outside the class that creates the toolbar.
In the example below the new action is never triggered. Any idea on how this can be done?
import sys
from PyQt4 import QtGui
from toolbarmodifier import ToolbarModifier
class FluidToolbar(QtGui.QMainWindow):
def __init__(self):
super(FluidToolbar, self).__init__()
self.initUI()
def initUI(self):
createAction = QtGui.QAction( 'create Action', self)
createAction.triggered.connect(self.createActions)
self.toolbar = self.addToolBar('create Action')
self.toolbar.addAction(createAction)
self.setGeometry(300, 300, 300, 200)
self.show()
def createActions(self):
print(">>createActions()")
toolbarModifier = ToolbarModifier()
toolbarModifier.addAction(self)
def main():
app = QtGui.QApplication(sys.argv)
ex = FluidToolbar()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
toolbarmodifier.py
from PyQt4 import QtGui
from PyQt4.QtGui import QWidget
class ToolbarModifier(QWidget):
def __init__(self):
super(ToolbarModifier, self).__init__()
def newActionTriggered(self):
print(">>newActionTriggered()")
def addAction(self, gui):
triggerAction = QtGui.QAction( 'New action', gui)
triggerAction.triggered.connect(self.newActionTriggered)
gui.toolbar.addAction(triggerAction)
print("<<addAction()")
Not having a link back to parent was the issue. In FluidToobar modify code in createActions method to include self in call:
toolbarModifier = ToolbarModifier(self)
In ToolbarModifier change first few lines to:
class ToolbarModifier(QtCore.QObject):
def __init__(self, parent=None):
super(ToolbarModifier, self).__init__(parent)
Look at the code
import sys
from PySide import QtCore, QtGui
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.quit = QtGui.QPushButton("Quit", self)
self.setGeometry(300, 300, 250, 150)
self.statusBar().showMessage('Ready')
app = QtGui.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
Now all I want to do , is add a Status. Now status is available in QtGui.QMainWindow
How can i use this fact to add it in the above program? In pyside coding , seems like for every component , we need to make a class and some connect to the main class..whata s the theory here?
I tried myself like this , but it did not work.
import sys
from PySide import QtCore, QtGui
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.quit = QtGui.QPushButton("Quit", self)
self.setGeometry(300, 300, 250, 150)
self.statusBar().showMessage('Ready')
self.s = MyStatus()
class MyStatus(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.statusBar().showMessage('Ready')
app = QtGui.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
You do not need to make a class for every component, but if you want to modify/override each component's built-in function you need to make a class for it.
To add something to your main window, you simply have to create an object and add it to the layout. As follow:
import sys
from PySide import QtGui , QtCore
class MyStatusBar(QtGui.QStatusBar):
def __init__(self, parent=None):
super(MyStatusBar, self).__init__(parent)
#Override any functions, or define new function for our status bar here
class MyMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
#Set the size of the window
self.setMinimumSize(300,300)
#Create a status bar, from our OWN class
self.status_bar = MyStatusBar(self)
self.status_bar.setGeometry(QtCore.QRect(0, 0, 50, 50))
self.status_bar.showMessage('Ready')
#Add a simple quit button, from the DEFAULT class
self.quit_button = QtGui.QPushButton(self)
self.quit_button.clicked.connect(self.close)
self.quit_button.setGeometry(QtCore.QRect(100, 100, 100, 35))
self.quit_button.setText("Close")
#Start the application
app = QtGui.QApplication(sys.argv)
top = MyMainWindow()
top.show()
app.exec_()
If you want a window with a status-bar, use QMainWindow: it has one built-in (and also a menu-bar, tool-bars, dock-widgets, etc). Other widgets don't have these built-in features, and so, quite naturally, they don't have things like a statusBar method. If you insist on doing things the hard way by not using QMainWindow, you will have to add all these features yourself.
Although I wouldn't recommend doing things this way, here is a simple demo that adds a status-bar to a QWidget:
import sys
from PySide import QtCore, QtGui
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.central_widget = QtGui.QWidget(self)
self.quit = QtGui.QPushButton("Quit", self)
self.setGeometry(300, 300, 250, 150)
layout = QtGui.QVBoxLayout(self.central_widget)
layout.addWidget(self.quit)
self.status = QtGui.QStatusBar(self)
layout = QtGui.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.widget)
layout.addStretch()
layout.addWidget(self.status)
self.status.showMessage('Ready')
app = QtGui.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())