[Python, Qt] Кастомизация календаря на PyQt5
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Сегодня столкнулся с простой на первый взгляд задачей: в виджете календаря на PyQt5 сделать так, чтобы сегодняшняя дата обводилась зеленой рамкой. Но оказалось, что на русском языке материалов на эту тему вообще нет, а на английском - только один вопрос на stackoverflow. Решил облегчить жизнь другим разработчикам, которые только знакомятся с этой библиотекой и описать, как я решал эту задачу. Создаем календарьЧтобы создать окно с календарем, открываем Qt Creator или Qt Designer. В боковом меню во вкладке Display Widgets выбираем Calendar и перетаскиваем в редактор:
После этого сохраняем получившийся .ui-файл. Чтобы его конвертировать в Python-файл, запускаем в терминале команду:
pyuic5 path/to/design.ui -o output/path/to/design.py
Если вы видите сообщение, что такой команды нет, то, скорее всего, что-то не так с PyQt. Проверьте переменную PATH или попробуйте переустановить PyQt.После выполнения этой команды появляется файл design.py, в который мы и будем вносить изменения. Кастомизация календаряВ стандартом виджете подсвечивается только выбранная дата. Чтобы сегодняшняя дата была подсвечена постоянно, нужно сделать свой виджет на основе встроенного. Создаем файл CustomCalendar.py, в котором расширяем класс QtWidgets.QCalendarWidget:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
class MyCalendar(QtWidgets.QCalendarWidget):
def __init__(self, parent=None):
QtWidgets.QCalendarWidget.__init__(self, parent)
Теперь нужно перегрузить метод отрисовки ячейки в календаре:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
class MyCalendar(QtWidgets.QCalendarWidget):
def __init__(self, parent=None):
QtWidgets.QCalendarWidget.__init__(self, parent)
def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
if date == date.currentDate():
painter.setBrush(QtGui.QColor(0, 200, 200, 50))
painter.drawRect(rect)
Метод printCell принимает три аргумента:
- painter - часть библиотеки Qt, которая отвечает за отрисовку
- rect - объект, в котором содержится информация о позиции и размерах ячейки, которая отрисовывается
- date - дата, которую отражает эта ячейка
Сначала вызывается метод родителя, чтобы календарь выглядел так, как должен. А затем можно добавить что-то, что нужно нам. Например, если ячейка описывает дату, совпадающую с сегодняшней, поверх нее можно нарисовать полупрозрачный зеленый прямоугольник, и она будет постоянно подсвечена. Теперь в файле design.py подключаем модуль CustomCalendar и заменяем QtWidgets.QCalendarWidget на MyCalendar:
from PyQt5 import QtCore, QtGui, QtWidgets
from CustomCalendar import MyCalendar
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(600, 502)
MainWindow.setStyleSheet("")
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.calendarWidget = MyCalendar(self.centralWidget)
self.calendarWidget.setGeometry(QtCore.QRect(60, 50, 471, 341))
self.calendarWidget.setObjectName("calendarWidget")
MainWindow.setCentralWidget(self.centralWidget)
self.menuBar = QtWidgets.QMenuBar(MainWindow)
self.menuBar.setGeometry(QtCore.QRect(0, 0, 600, 22))
self.menuBar.setObjectName("menuBar")
MainWindow.setMenuBar(self.menuBar)
self.mainToolBar = QtWidgets.QToolBar(MainWindow)
self.mainToolBar.setObjectName("mainToolBar")
MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
self.statusBar = QtWidgets.QStatusBar(MainWindow)
self.statusBar.setObjectName("statusBar")
MainWindow.setStatusBar(self.statusBar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
Чтобы приложение запустилось, нужно создать минимальный файл с логикой приложения. Назовем его logic.py:
from PyQt5 import QtWidgets
import sys
import design
class CalendarApp(QtWidgets.QMainWindow, design.Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
def main():
app = QtWidgets.QApplication(sys.argv)
window = CalendarApp()
window.show()
app.exec_()
if __name__ == '__main__':
main()
Запускаем приложение и видим, что всё получилось:
Чтобы убрать черную рамку, в функции paintRect нужно изменить painter так, чтобы обводка была прозрачной:
def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
if date == date.currentDate():
painter.setBrush(QtGui.QColor(0, 200, 200, 50))
painter.setPen(QtGui.QColor(0, 0, 0, 0))
painter.drawRect(rect)
Обводим ячейкуПервоначальная задача была сделать для сегодняшней даты зеленую рамку. Кажется, что достаточно нарисовать прямоугольник с зеленой обводкой. Для этого нужно убрать строчку с painter.setBrush и установить нужный цвет в painter.setPen. Но если сделать так, то получается не очень красиво:
Ответ на то, как у этого прямоугольника сделать границы одинаковой толщины, я не нашел. Но ничего не мешает нарисовать четыре отдельные линии:
def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date)
if date == date.currentDate():
painter.setPen(QtGui.QPen(QtGui.QColor(0, 200, 200), 2, Qt.SolidLine, Qt.RoundCap))
painter.drawLine(rect.topRight(), rect.topLeft())
painter.drawLine(rect.topRight(), rect.bottomRight())
painter.drawLine(rect.bottomLeft(), rect.bottomRight())
painter.drawLine(rect.topLeft(), rect.bottomLeft())
И финальный результат:
Что ещё можно сделатьС помощью painter можно не только обвести или закрасить ячейку, но и написать в ней какой-то текст или нарисовать геометрическую фигуру. Всё зависит от решаемой задачи и воображения разработчика.
===========
Источник:
habr.com
===========
Похожие новости:
- [Анализ и проектирование систем, ERP-системы, Управление разработкой, DevOps] Как сделать хорошую интеграцию? Часть 1
- [Разработка веб-сайтов] 5 распространенных ошибок разработчиков, влияющих на время загрузки страницы (перевод)
- [Высокая производительность, Ненормальное программирование] Новогодние бенчмарки компьютеров Эльбрус
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android, Тестирование мобильных приложений] 3 видео для мобильного разработчика
- [Программирование, Разработка мобильных приложений, Разработка под Android, Развитие стартапа, Софт] Бизнес-идея для программистов. Совершенно незанятая ниша на рынке программ
- [Open source, JavaScript, Голосовые интерфейсы] Навыки для виртуальных ассистентов на веб-технологиях
- [Работа с видео, Разработка игр, Монетизация игр, Игры и игровые приставки] Какие ролики об играх мы сделали в 2020-м
- [Управление разработкой, Управление проектами, Фриланс, Производство и разработка электроники, Электроника для начинающих] Как разработать корпус силами фрилансеров — промдизайнеров и конструкторов
- [Производство и разработка электроники, Нанотехнологии] Японские исследователи обнаружили способ промышленного производства нанопроводов
- [Python, Обработка изображений, Машинное обучение, Искусственный интеллект, Natural Language Processing] Первое место на AI Journey 2020 Digital Петр
Теги для поиска: #_python, #_qt, #_pyqt5, #_python, #_razrabotka (разработка), #_python, #_qt
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:53
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Сегодня столкнулся с простой на первый взгляд задачей: в виджете календаря на PyQt5 сделать так, чтобы сегодняшняя дата обводилась зеленой рамкой. Но оказалось, что на русском языке материалов на эту тему вообще нет, а на английском - только один вопрос на stackoverflow. Решил облегчить жизнь другим разработчикам, которые только знакомятся с этой библиотекой и описать, как я решал эту задачу. Создаем календарьЧтобы создать окно с календарем, открываем Qt Creator или Qt Designer. В боковом меню во вкладке Display Widgets выбираем Calendar и перетаскиваем в редактор: После этого сохраняем получившийся .ui-файл. Чтобы его конвертировать в Python-файл, запускаем в терминале команду: pyuic5 path/to/design.ui -o output/path/to/design.py
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt class MyCalendar(QtWidgets.QCalendarWidget): def __init__(self, parent=None): QtWidgets.QCalendarWidget.__init__(self, parent) from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt class MyCalendar(QtWidgets.QCalendarWidget): def __init__(self, parent=None): QtWidgets.QCalendarWidget.__init__(self, parent) def paintCell(self, painter, rect, date): QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date) if date == date.currentDate(): painter.setBrush(QtGui.QColor(0, 200, 200, 50)) painter.drawRect(rect)
from PyQt5 import QtCore, QtGui, QtWidgets
from CustomCalendar import MyCalendar class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(600, 502) MainWindow.setStyleSheet("") self.centralWidget = QtWidgets.QWidget(MainWindow) self.centralWidget.setObjectName("centralWidget") self.calendarWidget = MyCalendar(self.centralWidget) self.calendarWidget.setGeometry(QtCore.QRect(60, 50, 471, 341)) self.calendarWidget.setObjectName("calendarWidget") MainWindow.setCentralWidget(self.centralWidget) self.menuBar = QtWidgets.QMenuBar(MainWindow) self.menuBar.setGeometry(QtCore.QRect(0, 0, 600, 22)) self.menuBar.setObjectName("menuBar") MainWindow.setMenuBar(self.menuBar) self.mainToolBar = QtWidgets.QToolBar(MainWindow) self.mainToolBar.setObjectName("mainToolBar") MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar) self.statusBar = QtWidgets.QStatusBar(MainWindow) self.statusBar.setObjectName("statusBar") MainWindow.setStatusBar(self.statusBar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) from PyQt5 import QtWidgets
import sys import design class CalendarApp(QtWidgets.QMainWindow, design.Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) def main(): app = QtWidgets.QApplication(sys.argv) window = CalendarApp() window.show() app.exec_() if __name__ == '__main__': main() Чтобы убрать черную рамку, в функции paintRect нужно изменить painter так, чтобы обводка была прозрачной: def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date) if date == date.currentDate(): painter.setBrush(QtGui.QColor(0, 200, 200, 50)) painter.setPen(QtGui.QColor(0, 0, 0, 0)) painter.drawRect(rect) Обводим ячейкуПервоначальная задача была сделать для сегодняшней даты зеленую рамку. Кажется, что достаточно нарисовать прямоугольник с зеленой обводкой. Для этого нужно убрать строчку с painter.setBrush и установить нужный цвет в painter.setPen. Но если сделать так, то получается не очень красиво: Ответ на то, как у этого прямоугольника сделать границы одинаковой толщины, я не нашел. Но ничего не мешает нарисовать четыре отдельные линии: def paintCell(self, painter, rect, date):
QtWidgets.QCalendarWidget.paintCell(self, painter, rect, date) if date == date.currentDate(): painter.setPen(QtGui.QPen(QtGui.QColor(0, 200, 200), 2, Qt.SolidLine, Qt.RoundCap)) painter.drawLine(rect.topRight(), rect.topLeft()) painter.drawLine(rect.topRight(), rect.bottomRight()) painter.drawLine(rect.bottomLeft(), rect.bottomRight()) painter.drawLine(rect.topLeft(), rect.bottomLeft()) Что ещё можно сделатьС помощью painter можно не только обвести или закрасить ячейку, но и написать в ней какой-то текст или нарисовать геометрическую фигуру. Всё зависит от решаемой задачи и воображения разработчика. =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:53
Часовой пояс: UTC + 5