使用pyat和pyqtgraph实现根据鼠标选择内容进行实时图像绘制

使用pyat和pyqtgraph实现根据鼠标选择内容进行实时图像绘制

  • 1.效果
  • 2.程序组成
  • 3.程序解析
    • 3.1鼠标选择范围捕捉
      • itemSelectionChanged信号
      • selectedIndexes()方法
      • 数据整理
    • 3.2数据传递
    • 3.3图像更新
  • 完整代码
  • 运行效果

1.效果

根据鼠标选择内容,图像动态变化。本文选的是条形图。

2.程序组成

此示例程序涉及到3个界面。
一是图像展示界面,使用的是pyqtgraph库实现。
二是数据界面,用QTableWidget展示数据区域。
三是主界面,组织数据展示界面和图像暂时界面,并且起一个数据传输的作用。

3.程序解析

先来理一下逻辑,要实现根据鼠标选择范围动态绘制图像。首先要捕捉鼠标选择的数据范围,其次传输数据到绘图界面,最后更新图像。我在实现这个效果的时候,网上没有找到直接的示范,东拼西凑找了一些代码,幸运的是,最后顺利完成。

3.1鼠标选择范围捕捉

itemSelectionChanged信号

使用itemSelectionChanged信号触发,并绑定到槽函数handleCellChanged。简单来说,把clicked换成itemSelectionChanged。

selectedIndexes()方法

槽函数handleCellChanged中,要使用到一个很重要的方法selectedIndexes(),这个方法会返回一个选择区域。对这个选择区域进行遍历,可以通过遍历项的row()和column()方法获取遍历项的行索引和列索引。这样我们就可以获得所有选择单元格的索引,有了索引就能获取到数据。

数据整理

获取数据之后,接着就有一个问题,我们现在获取的是一个区域中的数据,比如说这个区域是2列乘6行的一个区域。这里画的是条形图,条形图的数据一组一组的的,这里我把一列做为一组。那就需要对这个数据进行整理,根据索引分成两列数据,我用了一个二维列表来存,一个子列表表示一组数据。

3.2数据传递

数据整理好了,需要传给条形图进行绘制。这里用的pyqt自定义信号机制,网上资料很多,不再介绍。

3.3图像更新

数据传过来了,一切当然是水到渠成!!pyqtgraph的绘图方法和与pyqt结合不在此介绍,事实上,你换成matplotlib库也可以。

完整代码

import numpy as np
import pyqtgraph as pg
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QHBoxLayout, QWidget
from PyQt5.QtCore import pyqtSignal


class CtxPlotBar(QMainWindow):
    def __init__(self):
        super().__init__()
        self.plot_bar()

    def plot_bar(self, plot_data=None):
        if plot_data is None:
            plot_data = [[1, 2, 3, 4, 5, 6, 7, 8, 9]]
        self.setWindowTitle('条形图')
        view = pg.GraphicsLayoutWidget()
        self.w1 = view.addPlot()
        # 单组数据即可,x为横坐标
        x = np.arange(len(plot_data[0]))
        bar_count = 0
        for item in plot_data:
            y = []
            for value in item:
                y.append(value)
            bg = pg.BarGraphItem(x=x + bar_count, height=y, width=0.3, brush='r')
            self.w1.addItem(bg)
            bar_count += 0.33
        self.setCentralWidget(view)


class TableUi(QMainWindow):
    # 自定义信号
    plot_signal = pyqtSignal(list)

    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.initUI()

    def initUI(self):
        self.tableWidget = QTableWidget(self)
        self.tableWidget.itemSelectionChanged.connect(self.handleCellChanged)
        self.setCentralWidget(self.tableWidget)
        self.tableWidget.setRowCount(30)
        self.tableWidget.setColumnCount(6)
        self.data = [[1, 2, 3, 1, 2, 3], [4, 5, 6, 1, 2, 3], [7, 8, 9, 1, 2, 3], [1, 2, 3, 1, 2, 3], [4, 5, 6, 1, 2, 3],
                     [7, 8, 9, 1, 2, 3], [1, 2, 3, 1, 2, 3], [4, 5, 6, 1, 2, 3], [7, 8, 9, 1, 2, 3]]
        # 读取数据并显示在表格中
        for i in range(len(self.data)):
            for j in range(len(self.data[0])):
                item = QTableWidgetItem(str(self.data[i][j]))
                self.tableWidget.setItem(i, j, item)

    def handleCellChanged(self):
        row_list = []
        column_list = []
        plot_data = []
        select_area = self.tableWidget.selectedIndexes()
        #  select_area是一个鼠标选择区域,可以通过row()和column()方法获取每项的行坐标和列坐标
        for item in select_area:
            if item.row() not in row_list:
                row_list.append(item.row())
            if item.column() not in column_list:
                column_list.append(item.column())
        # 获取选中数据的索引
        # 数据组合,传递数据,colum_list决定几组数量
        for col in column_list:
            line = []
            for row in row_list:
                line.append(self.data[row][col])
            plot_data.append(line)
        self.plot_signal.emit(plot_data)  # 信号的触发


class MainUi(QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 400)
        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout()
        # 横向布局
        self.table = TableUi()
        # 连接信号
        self.table.plot_signal.connect(self.plot_data_deal)
        self.bar = CtxPlotBar()
        hbox.addWidget(self.table)
        hbox.addWidget(self.bar)
        self.setLayout(hbox)

    def plot_data_deal(self, plot_data):
        self.bar.plot_bar(plot_data)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    demo = MainUi()
    demo.show()
    sys.exit(app.exec_())

运行效果

在这里插入图片描述
在这里插入图片描述