PyQt FAQ Widgets
Материал из Wiki.crossplatform.ru
(Новая: Widgets are basic building blocks of an application. The PyQt4 programming toolkit has a wide range of various widgets. Buttons, check boxes, sliders, list boxes etc. Everything a progra...)
Следующая правка →
Версия 11:16, 18 февраля 2009
Widgets are basic building blocks of an application. The PyQt4 programming toolkit has a wide range of various widgets. Buttons, check boxes, sliders, list boxes etc. Everything a programmer needs for his job. In this section of the tutorial, we will describe several useful widgets.
Содержание |
QCheckBox
QCheckBox is a widget that has two states. On and Off. It is a box with a label. Whenever a checkbox is checked or cleared it emits the signal stateChanged().
#!/usr/bin/python # checkbox.py import sys from PyQt4 import QtGui from PyQt4 import QtCore class CheckBox(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Checkbox') self.cb = QtGui.QCheckBox('Show title', self) self.cb.setFocusPolicy(QtCore.Qt.NoFocus) self.cb.move(10, 10) self.cb.toggle(); self.connect(self.cb, QtCore.SIGNAL('stateChanged(int)'), self.changeTitle) def changeTitle(self, value): if self.cb.isChecked(): self.setWindowTitle('Checkbox') else: self.setWindowTitle('') app = QtGui.QApplication(sys.argv) icon = CheckBox() icon.show() app.exec_()
In our example, we will create a checkbox that will toggle the window title.
self.cb = QtGui.QCheckBox('Show title', self)
This is the QCheckBox constructor.
self.cb.setFocusPolicy(QtCore.Qt.NoFocus)
We connect the user defined changeTitle() method to the stateChanged() signal. The changeTitle() method will toggle the window title.
self.connect(self.cb, QtCore.SIGNAL('stateChanged(int)'), self.changeTitle)
By default, the QCheckBox accepts focus. It is represented by a thin rectangle over the checkbox label. The rectangle looks awful, so I disable it by setting the widget focus policy to Qt.NoFocus.
self.cb.toggle();
We set the window title, so we must also check the checkbox. By default, the window title is not set and the check box is unchecked.
ToggleButton
PyQt4 has no widget for a ToggleButton. To create a ToggleButton, we use a QPushButton in a special mode. ToggleButton is a button that has two states. Pressed and not pressed. You toggle between these two states by clicking on it. There are situations where this functionality fits well.
#!/usr/bin/python # togglebutton.py import sys from PyQt4 import QtGui from PyQt4 import QtCore class ToggleButton(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.color = QtGui.QColor(0, 0, 0) self.setGeometry(300, 300, 280, 170) self.setWindowTitle('ToggleButton') self.red = QtGui.QPushButton('Red', self) self.red.setCheckable(True) self.red.move(10, 10) self.connect(self.red, QtCore.SIGNAL('clicked()'), self.setRed) self.green = QtGui.QPushButton('Green', self) self.green.setCheckable(True) self.green.move(10, 60) self.connect(self.green, QtCore.SIGNAL('clicked()'), self.setGreen) self.blue = QtGui.QPushButton('Blue', self) self.blue.setCheckable(True) self.blue.move(10, 110) self.connect(self.blue, QtCore.SIGNAL('clicked()'), self.setBlue) self.square = QtGui.QWidget(self) self.square.setGeometry(150, 20, 100, 100) self.square.setStyleSheet("QWidget { background-color: %s }" % self.color.name()) QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('cleanlooks')) def setRed(self): if self.red.isChecked(): self.color.setRed(255) else: self.color.setRed(0) self.square.setStyleSheet("QWidget { background-color: %s }" % self.color.name()) def setGreen(self): if self.green.isChecked(): self.color.setGreen(255) else: self.color.setGreen(0) self.square.setStyleSheet("QWidget { background-color: %s }" % self.color.name()) def setBlue(self): if self.blue.isChecked(): self.color.setBlue(255) else: self.color.setBlue(0) self.square.setStyleSheet("QWidget { background-color: %s }" % self.color.name()) app = QtGui.QApplication(sys.argv) tb = ToggleButton() tb.show() app.exec_()
In our example, we create three ToggleButtons. We also create a QWidget. We set the background color of the QWidget to black. The togglebuttons will toggle the red, green and blue parts of the color value. The background color will depend on which togglebuttons we have pressed.
self.color = QtGui.QColor(0, 0, 0)
This is the initial color value. No red, green and blue equals to black. Theoretically speaking, black is not a color after all.
self.red = QtGui.QPushButton('Red', self) self.red.setCheckable(True)
To create a ToggleButton, we create a QPushButton and make it checkable by calling setCheckable() method.
self.connect(self.red, QtCore.SIGNAL('clicked()'), self.setRed)
We connect a clicked() signal to our user defined method.
QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('cleanlooks'))
I have set the style of the application to cleanlooks. I did it, because the default style for linux, plastique has a design bug. You cannot easily tell whether the ToggleButton is pressed or not. CleanLooks style is better.
if self.red.isChecked(): self.color.setRed(255) else: self.color.setRed(0)
We check, whether the button is pressed and change the color value accordingly.
self.square.setStyleSheet("QWidget { background-color: %s }" % self.color.name())
To change the background color, we use stylesheets.
QSlider, QLabel
QSlider is a widget that has a simple handle. This handle can be pulled back and forth. This way we are choosing a value for a specific task. Sometimes using a slider is more natural, than simply providing a number or using a spin box. QLabel displays text or image.
In our example we will show one slider and one label. This time, the label will display an image. The slider will control the label.
#!/usr/bin/python # slider-label.py import sys from PyQt4 import QtGui from PyQt4 import QtCore class SliderLabel(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.setGeometry(300, 300, 250, 150) self.setWindowTitle('SliderLabel') self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.slider.setFocusPolicy(QtCore.Qt.NoFocus) self.slider.setGeometry(30, 40, 100, 30) self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue) self.label = QtGui.QLabel(self) self.label.setPixmap(QtGui.QPixmap('mute.png')) self.label.setGeometry(160, 40, 80, 30) def changeValue(self, value): pos = self.slider.value() if pos == 0: self.label.setPixmap(QtGui.QPixmap('mute.png')) elif pos > 0 and pos <= 30: self.label.setPixmap(QtGui.QPixmap('min.png')) elif pos > 30 and pos < 80: self.label.setPixmap(QtGui.QPixmap('med.png')) else: self.label.setPixmap(QtGui.QPixmap('max.png')) app = QtGui.QApplication(sys.argv) icon = SliderLabel() icon.show() app.exec_()
In our example we simulate a volume control. By dragging the handle of a slider, we change a image on the label.
self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
Here we create a horizontal QSlider.
self.label = QtGui.QLabel(self) self.label.setPixmap(QtGui.QPixmap('mute.png'))
We create a Qlabel. And set an initial mute image to it.
self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue)
We connect the valueChanged signal to the user defined changeValue() method.
pos = self.slider.value()
We get the position of the slider by calling the value() method. We change the image on the label accordingly.
QProgressBar
A progress bar is a widget that is used, when we process lengthy tasks. It is animated so that the user knows, that our task is progressing. The QProgressBar widget provides a horizontal or vertical progress bar in PyQt4 toolkit. The task is divided into steps. The programmer can set the minimum and maximum values for the progress bar. The default values are 0, 99.
#!/usr/bin/python # progressbar.py import sys from PyQt4 import QtGui from PyQt4 import QtCore class ProgressBar(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.setGeometry(300, 300, 250, 150) self.setWindowTitle('ProgressBar') self.pbar = QtGui.QProgressBar(self) self.pbar.setGeometry(30, 40, 200, 25) self.button = QtGui.QPushButton('Start', self) self.button.setFocusPolicy(QtCore.Qt.NoFocus) self.button.move(40, 80) self.connect(self.button, QtCore.SIGNAL('clicked()'), self.onStart) self.timer = QtCore.QBasicTimer() self.step = 0; def timerEvent(self, event): if self.step >= 100: self.timer.stop() return self.step = self.step + 1 self.pbar.setValue(self.step) def onStart(self): if self.timer.isActive(): self.timer.stop() self.button.setText('Start') else: self.timer.start(100, self) self.button.setText('Stop') app = QtGui.QApplication(sys.argv) icon = ProgressBar() icon.show() app.exec_()
In our example we have a horizontal progress bar and a push button. The push button starts and stops the progress bar.
self.pbar = QtGui.QProgressBar(self)
QProgressBar constructor.
self.timer = QtCore.QBasicTimer()
To activate the progress bar, we use the timer object.
self.timer.start(100, self)
To launch the timer events, we call the start() method. This method has two parameters. The timeout and the object, which will receive the events.
def timerEvent(self, event): if self.step >= 100: self.timer.stop() return self.step = self.step + 1 self.pbar.setValue(self.step)
Each QObject and its descendants has a QObject.timerEvent event handler. In order to react to timer events, we reimplement the event handler.
QCalendarWidget
The QCalendarWidget provides a monthly based calendar widget. It allows a user to select a date in a simple and intuitive way.
#!/usr/bin/python # calendar.py import sys from PyQt4 import QtGui from PyQt4 import QtCore class Calendar(QtGui.QWidget): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.setGeometry(300, 300, 350, 300) self.setWindowTitle('Calendar') self.cal = QtGui.QCalendarWidget(self) self.cal.setGridVisible(True) self.cal.move(20, 20) self.connect(self.cal, QtCore.SIGNAL('selectionChanged()'), self.showDate) self.label = QtGui.QLabel(self) date = self.cal.selectedDate() self.label.setText(str(date.toPyDate())) self.label.move(130, 260) def showDate(self): date = self.cal.selectedDate() self.label.setText(str(date.toPyDate())) app = QtGui.QApplication(sys.argv) icon = Calendar() icon.show() app.exec_()
The example has a calendar widget and a label widget. The currently selected date is displayed in the label widget.
self.cal = QtGui.QCalendarWidget(self)
We construct a calendar widget.
self.connect(self.cal, QtCore.SIGNAL('selectionChanged()'), self.showDate)
If we select a date from the widget, a selectionChanged() signal is emitted. We connect this method to the user defined showDate() method.
def showDate(self): date = self.cal.selectedDate() self.label.setText(str(date.toPyDate()))
We retrieve the selected date calling the selectedDate() method. Then we transform the date object into string and set it to the label widget.