Быстрый в изучении - мощный в программировании
>> Telegram ЧАТ для Python Программистов

Свободное общение и помощь советом и решением проблем с кодом! Заходите в наш TELEGRAM ЧАТ!

>> Python Форум Помощи!

Мы создали форум где отвечаем на все вопросы связанные с языком программирования Python. Ждем вас там!

>> Python Канал в Telegram

Обучающие статьи, видео и новости из мира Python. Подпишитесь на наш TELEGRAM КАНАЛ!

Виджеты PyQt5 [Урок №7]

Виджеты 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('')

Состояние виджета даётся методом changeTitle() в переменной state. Если виджет помечен галочкой, мы устанавливаем заголовок окна. В противном случае, мы устанавливаем пустую строку в заголовке.

QCheckBox

Рисунок: QCheckBox

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

Кнопка переключателя – это 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)
 
        redb = QPushButton('Green', self)
        redb.setCheckable(True)
        redb.move(10, 60)
 
        redb.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. Мы устанавливаем чёрный цвет фона 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)

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

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)

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

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 на метку, если ползунок приравнен к нулю.

QSlider

Рисунок: Виджет QSlider

QProgressBar

Индикатор прогресса – это виджет, который используется, когда мы обрабатываем продолжительные задачи. Он анимирует процесс, чтобы пользователи знали, что задача продвигается. Виджет QProgressBar предоставляет горизонтальный и вертикальный индикатор прогресса в инструментарии PyQt5. Программисы могут установить минимальное и максимальнео значение для индикатора прогресса. Значения по умолчанию – 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(), мы запускаем и останавливаем таймер.

QProgressBar

Рисунок: QProgressBar

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 = QCalendarWidget(self)

Создан QCalendarWidget.

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

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

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

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

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

Прошлый урок: Диалоги в PyQt5 [Урок №6]

Комментариев: 3
  1. При исполнении на MAC OS примера с QSlider

    в окне не появляется изображение.

    Где брать файлы картинок на которые ссылаются примеры?

  2. SM, на сайте https://iconfinder.com/ их там море.

    Скачай нужные иконки и копируй в ту же папку где исполняется ваше приложение.

  3. Может глупый вопрос где почитать для чего используется такая конструкция.

    в функции переменная после self

    Например, тут это date

    def showDate(self, date):

    при вызове же не передается нечего в это функцию, зачем указывать тогда переменную?