Bài 32: Trực quan hóa dữ liệu – PyQtGraph-PlotWidget-PyQt6 – Part 2

Bài học này Tui trình bày chi tiết về đối tượng PlotWidget được đề cập trong PyQtGraph Part 1 mà ta đã dùng để vẽ một Chart đơn giản.

Việc nắm được ý nghĩa và các kỹ thuật sử dụng các phương thức của đối tượng PlotWidget sẽ giúp chúng ta dễ dàng hiệu chỉnh Chart theo nhu cầu:

  1. Thiết lập tiêu đề cho Chart
  2. Thiết lập tiêu đề cho các Trục
  3. Thiết lập màu nền cho Chart
  4. Thiết lập Background Grid
  5. Thiết lập màu, độ rộng và kiểu dáng của đường kẻ
  6. Thiết lập Line Markers
  7. Thiết lập Legends
  8. Thiết lập giới hạn các trục
  9. Thiết lập multiple plot trong một Chart
  10. Xóa và cập nhật Plot

Tui tóm tắt sơ lược ý nghĩa chức năng của một số phương thức của PlotWidget

Phương thứcÝ nghĩa chức năng
setTitle(title)Thiết lập tiêu đề cho Chart
Ví dụ:
self.graphWidget.setTitle(“My Chart Title”)
setTitle(title, color, size)Thiết lập tiêu đề cho Chart cùng với định dạng màu chữ và cỡ chữ.
Ví dụ:
self.graphWidget.setTitle(“My Chart Title”, color=”b”, size=”30pt”)
setLabel(position,text)Thiết lập tiêu đề cho các trục.
position có 4 giá trị: ‘left,’right’,’top’,’bottom’
Ví dụ:
styles = {‘color’:’r’, ‘font-size’:’30pt’}
self.graphWidget.setLabel(‘left’, ‘Temperature (°C)’, **styles)
self.graphWidget.setLabel(‘bottom’, ‘Hour (H)’, **styles)
setBackground(background)Phương thức này dùng để thiết lập màu nền cho Chart.
Ví dụ:
import pyqtgraph as pg
self.graphWidget=pg.PlotWidget()
self.graphWidget.setBackground(“y”)
showGrid(x=True, y=True)Hiển thị lưới cho Chart
plot(X value, Y value,
name=”Plot 1″,
pen=pen, symbol=”+”,
symbolSize=30,
symbolBrush=(“b”),
)
Hàm để vẽ Chart có sử dụng Pen để định dạng đường vẽ như màu đường kẻ, kiểu đường kẻ, độ dày đường kẻ, biểu tượng.
Ví dụ:
pen = pg.mkPen(color=(255, 0, 0))
self.graphWidget.plot(hour, temperature, pen=pen)
addLegend()Hàm hiển thị Legend cho Chart
setXRange(5, 20, padding=0)Thiết lập giới hạn cho trục X
setYRange(30, 40, padding=0)Thiết lập giới hạn cho trục Y
clear()Xóa các plot trên Chart
data_line= graphWidget.plot(x, y)

data_line.setData(new x, new y)
Cập nhật dữ liệu cho Plot

Tui trình bày chi tiết các chức năng dưới này, vừa kết hợp lý thuyết và thực hành, các bạn nhớ thực hiện theo.

Tạo dự án “LearnPyQtGraphPart2” thiết kế giao diện và dữ liệu mẫu giống như bài trước. Bạn có thể copy y chang toàn bộ các file .py, .ui của bài trước vào “LearnPyQtGraphPart2” để sử dụng luôn

  • “MainWindow.ui” là giao diện được thiết kế bằng Qt Designer
  • “MainWindow.py” là generate python code của “MainWindow.ui”
  • “MainWindowEx.py” là file mã lệnh kế thừa từ “MainWindow.py” để xử lý nạp giao diện, gán Chart và các sự kiện, lớp này sẽ không lệ thuộc vào sự thay đổi của giao diện cũng như generate code
  • “MyApp.py” là file mã lệnh thực thi chương trình

Giao diện “MainWindow.ui” và dữ liệu mẫu trong “MainWidowEx.py” là y chang như bài trước nên Tui không chụp hình lại, các bạn tự chuyển qua. Còn dưới đây Tui sẽ lần lượt hướng dẫn từng chức năng cụ thể, các bạn bổ sung vào “MainWindowEx.py“:

1. Thiết lập tiêu đề cho Chart

Ta thiết lập tiêu đề cho Chart bằng hàm setTitle(title)

self.graphWidget.setTitle("Chart Title Here")

Ngoài ra ta có thể định dạng style cho title như màu tiêu đề, cỡ chữ tiêu đề, in đậm, in nghiêng.

StyleCách dùng
color‘CCFF00’ , ‘b’
size’10pt’
boldTrue/False
italicTrue/False
self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt",bold=True,italic=True)

Dưới đây là chi tiết mã lệnh của MainWindowEx.py cho phần tiêu đề:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        self.graphWidget.plot(hour, temperature)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy “MyApp.py” ta có kết quả:

Ngoài ra ta cũng có thể thiết lập title bằng cấu trúc HTML như dưới đây:

self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")


2. Thiết lập tiêu đề cho các Trục

Chúng ta dùng hàm setLabel(position,text,style) để thiết lập tiêu đề cho các trục. position có ‘left,’right’,’top’,’bottom’. Ví dụ:

styles = {"color": "#f00", "font-size": "20px"}
self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
self.graphWidget.setLabel("bottom", "Hour (H)", **styles)

Coding đầy đủ của MainWindowEx.py cho phần thiết lập tiêu đề cho các Trục:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        self.graphWidget.plot(hour, temperature)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy “MyApp.py” ta có kết quả như dưới đây:

Ở Chart bên trên ta thấy, cả 4 trục đều có tiêu đề.


3. Thiết lập màu nền cho Chart

Bây giờ ta làm quen với phương thức setBackground(). Phương thức đổi thiết lập màu nền có thể nhận các dạng màu sau:

  • Dùng Letter code
ColorLetter Code
blueb
greeng
redr
cyanc
magentam
yellowy
blackk
whitew

Ví dụ lệnh dưới đây thiết lập nền trắng cho Chart:

self.graphWidget.setBackground("w")
  • Dùng hex color

Danh sách Hex Color bạn có thể lấy nhiều nơi, có thể lấy ở đây:

https://www.color-hex.com/

Ví dụ ta thiết lập màu nền Hex Color #ff0000 màu đỏ:

self.graphWidget.setBackground('#ff0000')
  • Sử dụng RGB (Red – Green-Blue) RGBA (Red Green Blue Alpha Opacity)

Khi dùng RGB thì ta dùng bộ 3:

self.graphWidget.setBackground((100,50,255)) # RGB each 0-255

Khi dùng RGBA thì ta dùng bộ 4:

self.graphWidget.setBackground((100,50,255,25)) # RGBA (A = alpha opacity)
  • Ngoài ra ta có thể dùng đối tượng QColor để thiết lập màu
self.graphWidget.setBackground(QColor(50, 168, 82,255)) # R, G, B, A

Mã lệnh đầy đủ của MainWindowEx.py để đổi màu nền của Chart qua màu trắng:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        self.graphWidget.plot(hour, temperature)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy “MyApp.py” ta có kết quả:


4. Thiết lập Background Grid

Để hiển thị lưới cho Chart ta dùng hàm .showGrid()

self.graphWidget.showGrid(x=True, y=True)

Ta có thể tùy chỉnh trục nào sẽ xuất hiện lưới, mã lệnh ở trên là hiển thị cả trục tung và trục hoành, dưới đây là mã lệnh đầy đủ của MainWindowEx.py:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        self.graphWidget.plot(hour, temperature)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy “MyApp.py” ta có kết quả:


5. Thiết lập màu, độ rộng và kiểu dáng của đường kẻ

  • Bây giờ chúng ta làm quen với đối tượng QPen hiệu chỉnh màu đường kẻ, kiểu đường kẻ, độ dày đường kẻ:
pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DashLine)
self.graphWidget.plot(hour, temperature,pen=pen)

Kiểu của đường kẻ ta dùng như dưới đây:

Enum StyleÝ nghĩa chức năng
Qt.PenStyle.SolidLineVẽ đường liên tục
Qt.PenStyle.DashLineVẽ đường các gạch ngang
Qt.PenStyle.DotLineVẽ đường các chấm
Qt.PenStyle.DashDotLineVẽ đường: Gạch ngang – chấm – gạch ngang
Qt.PenStyle.DashDotDotLineVẽ đường: Gạch ngang – chấm- chấm – gạch ngang

Coding đầy đủ của MainWindowEx.py:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from PyQt6.QtCore import Qt

from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DashDotLine)
        self.graphWidget.plot(hour, temperature,pen=pen)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy MyApp.py ta có kết quả:


6. Thiết lập Line Markers

Để thiết lập Markers cho các Line plot, ta dùng các thuộc tính sau cho hàm plot() của đối tương PlotWidget:

self.graphWidget.plot(hour, temperature, pen=pen, symbol='+', symbolSize=30, symbolBrush=('b'))
  • symbol: Thiết lập biểu tượng của Marker
SymbolÝ nghĩa
oCircular
sSquare
tTriangular
dDiamond
+Cross
  • symbolSize: Thiết lập độ lớn của Marker
  • symbolBrush: Thiết lập màu của Marker
  • symbolPen: Thiết lập màu đường viên của Marker

Dưới đây là coding minh họa phần Marker trong MainWindowEx.py:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from PyQt6.QtCore import Qt

from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DotLine)
        symbolPen = pg.mkPen(color=(196, 196, 196), width=2)
        self.graphWidget.plot(hour, temperature, pen=pen,
                              symbol='+',
                              symbolSize=15,
                              symbolBrush=('b'),
                              symbolPen=symbolPen)
        #self.graphWidget.plot(hour, temperature,pen=pen)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy MyApp.py ta có kết quả:

Ta thấy Marker có màu xanh (symbolBrush) và màu viền là xám (symbolPen), biểu tượng + (symbol), kích thước của marker (symbolSize). Ta thử thay thế các symbol khác nhau rồi quan sát so sánh kết quả.


7. Thiết lập Legends

Để thiết lập Legends cho Chart, trước tiên các Line/plot cần được đặt tên khi gọi phương thức plot() của PlotWidget.

Sau đó ta gọi phương thức addLegend() của PlotWidget.

self.graphWidget.addLegend()
self.graphWidget.plot(hour, temperature,name="Sensor X",
                      pen=pen,
                      symbol='+',
                      symbolSize=15,
                      symbolBrush=('b'),
                      symbolPen=symbolPen)

Dưới đây là mã lệnh đầy đủ của MainWindowEx.py để hiển thị Legend:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from PyQt6.QtCore import Qt

from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DotLine)
        symbolPen = pg.mkPen(color=(196, 196, 196), width=2)
        self.graphWidget.addLegend()
        self.graphWidget.plot(hour, temperature,name="Sensor X",
                              pen=pen,
                              symbol='+',
                              symbolSize=15,
                              symbolBrush=('b'),
                              symbolPen=symbolPen)
        #self.graphWidget.plot(hour, temperature,pen=pen)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy “MyApp.py” ta có kết quả:

Quan sát Chart ta thấy Legen “Sensor X” được hiển thị mặc định ở góc trái bên trên của Chart, ta có thể dùng chuột để di chuyển.


8. Thiết lập giới hạn các trục

Đôi khi trong quá trình trực quan hóa dữ liệu, chúng ta cần thiết phải giới hạn hiển thị dữ liệu ở các trục.

Ta dùng hàm setXRange(min, max,padding) và setYRange(min,max,padding) để giới hạn

Ví dụ:

self.graphWidget.setXRange(1, 8, padding=0)
self.graphWidget.setYRange(10, 80, padding=0)

Dưới đây là mã lệnh đầy đủ của MainWindowEx.py:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from PyQt6.QtCore import Qt

from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        # Step 4: call plot method
        pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DotLine)
        symbolPen = pg.mkPen(color=(196, 196, 196), width=2)
        self.graphWidget.addLegend()
        self.graphWidget.setXRange(1, 8, padding=0)
        self.graphWidget.setYRange(10, 80, padding=0)
        self.graphWidget.plot(hour, temperature,name="Sensor X",
                              pen=pen,
                              symbol='+',
                              symbolSize=15,
                              symbolBrush=('b'),
                              symbolPen=symbolPen)
        #self.graphWidget.plot(hour, temperature,pen=pen)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy MyApp.py ta có kết quả:


9. Thiết lập multiple plot trong một Chart

Thông thường khi vẽ chart ta hay kết hợp nhiều plot để hiển thị, so sánh…. PyQtGraph cũng hỗ trợ đặc tính này:

hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
temperature2 = [25, 18, 30,10, 47, 29, 26, 32, 35, 45, 40, 42]

pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DotLine)
pen2 = pg.mkPen(color=(0, 0, 255), width=8, style=Qt.PenStyle.SolidLine)

symbolPen = pg.mkPen(color=(196, 196, 196), width=2)
symbolPen2 = pg.mkPen(color=(255, 255, 0), width=2)


self.graphWidget.plot(hour, temperature,name="Sensor X",
                      pen=pen,
                      symbol='+',
                      symbolSize=15,
                      symbolBrush=('b'),
                      symbolPen=symbolPen)

self.graphWidget.plot(hour, temperature2, name="Sensor Y",
                      pen=pen2,
                      symbol='d',
                      symbolSize=8,
                      symbolBrush=('r'),
                      symbolPen=symbolPen2)

Mã lệnh ở trên các bạn quan sát Tui bổ sung thêm các biến:

  • temperature2: lưu trữ mảng nhiệt độ mới cho Sensor Y
  • pen2: thiết lập đường kẻ thứ 2
  • symbolPen2: thiết lập biểu tượng cho đường kẻ thứ 2

Và Ta gọi 2 lần hàm plot() của đối tượng PlotWidget (biến graphWidget)

Dưới đây là mã lệnh đẩy đủ của MainWindowEx.py:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from PyQt6.QtCore import Qt

from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        temperature2 = [25, 18, 30,10, 47, 29, 26, 32, 35, 45, 40, 42]
        # Step 4: call plot method
        pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DotLine)
        pen2 = pg.mkPen(color=(0, 0, 255), width=8, style=Qt.PenStyle.SolidLine)
        symbolPen = pg.mkPen(color=(196, 196, 196), width=2)
        symbolPen2 = pg.mkPen(color=(255, 255, 0), width=2)
        self.graphWidget.addLegend()
        #self.graphWidget.setXRange(1, 8, padding=0)
        #self.graphWidget.setYRange(10, 80, padding=0)
        self.graphWidget.plot(hour, temperature,name="Sensor X",
                              pen=pen,
                              symbol='+',
                              symbolSize=15,
                              symbolBrush=('b'),
                              symbolPen=symbolPen)
        self.graphWidget.plot(hour, temperature2, name="Sensor Y",
                              pen=pen2,
                              symbol='d',
                              symbolSize=8,
                              symbolBrush=('r'),
                              symbolPen=symbolPen2)
        #self.graphWidget.plot(hour, temperature,pen=pen)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy “MyApp.py” ta có kết quả:

Ta có thể ẩn/hiển thị các Plot bằng cách nhấn vào Legend, ví dụ như muốn ẩn Sensor Y:

Ta có thể áp dụng kỹ thuật của Multiple Line để tự động nạp nhiều Plot cho 1 Chart. Ví dụ như hãy vẽ biểu đồ doanh thu từng tháng của 10 chi nhánh trong năm 2023.


10. Xóa và cập nhật Plot

Để xóa Plot trên Chart ta gọi lệnh:

self.graphWidget.clear()

Trong quá trình hiển thị Chart, đặc biệt là liên quan tới Realtime data thì rõ ràng ta muốn Chart được cập nhật tự động.

Bước 1: Khai báo đối tượng lưu trữ lại Plot, ví dụ ta khai báo plot 2 cho Sensor Y

plot2=self.graphWidget.plot(hour, temperature2, name="Sensor Y",
                              pen=pen2,
                              symbol='d',
                              symbolSize=8,
                              symbolBrush=('r'),
                              symbolPen=symbolPen2)

Bước 2: Thay đổi giá trị trong mảng temperature2, ví dụ:

temperature2[3]=100

Ở bước 2 này tức là nếu trong quá trình vận hành trực quan hóa, mà bất cứ khi nào đó mảng dữ liệu bị thay đổi. Ở đây là Tui minh họa 1 trường hợp phần tử thứ 3 bị đổi dữ liệu

Bước 3: Gọi hàm setData() của plot2 để cập nhật Plot

plot2.setData(hour, temperature2)

Code đầy đủ của MainWindowEx.py cho phần cập nhật Plot:

#Step 1: import pyqtgraph
import pyqtgraph as pg
from PyQt6.QtCore import Qt

from MainWindow import Ui_MainWindow

class MainWindowEx(Ui_MainWindow):
    def __init__(self):
        super().__init__()
    def setupUi(self, MainWindow):
        super().setupUi(MainWindow)
        self.MainWindow=MainWindow
        #Step 2: call pg.PlotWidget()
        self.graphWidget = pg.PlotWidget()
        #self.graphWidget.setTitle("Temperature per hour")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="30pt")
        #self.graphWidget.setTitle("Temperature per hour", color="b", size="20pt",bold=True,italic=True)
        self.graphWidget.setTitle("<span style=\"color:blue;font-size:20pt\">Temperature per hour</span>")
        styles = {"color": "#f00", "font-size": "20px"}
        self.graphWidget.setLabel("left", "Temperature (°C)", **styles)
        self.graphWidget.setLabel("bottom", "Hour (H)", **styles)
        styles_top_right = {"color": "green", "font-size": "15px"}
        self.graphWidget.setLabel("top", "Learn PyQtGraph",**styles_top_right)
        self.graphWidget.setLabel("right", "tranduythanh.com",**styles_top_right)
        self.graphWidget.setBackground("w")
        self.graphWidget.showGrid(x=True, y=True)
        #Step 3: Create plot data
        hour = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12]
        temperature = [20, 21, 20, 32, 33, 31, 29,31, 32, 35,37, 45]
        temperature2 = [25, 18, 30,10, 47, 29, 26, 32, 35, 45, 40, 42]
        # Step 4: call plot method
        pen = pg.mkPen(color=(255, 0, 0), width=15, style=Qt.PenStyle.DotLine)
        pen2 = pg.mkPen(color=(0, 0, 255), width=8, style=Qt.PenStyle.SolidLine)
        symbolPen = pg.mkPen(color=(196, 196, 196), width=2)
        symbolPen2 = pg.mkPen(color=(255, 255, 0), width=2)
        self.graphWidget.addLegend()
        #self.graphWidget.setXRange(1, 8, padding=0)
        #self.graphWidget.setYRange(10, 80, padding=0)
        self.graphWidget.plot(hour, temperature,name="Sensor X",
                              pen=pen,
                              symbol='+',
                              symbolSize=15,
                              symbolBrush=('b'),
                              symbolPen=symbolPen)
        plot2=self.graphWidget.plot(hour, temperature2, name="Sensor Y",
                              pen=pen2,
                              symbol='d',
                              symbolSize=8,
                              symbolBrush=('r'),
                              symbolPen=symbolPen2)
        temperature2[3]=100
        plot2.setData(hour, temperature2)
        #self.graphWidget.plot(hour, temperature,pen=pen)
        #Step 5: add graphWidget into Layout:
        self.myLayout.addWidget(self.graphWidget)
    def show(self):
        self.MainWindow.show()

Chạy MyApp.py ta thấy temperature2[3]=100 được update.

Dựa vào tính năng nay ta có thể viết code tự động update dữ liệu theo thời gian.

Như vậy tới Tui đã hướng dẫn đầy đủ và chi tiết các chức năng quan trọng và thường dùng của PlotWidget trong trực quan hóa dữ liệu. Các bạn chú ý làm lại nhiều lần và hiểu thật rõ, áp dụng thật tốt từng kỹ thuật để giúp cho trực quan hóa được tốt nhất.

Các bạn tải mã lệnh đầy đủ của dự án ở đây:

https://www.mediafire.com/file/7s7lkzsmsoyufy0/LearnPyQtGraphPart2.rar/file

Bài học sau Tui sẽ minh họa cách sử dụng PyQtGraph và OpenGL để hiển thị 3D Graph, các bạn chú ý theo dõi

Chúc các bạn thành công

2 thoughts on “Bài 32: Trực quan hóa dữ liệu – PyQtGraph-PlotWidget-PyQt6 – Part 2”

Leave a Reply