Малюємо кругову діаграму в PyQt5

Діаграма однозначно стане прикрасою вашого додатку і допоможе візуалізувати те, що складно описати словами та цифрами. За допомогою набору бібліотек PyQt5, про який ми говорили в попередній статті, можна створити чимало яскравих діаграм різного типу. Однак сьогодні ми зупинимося на круговій.

Стандартно почнемо з так званого базового коду для додатку PyQt5. Його детальний опис я вже проводила в попередній статті, тому зараз продублюю лише код:

from PyQt5.QtWidgets import QMainWindow, QApplication

class DiagramApp(QMainWindow):                
    def __init__(self):
        super().__init__()                  
        self.setWindowTitle("Diagram App")    
        self.setFixedSize(1000, 1000) 

def run_app():
    form = QApplication([])                 
    WidMain = DiagramApp()                    
    WidMain.show()                          
    form.exec_()                            

if __name__== '__main__':                   
    run_app()

Після запуску побачимо порожнє вікно:

Тепер почнемо працювати з діаграмою. Перше, що нам необхідно – це, звичайно ж, дані, на основі яких ми будемо її будувати. Розглянемо список з кортежів products, де перше значення кожного кортежу – тип продукту, а друге – загальна ціна:

products = [
            ('electronics', 1000),
            ('clothing', 890),
            ('books', 720),
            ('kitchenware', 600),
            ('groceries', 530),
            ('toys', 400),
            ('cosmetics', 350),
            ('others', 200)
             ] 

Для побудови діаграми нам знадобиться цілих три класи з модулю PyQt5.QtChart. Щоб їх описати, без методу асоціацій, напевно, не обійтися.

  • QPieSeries. Якщо розглянути кругову діаграму у вигляді торту, то QPieSeries – чимось нагадує список шматочків, з яких вона складається. Ми можемо додавати і видаляти «шматочки» за допомогою методів append та remove.
  • QChart. Всі ці «шматочки» об’єднуються в один великий «торт» під назвою QChart. Якщо серйозно, то даний клас відповідає за так звану технічну частину нашої діаграми, а саме управляє даними, які необхідні для відображення (тут відбувається встановлення осей координат, заголовку, керування стилем тощо).
  • QChartView – відображає QChart і все те, що ми в ньому налаштували.  

Тепер розглянемо код, який нам допоможе створити кругову діаграму в PyQt5:

Pieseries = QPieSeries()    

Chart = QChart()
Chart.addSeries(Pieseries)

Diagram = QChartView(Chart)  

В принципі, нічого особливого і суперскладного в даному коді нема. Створено три екземпляри класів, які по черзі «вкладаються» один в один (якщо це можна так назвати).

Однак  тут ми не зробили головного, а саме не «сконтактували» наші дані з діаграмою. Цей процес ми робитимемо через клас QPieSeries, створивши «шматочки» і послідовно додавши їх до нашого «торту», а також встановивши їхній колір:

for p in products:
    Oneslice = Pieseries.append(p[0], p[1])
    Oneslice.setBrush(QColor(21, 187, 185))

Наразі колір у всіх слайсів однаковий і брала я його з сайту HTML COLOR CODES. Це моє улюблене джерело, що дозволяє отримати «координати» потрібного кольору у різних моделях. Ось обраний нами колір:

Підемо далі і відобразимо назви продуктів на діаграмі, використовуючи такий метод:

Pieseries.setLabelsVisible()

Ну і, нарешті, помістимо сформований віджет в центр нашого головного вікна:

self.setCentralWidget(Diagram)

Отже, весь код матиме такий вигляд:

from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtChart import QPieSeries, QChart, QChartView
from PyQt5.QtGui import QColor

class DiagramApp(QMainWindow):                
    def __init__(self):
        super().__init__()                  
        self.setWindowTitle("Diagram App")    
        self.setFixedSize(1000, 1000) 

        Pieseries = QPieSeries()    

        Chart = QChart()
        Chart.addSeries(Pieseries)

        Diagram = QChartView(Chart)  

       products = [
                        ('electronics', 1000),
                        ('clothing', 890),
                        ('books', 720),
                        ('kitchenware', 600),
                        ('groceries', 530),
                        ('toys', 400),
                        ('cosmetics', 350),
                        ('others', 200)
                        ] 
        
        for p in products:
            Oneslice = Pieseries.append(p[0], p[1])
            Oneslice.setBrush(QColor(21, 187, 185))

        Pieseries.setLabelsVisible()
        
        self.setCentralWidget(Diagram)

def run_app():
    form = QApplication([])                 
    WidMain = DiagramApp()                    
    WidMain.show()                          
    form.exec_()                            

if __name__== '__main__':                   
    run_app()

Після запуску ви побачите наступну картину:

Напевно, вам захочеться мати різнокольорову діаграму. Однак я не впевнена, що ваш додаток повинен бути схожий на веселку. Зазвичай вимагається, щоб кольори були в одному стилі, не надто відхиляючись від кольорів інших елементів додатка. Тому пропоную змінити наш код, враховуючи цей важливий момент.

Як ви вже напевно побачили, граючись з кольорами на сайті HTML COLOR CODES, достатньо змінити лише один параметр і ми не надто сильно відхилимося від заданого стилю додатку:

Це будуть лише відтінки бірюзового кольору, які поступово переходять у сірі. Тому просто змінюватимемо одну цифру і таким чином досягнемо потрібного результату. Для цього оновимо код додавання слайсів на QPieSeries:

startcolor = 20           #наше початкове значеня R
currentcolor = startcolor
colorrestriction = 182    #наше кінцеве значення R
for p in products:
    Oneslice = Pieseries.append(p[0], p[1])
    Oneslice.setBrush(QColor(currentcolor, 187, 185))
    currentcolor += round((colorrestriction - startcolor)/len(products))  

Тобто цикл «бігає» лише по значенням R, а все інше лишається тим самим. Звичайно, ви можете сюди додати різноманітні «заглушки» на випадок порожнього масиву даних чи якихсь інших «траблів» – я показала тільки ідею.

Ось як це виглядає тепер:

Як бачите, ми не відхилилися від загального стилю, але при цьому зробили діаграму кольоровою і більш привабливою для глядача.