使用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_())
运行效果