Виджеты в PyQt5

Виджеты – это основные строительные кирпичики приложения. PyQt5 имеет множество разнообразных виджетов, включая кнопки, чекбоксы, ползунки и списки. В этой части руководства, мы опишем несколько полезных виджетов: QCheckBox, ToggleButton, QSlider, QProgressBar и QCalendarWidget.

QCheckBox (чекбокс)

QCheckBox – чекбокс (виджет, который имеет два состояния: включен и выключен). Как правило, чекбоксы используют для функций приложения, которые могут быть включены или выключены.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication
from PyQt5.QtCore import Qt


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        cb = QCheckBox('Show title', self)
        cb.move(20, 20)
        cb.toggle()
        cb.stateChanged.connect(self.changeTitle)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('QCheckBox')
        self.show()


    def changeTitle(self, state):

        if state == Qt.Checked:
            self.setWindowTitle('QCheckBox')
        else:
            self.setWindowTitle('')


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы создаём чекбокс, который переключает заголовок окна.

cb = QCheckBox('Show title', self)

Это конструктор QCheckBox.

cb.toggle()

Мы установили заголовок окна так, что мы должны к тому же проверять чекбокс. По умолчанию, заголовок окна не установлен и чекбокс выключен.

cb.stateChanged.connect(self.changeTitle)

Мы связываем наш метод changeTitle(), с сигналом stateChanged. Метод changeTitle() будет переключать заголовок окна.

def changeTitle(self, state):

    if state == Qt.Checked:
        self.setWindowTitle('QCheckBox')
    else:
        self.setWindowTitle('')

Если виджет помечен галочкой, мы устанавливаем заголовок окна. В противном случае, мы устанавливаем пустую строку в заголовке.

Чекбокс

Кнопка переключателя (toogle button)

Кнопка переключателя – это QPushButton в особом режиме. Это кнопка, которая имеет два состояния: нажатое и не нажатое. Мы переключаемся между этими двумя состояниями, кликая по ней. Существуют ситуации, где эта функциональность отлично подходит.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
    QFrame, QApplication)
from PyQt5.QtGui import QColor


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.col = QColor(0, 0, 0)

        redb = QPushButton('Red', self)
        redb.setCheckable(True)
        redb.move(10, 10)

        redb.clicked[bool].connect(self.setColor)

        greenb = QPushButton('Green', self)
        greenb.setCheckable(True)
        greenb.move(10, 60)

        greenb.clicked[bool].connect(self.setColor)

        blueb = QPushButton('Blue', self)
        blueb.setCheckable(True)
        blueb.move(10, 110)

        blueb.clicked[bool].connect(self.setColor)

        self.square = QFrame(self)
        self.square.setGeometry(150, 20, 100, 100)
        self.square.setStyleSheet("QWidget { background-color: %s }" %
            self.col.name())

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('Toggle button')
        self.show()


    def setColor(self, pressed):

        source = self.sender()

        if pressed:
            val = 255
        else: val = 0

        if source.text() == "Red":
            self.col.setRed(val)
        elif source.text() == "Green":
            self.col.setGreen(val)
        else:
            self.col.setBlue(val)

        self.square.setStyleSheet("QFrame { background-color: %s }" %
            self.col.name())


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы создаём три кнопки переключателя и QWidget. Мы устанавливаем чёрный цвет фона. Кнопки переключателей будут переключать красные, зелёные и синие части значений цвета. Цвет фона будет зависеть от того, на какие кнопки переключателей мы нажали.

self.col = QColor(0, 0, 0)

Это начальное значение цвета (чёрный).

redb = QPushButton('Red', self)
redb.setCheckable(True)
redb.move(10, 10)

Чтобы создать кнопку переключателя, мы создаём QPushButton и делаем её проверяемой, путём вызова метода setCheckable().

redb.clicked[bool].connect(self.setColor)

Мы привязываем сигнал к нашему пользовательскому методу. Мы используем сигнал clicked, который работает с логическим значением.

source = self.sender()

Мы получаем кнопку, которая была переключена.

if source.text() == "Red":
    self.col.setRed(val)

В случае кнопки red, мы обновляем красную часть цвета соответственно.

self.square.setStyleSheet("QFrame { background-color: %s }" % self.col.name())

Мы используем таблицы стилей, чтобы менять цвет фона.

Кнопка переключателя

QSlider (ползунок)

Qslider – ползунок (виджет, который имеет простой регулятор). Этот регулятор может быть утянут назад и вперёд. Таким способом, мы выбираем значение для конкретной задачи. Иногда, использование ползунка более естественно, чем ввод числа или использование переключателя-счётчика. В нашем примере, мы покажем один ползунок и одну метку. Метка будет показывать изображение. Ползунок будет контролировать метку.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QSlider,
    QLabel, QApplication)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setGeometry(30, 40, 100, 30)
        sld.valueChanged[int].connect(self.changeValue)

        self.label = QLabel(self)
        self.label.setPixmap(QPixmap('mute.png'))
        self.label.setGeometry(160, 40, 80, 30)

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('QSlider')
        self.show()


    def changeValue(self, value):

        if value == 0:
            self.label.setPixmap(QPixmap('mute.png'))
        elif value > 0 and value <= 30:
            self.label.setPixmap(QPixmap('min.png'))
        elif value > 30 and value < 80:
            self.label.setPixmap(QPixmap('med.png'))
        else:
            self.label.setPixmap(QPixmap('max.png'))


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы симулируем контроль громкости. Путём перетаскивания регулятора ползунка, мы меняем изображение на метке.

sld = QSlider(Qt.Horizontal, self)

Здесь мы создаём горизонтальный ползунок.

self.label = QLabel(self)
self.label.setPixmap(QPixmap('mute.png'))

Мы создаём виджет QLabel и устанавливаем начальное изображение "Mute" на него.

sld.valueChanged[int].connect(self.changeValue)

Мы привязываем сигнал valueChanged к определенному нами методу changeValue().

if value == 0:
    self.label.setPixmap(QPixmap('mute.png'))
...

Основываясь на значении ползунка, мы устанавливаем изображение на метку. В коде выше, мы устанавливаем изображение mute.png на метку, если ползунок приравнен к нулю.

Ползунок

QProgressBar (прогресс бар)

QProgressBar – прогресс бар (виджет, который используется, когда мы обрабатываем продолжительные задачи). Он анимирует процесс, чтобы пользователи знали, что задача продвигается. Мы можем установить минимальное и максимальное значение для прогресс бара. Значения по умолчанию – 0 и 99.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QProgressBar,
    QPushButton, QApplication)
from PyQt5.QtCore import QBasicTimer


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.pbar = QProgressBar(self)
        self.pbar.setGeometry(30, 40, 200, 25)

        self.btn = QPushButton('Start', self)
        self.btn.move(40, 80)
        self.btn.clicked.connect(self.doAction)

        self.timer = QBasicTimer()
        self.step = 0

        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('QProgressBar')
        self.show()


    def timerEvent(self, e):

        if self.step >= 100:
            self.timer.stop()
            self.btn.setText('Finished')
            return

        self.step = self.step + 1
        self.pbar.setValue(self.step)


    def doAction(self):

        if self.timer.isActive():
            self.timer.stop()
            self.btn.setText('Start')
        else:
            self.timer.start(100, self)
            self.btn.setText('Stop')


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В нашем примере, мы имеем горизонтальный индикатор прогресса и кнопку. Кнопка запускает и останавливает индикатор прогресса.

self.pbar = QProgressBar(self)

Это конструктор QProgressBar.

self.timer = QtCore.QBasicTimer()

Чтобы активировать индикатор прогресса, мы используем объект таймера.

self.timer.start(100, self)

Чтобы запустить событие таймера, мы вызываем его методом start(). Этот метод имеет два параметра: таймаут, и объект, который будет принимать события.

def timerEvent(self, e):

    if self.step >= 100:

        self.timer.stop()
        self.btn.setText('Finished')
        return

    self.step = self.step + 1
    self.pbar.setValue(self.step)

Каждый QObject и его наследники имеют обработчик событий timerEvent(). Для того, чтобы реагировать на события таймера, мы переопределяем обработчик событий.

def doAction(self):

    if self.timer.isActive():
        self.timer.stop()
        self.btn.setText('Start')

    else:
        self.timer.start(100, self)
        self.btn.setText('Stop')

Внутри метода doAction(), мы запускаем и останавливаем таймер.

Прогресс бар

QCalendarWidget (виджет календаря)

QCalendarWidget предоставляет виджет помесячного календаря. Он позволяет пользователю выбирать дату простым и интуитивно-понятным способом.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QCalendarWidget,
    QLabel, QApplication)
from PyQt5.QtCore import QDate


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        cal = QCalendarWidget(self)
        cal.setGridVisible(True)
        cal.move(20, 20)
        cal.clicked[QDate].connect(self.showDate)

        self.lbl = QLabel(self)
        date = cal.selectedDate()
        self.lbl.setText(date.toString())
        self.lbl.move(130, 260)

        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('Calendar')
        self.show()


    def showDate(self, date):

        self.lbl.setText(date.toString())


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Пример имеет виджет календаря и виджет метки. Текущая выбранная дата отображается в виджете метки.

cal.clicked[QDate].connect(self.showDate)

Если мы выбираем дату из виджета, срабатывает сигнал clicked[QDate]. Мы присоединяем этот сигнал к пользовательскому методу showDate().

def showDate(self, date):
    self.lbl.setText(date.toString())

Мы возвращаем выбранную дату путём вызова метода selectedDate(). Тогда мы превращаем объект даты в строку и устанавливаем его в виджет метки.

В этой части руководства PyQt5, мы изучили некоторые виджеты.

Для вставки кода на Python в комментарий заключайте его в теги <pre><code class="python3">Ваш код</code></pre>
Опечатка в тексте:
Послать сообщение об ошибке автору?