Рисуем свою кнопку в QGraphicsScene в PyQt4

в 11:41, , рубрики: button, pyqt, pyqt4, python, Qt Software, кнопка, метки: , , , ,

Казалось бы, что может быть проще обычной кнопки с её стандартным поведением и привычным всему миру видом? Однако, сам процесс создания своей кнопки не менее интересен, чем создание целого приложения с помощью PyQt4.

Здесь приводится пример создания в QGraphicsScene своей рисованной кнопки с помощью QGraphicsWidget.

Рекомендуется к прочтению людям, имеющим опыт работы с PyQt4.

Для начала, разберёмся, что из себя представляет кнопка.
Обычная кнопка — это, чаще всего, прямоугольник с текстом и/или картинкой, щелчок мышью на который сопровождается визуальным откликом. Основное назначение кнопок — реагировать на простое событие нажатия и отжатия указателем мыши (или пальцем), находящегося в поле координат этой кнопки.

  1. # -*- coding: utf-8 -*-
  2. from PyQt4 import QtCore, QtGui
  3. import sys
  4.  
  5. class AButton(QtGui.QGraphicsWidget):
  6.     # нажата ли кнопка мыши
  7.     mouse_isPressed = False
  8.  
  9.     def __init__(self, parent = None):
  10.         QtGui.QGraphicsWidget.__init__(self)
  11.  
  12.     def boundingRect(self):
  13.         # размеры кнопки
  14.         # для наглядности возвращается фиксированное значение
  15.         # хотя можно считать размеры текста и иконки и
  16.         # использовать их динамически.
  17.         # QRectF, в отличие от QRect, позволяет оперировать
  18.         # числами с плавающей точкой.
  19.         return QtCore.QRectF(0, 0, 40, 40)
  20.  
  21.     def paint(self, painter, option, widget = 0):
  22.         # метод прорисовки кнопки со стилями
  23.         opt = QtGui.QStyleOptionButton()
  24.  
  25.         # стиль нажатой и отжатой кнопки в зависимости от того,
  26.         # нажата ли кнопка мыши
  27.         opt.state = ((QtGui.QStyle.State_Sunken if self.mouse_isPressed else QtGui.QStyle.State_Raised) | QtGui.QStyle.State_Enabled)
  28.         # текст на кнопке
  29.         opt.text = self.text()
  30.         # иконка кнопки
  31.         opt.icon = self.icon()
  32.         # геометрия
  33.         opt.rect = option.rect
  34.         # палитра для стиля
  35.         opt.palette = option.palette
  36.  
  37.         # сама прорисовка кнопки с определённым выше стилем и опциями
  38.         QtGui.QApplication.style().drawControl(QtGui.QStyle.CE_PushButton, opt, painter)
  39.  
  40.     def text(self):
  41.         # метод, возвращающий текст, отображаемый на кнопке
  42.         # для наглядности возвращаем фиксированное значение
  43.         return QtCore.QString("hi")
  44.  
  45.     def icon(self):
  46.         # метод, возвращающий иконку кнопки
  47.         # пока возвращаем пустую иконку
  48.         # вроде можно использовать QPixmap вместо QIcon
  49.         return QtGui.QIcon()
  50.  
  51.     def mousePressEvent(self, event):
  52.         # событие нажания кнопки мыши и обновление
  53.         # внешнего вида состояния кнопки
  54.         self.mouse_isPressed = True
  55.         self.update()
  56.  
  57.     def mouseReleaseEvent(self, event):
  58.         # отжатие кнопки
  59.         self.mouse_isPressed = False
  60.         # метод update - обязательный, он отвечает за перерисовку
  61.         # любого графического виджета
  62.         self.update()
  63.  
  64. if __name__ == "__main__":
  65.     app = QtGui.QApplication(sys.argv)
  66.  
  67.     # создаём графическую область, на которой будет рисоваться
  68.     # наша кнопка
  69.     scene = QtGui.QGraphicsScene()
  70.     # создаём кнопку
  71.     button = AButton()
  72.     # добавляем кнопку в графическую область
  73.     scene.addItem(button)
  74.  
  75.     # и создаём графическое поле, на которое накладывается
  76.     # графическая область с кнопкой
  77.     view = QtGui.QGraphicsView(scene)
  78.     # сглаживание
  79.     view.setRenderHint(QtGui.QPainter.Antialiasing)
  80.     # задаём размер графического поля
  81.     view.resize(200, 100)
  82.     # фон
  83.     view.setBackgroundBrush(QtGui.QApplication.palette().background())
  84.     view.show()
  85.  
  86.     sys.exit(app.exec_())

В моём случае, этот код исправно работает в PyQt 4.9.1 for Python 2.7.

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

Изначально, вышеописанный код был найден в интернете, написанный на C++, благополучно сохранён на компьютер, а источник утерян. Позже и сам код был переписан на язык Python с некоторыми особенностями, а оригинал удалён с компьютера.

Благодарю за внимание.

Автор: Chrizt

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js