表格类
在qt中,绘制表格可能有很多种方法,但是我这次使用到的是类 QTableWidget
我们在做整体项目的时候,最好将每个控件或者功能都细化,最好可以用一个类完成这个功能或者表示出这个控件。因此我自己写了类继承 QTableWidget 来绘制我需要的表格。有些人会说为啥不直接使用这个现成的类,方便简洁。直接使用确实方便,但是我们这个表格可能不单单只是绘制出表格,还可能会和其他的类,功能会有交互,那么我们自己定义的类就可以在上面添加我们需要的方法,qt中尤其是信号和槽。
1、初始化表格
我们绘制一个表格,最先是绘制窗体,然后才会绘制里面的数据。在这里我只用了几个基础设定,如果大家希望更清晰的设定可以查看qt官方帮助文档。
//设置表格内容不能修改
this->setEditTriggers(QAbstractItemView::NoEditTriggers);
// 设置选中背景色
this->setStyleSheet("selection-background-color:blue;");
// 整行选中的方式
this->setSelectionBehavior(QAbstractItemView::SelectRows);
// 显示格子线
this->setShowGrid(true);
2、初始化表头
表格基础设定好了以后,我们则需要设置好表头
// 设置表头字体加粗
QFont font = QFont();
font.setBold(true);
this->horizontalHeader()->setFont(font);
this->horizontalHeader()->setFont(font);
// 获取表头各列参数
QString Headers = MeasureResult::getHeaders();
// 截取字符串
QStringList headers = Headers.split(",");
// 设置表列数
this->setColumnCount(headers.count());
// 将各列参数加入表头中
this->setHorizontalHeaderLabels(headers);
// 自定义列宽
for (int i = 0 ; i < headers.count() ; i++)
{
this->setColumnWidth(i, 160);
}
3、添加数据
前面的表格大体框架已经设定好,那么我们接下来就可以添加数据了。
在这里需要一提的是 QTableWidgetItem 这个类,它是相当于 QTableWidget 中的一个一个模块,也就是表格中的一个个格子,我们添加数据也是通过添加这一个一个格子来进行的。
在这里,我的一个功能是对表格中的数据进行一个区间判断,不同的区间背景显示不同的颜色。这个区间判断的意义就是这个数据在一定范围内才是正常的,如果超过了这个范围,那么数据就是不正常的,所有不同的背景色可以更好的查看这个结果。
// 获取当前的行数
int rowCount = this->rowCount();
// 如果数量达到了200,那么清空,重新绘制
if (rowCount > 199)
{
clearAllData();
rowCount = 0;
}
// 行数从0开始,所有添加新行正好是当前行数最为新行数的索引
this->insertRow(rowCount);
// 获取所有测量数据
QString VALUES = measureResult->getValues();
QStringList values = VALUES.split(",");
// 判断数据应该是什么颜色,
QColor color = getColorByResult(measureResult);
// 将数据添加进表格中
for (int i = 0; i < values.count(); i++)
{
// 添加数据,添加数据的放是就是添加一个一个 QTableWidgetItem
this->setItem(rowCount, i, new QTableWidgetItem(values[i]));
// 设置每个格子的背景色
this->item(rowCount, i)->setBackgroundColor(color);
}
// 将数据添加近集合中,我需要将这个新建的数据保存起来,以便后续的功能使用
measureResults.push_back(measureResult);
有了这三步就可以将一个表格绘制出来了,让我们来看看绘制的结果。
但是单单绘制出来一个表格还不能满足我们的要求,还需要右键点击之后对表格进行数据行删除和单行删除。而这里说到右键点击,大家应该就会想到事件了。
4、右键点击事件
功能: 鼠标右击后,可以出现一个菜单栏,其中存在 删除单条数据和删除多条数据 两个选项
右键出现一个菜单选项,这个事件在 QWidget 下就存在,可以直接重写该方法即可。
[virtual protected] void QWidget::contextMenuEvent(QContextMenuEvent *event)
我的功能中,右击后需要存在两个菜单栏,但是并不是一定会出现,接下来仔细分析两个菜单选项功能。
1、 删除全部数据
- 将表格中的数据全部删除,前面提到存储所有数据的 measureResults 集合也清空,然后表格行数重置为0。
2、删除单条数据
- 在这里需要加一个判断,整个表格 widget中,任何位置右击都可以出现删除全部数据,但是删除单条数据显示的条件必须是鼠标要在 一行数据上,否则出现了这个选项都不知道删除哪行数据。
明确了功能,那么接下来就只需要代码实现即可:
void MzTableWidget::contextMenuEvent(QContextMenuEvent *event)
{
// 获取鼠标右击坐标点
QPoint point = event->pos();
// 获取鼠标坐标点对应的 item
QTableWidgetItem *item = this->itemAt(point);
// 右键显示菜单
QMenu *menu = new QMenu(this);
// 判断右击点是否在表格内,在表格内才新建清除改行
// 先判断鼠标右击的位置有没有 item,如果没有那么就不创建删除单条数据的相关事件和对象,节省空间
if (item != nullptr)
{
// 清楚一行数据 action
QAction *actionOne = new QAction("清除该行数据", this);
menu->addAction(actionOne);
// 点击删除一条数据,发送信号
// 这里可能有人会问? 这个连接直接触发对应的槽函数即可,为什么要自己写一个信号,然后再转一次。
//如果这里只做这一个功能的话。这里确实可以直接触发对应的槽函数,
// 但是这么写是为了后续的一个功能实现。我们后面会说到,请先看完。
connect(actionOne, &QAction::triggered, [=]() {
emit singalClearOneData(item->row());
});
// 删除数据信号槽关联
// Qt::UniqueConnection 只建立一次连接,因为如果不限制每次生成菜单就会建立一次连接,导致会发送一次信号,而执行多次槽函数
connect(this, &MzTableWidget::singalClearOneData, this, &MzTableWidget::clearOneData,Qt::UniqueConnection);
}
// 清楚所有数据
QAction *actionAll = new QAction("清除所有数据", this);
// 将action加入到菜单
menu->addAction(actionAll);
// 菜单显示在鼠标右击处
menu->move(QCursor::pos());
menu->show();
// 连接清除所有数据事件
connect(actionAll, &QAction::triggered, [=]() {
emit signalClearAll();
});
// 连接删除所有数据的信号和槽
connect(this, &MzTableWidget::signalClearAll, this, &MzTableWidget::clearAllData,Qt::UniqueConnection);
}
删除所有数据的方法:
// 清空数据
void MzTableWidget::clearAllData()
{
// 清空数据
this->clearContents();
// 将行数重新设为0
this->setRowCount(0);
// 将集合中的数据全部删除
measureResults.clear();
}
删除单个数据的方法
// 清空单个数据
void MzTableWidget::clearOneData(const int index)
{
// 删除这行数据
measureResults.removeAt(index);
// 清空数据
this->clearContents();
// 将行数重新设为0
this->setRowCount(0);
// 重新绘制表格
reDrawWidget();
}
重新绘制表格
// 重新绘制表格
void MzTableWidget::reDrawWidget()
{
MeasureResult *measureResult = nullptr;
for (int i = 0 ; i < measureResults.size() ; i++)
{
// 行数从0开始,所有添加新行正好是当前行数最为新行数的索引
this->insertRow(i);
// 获取所有测量数据
measureResult = measureResults[i];
QString VALUES = measureResult->getValues();
QStringList values = VALUES.split(",");
// 判断数据应该是什么颜色,
QColor color = getColorByResult(measureResult);
// 将数据添加进表格中
for (int j = 0; j < values.count(); j++)
{
this->setItem(i, j, new QTableWidgetItem(values[j]));
this->item(i, j)->setBackgroundColor(color);
}
}
}
// 判断数据是什么颜色
QColor MzTableWidget::getColorByResult(MeasureResult *measureResult)
{
QColor color = Qt::red;
if (measureResult != nullptr)
{
if (measureResult->getMeasureValue() < measureResult->getUpMonitLimit()
&& measureResult->getMeasureValue() > measureResult->getLowerMonitLimit())
{ // 正常范围
color = Qt::green;
}
else if (measureResult->getMeasureValue() >= measureResult->getUpMonitLimit()
&& measureResult->getMeasureValue() < measureResult->getUpErrorLimit()
|| measureResult->getMeasureValue() <= measureResult->getLowerMonitLimit()
&& measureResult->getMeasureValue() > measureResult->getLowerErrorLimit())
{ // 警告范围
color = Qt::yellow;
}
else // 错误范围
{
color = Qt::red;
}
}
return color;
}
以上,绘制表格就大功告成了。接下来我们看看如何绘制折线图。
折线图
折线图也是表示数据的一种好方法,在Qt中也有很多方式可以绘制,在这里我选用的类是 QChartView ,其中值得一提的还有类 QChart
QChartView Class
The QChartView is a standalone widget that can display charts
// 显示图标的标准小部件
QChart Class
The QChart class manages the graphical representation of the chart's series, legends, and axes. More...
//QChart类管理图表的序列、图例和轴的图形表示
一个是显示的小部件,一个是管理图形的,两者合作即可实现我们的功能,其中 QChartView 中有一个方法也可以说明这个问题。
// 直接获取QChart 对象,我们后续对 X,Y轴,数据线条等都是通过这个对象来进行操作的
QChart * chart() const
在这里还值得一说的是使用 QChart等相关类,需要几个准备工作:
1、安装qt是选用了 charts 模块
2、项目名右键–>属性–> Qt Project Settings --> Qt Modules --> 添加 charts 模块
3、引用头文件
#include <QChartView>
// 这一步不能忘记,否则就在前面自己加命名空间
using namespace QtCharts;
准备工作做好之后我们开始绘制图像,也分三部,初始化(绘制框架),添加数据绘制出来,其他功能实现
初始化折线图
相信大家都知道,折线图中,有X,Y轴形成一个坐标系,还有坐标系上面的线条,这里就又需要引入其他几个类
1、线条类,表现数据的,如果不是折线图是其他的线条,也有其他对应的类,大家可以自行查找。
QLineSeries Class
// 以折线图的形式显示数据
The QLineSeries class presents data in line charts.
2、离散点类
这个类就是在坐标系上面显示各个点,各个点并不相连。在这里我使用它的目的是为了可以鼠标移动到每个数据点的时候可以显示出这个坐标点的数据。
QScatterSeries Class
// QScatterSeries类以散点图的形式表示数据。
The QScatterSeries class presents data in scatter charts.
3、X,Y轴类
QValueAxis Class
// 将值添加到图表的轴上
The QValueAxis class adds values to a chart's axes.
这些类大家熟悉后,就可以开始初始化图形了,我们来看代码。
// 初始化折线图
void MzChartView::initChartView()
{
//数据条
seriesx = new QLineSeries();
// 绘制线条颜色
seriesx->setPen(QPen(QColor(Qt::green)));
// 设置转折点明显
seriesx->setPointsVisible(true);
seriesx->setName("测量数据");
// 离散点,显示转折点
seriesxPoint = new QScatterSeries();
// 设置圆形的点
seriesxPoint->setMarkerShape(QScatterSeries::MarkerShapeCircle);
// 设置离散点大小
seriesxPoint->setMarkerSize(5);
// 设置离散点边框颜色
seriesxPoint->setBorderColor(QColor(Qt::green));
// 设置离散点背景色
seriesxPoint->setBrush(QColor(Qt::green));
seriesxPoint->setName("转折点");
// 初始化点信息显示label ,这个label就是为了当鼠标移动到转折点十显示该点数据的
label = new QLabel(this);
// 设置label背景色
label->setStyleSheet("QLabel{background-color:rgb(87,250,255);}");
// 先将label隐藏
label->hide();
// 这些监控线也是和前面表格设置背景色一样,对数据进行一个直观的显示。
// 上监控线
seriesxUpMon = new QLineSeries();
seriesxUpMon->setName("监控上限");
seriesxUpMon->setPen(QPen(QColor(Qt::yellow)));
// 下监控线
seriesxLowMon = new QLineSeries();
seriesxLowMon->setName("监控下限");
seriesxLowMon->setPen(QPen(QColor(Qt::yellow)));
// 上警戒线
seriesxUpErr = new QLineSeries();
seriesxUpErr->setName("上警戒线");
seriesxUpErr->setPen(QPen(QColor(Qt::red)));
// 上警戒线
seriesxLowErr = new QLineSeries();
seriesxLowErr->setName("下警戒线");
seriesxLowErr->setPen(QPen(QColor(Qt::red)));
// X轴 Y 轴
axisx = new QValueAxis();
axisy = new QValueAxis();
// 设置X,Y轴名称
axisx->setTitleText("id");
axisy->setTitleText("length(um)");
// 基础配置
// 动画,使得曲线绘制的更平滑
this->chart()->setAnimationOptions(QChart::SeriesAnimations);
// 抗锯齿
this->setRenderHint(QPainter::Antialiasing);
// 设置主题
this->chart()->setTheme(QChart::ChartThemeDark);
// 设置图名
this->chart()->setTitle("曲线图");
// 线条加入图表中
this->chart()->addSeries(seriesx);
this->chart()->addSeries(seriesxUpMon);
this->chart()->addSeries(seriesxUpErr);
this->chart()->addSeries(seriesxLowMon);
this->chart()->addSeries(seriesxLowErr);
this->chart()->addSeries(seriesxPoint);
// X,Y轴加入图表中
this->chart()->addAxis(axisx, Qt::AlignBottom);
this->chart()->addAxis(axisy, Qt::AlignLeft);
// 数据线和X,Y轴关联,如果不关联则无法进行数据绘制
seriesx->attachAxis(axisx);
seriesx->attachAxis(axisy);
seriesxUpMon->attachAxis(axisx);
seriesxUpMon->attachAxis(axisy);
seriesxUpErr->attachAxis(axisx);
seriesxUpErr->attachAxis(axisy);
seriesxLowMon->attachAxis(axisx);
seriesxLowMon->attachAxis(axisy);
seriesxLowErr->attachAxis(axisx);
seriesxLowErr->attachAxis(axisy);
seriesxPoint->attachAxis(axisx);
seriesxPoint->attachAxis(axisy);
// 设置鼠标跟踪
this->setMouseTracking(true);
// 后面这两个关联事件我后续会说到,大家先往下看。
// 关联离散点显示坐标事件,
connect(seriesxPoint, &QScatterSeries::hovered, this, &MzChartView::slotPointHovered);
// 关联离散点点击时显示删除节点信息
connect(seriesxPoint, &QScatterSeries::clicked, this, &MzChartView::slotPointClicked);
}
上面的代码就是对这些工具类的一些属性设定,还有其他的设定大家可以查看文档,自行学习。
添加数据,绘制图形
初始化结束之后,图形的大体框架就已经有了 ,那么接下来就是添加数据,绘制图形了。
// 绘制绘制曲线图
void MzChartView::drawChartView(MeasureResult *measureResult)
{
// 定义X,Y轴的最大最小值
// X轴最开始默认10,后续添加数据后以数据数量为准
axisx->setMin(0);
axisx->setMax(10);
axisy->setMin(measureResult->getLowerErrorLimit() * 0.9 );
axisy->setMax(measureResult->getUpErrorLimit() * 1.1 );
//当前点的数量
int count = seriesx->points().size();
if (count > 10)
{
// 最开始默认X轴最大10,超过后则以当前的数量作为X州的最大范围
this->chart()->axisX()->setMax(count);
}
if (count > 199) // 达到两百,数据清除,防止数据太多,显示不好看
{
// 清空方法,后续会说到
clearAllData();
count = 0;
}
// 数据添加到集合,存储数据的集合,为了后续删除单个节点做准备
measureResults.push_back(measureResult);
// 每条线添加点
seriesx->append(QPointF(count, measureResult->getMeasureValue()));
seriesxPoint->append(QPointF(count, measureResult->getMeasureValue()));
seriesxUpMon->append(QPointF(count, measureResult->getUpMonitLimit()));
seriesxUpErr->append(QPointF(count, measureResult->getUpErrorLimit()));
seriesxLowMon->append(QPointF(count, measureResult->getLowerMonitLimit()));
seriesxLowErr->append(QPointF(count, measureResult->getLowerErrorLimit()));
}
有了这两步,我们的折线图就可以出现了。
其中这个绿线上的转折点就是离散类的点。
其他功能
绘制好了图形之后,我们还需要做几个小功能。
1、鼠标移动到转折点时显示数据
2、 鼠标点击离散点(转折点) 出现菜单栏
3、右键图形页面出现删除所有节点的菜单栏
明确了目标,接下来就开始实行即可。
鼠标移动到转折点时显示数据
在这里不知道大家是否还记得初始化的时候那两个 connect() 连接
// 关联离散点显示坐标事件,这个信号,槽连接就是实现这个功能的
connect(seriesxPoint, &QScatterSeries::hovered, this, &MzChartView::slotPointHovered);
我们先分析一下 QScatterSeries 中是否有自带的信号函数已供我们使用,明显是有的。
// 它的继承类 QXYSeries则有这个功能。
class Q_CHARTS_EXPORT QScatterSeries : public QXYSeries
[signal] void QXYSeries::hovered(const QPointF &point, bool state)
// 当鼠标悬停在图表中的某个点上时,就会发出这个信号。当鼠标移动到该点上时,状态变为真,当鼠标再次移动时,状态变为假。
This signal is emitted when a mouse is hovered over the point point in the chart. When the mouse moves over the point, state turns true, and when the mouse moves away again, it turns false.
有了这个现成的信号函数,我们则只需要写好槽函数即可
// 鼠标移到点位置,显示点数据的槽函数
void MzChartView::slotPointHovered(const QPointF &point, bool state)
{
// 表示在当前点上
if (state)
{
// 获取当前点位
QPoint curPoint = mapFromGlobal(QCursor::pos());
// 设置坐标数据的位置,这个点位的设定是我手动设置的,具体窗口,图形,等坐标我暂时还没有完全弄懂,等后续再研究
label->move(curPoint.x() + this->pos().x() - 125 , curPoint.y() + this->pos().y() - 125);
// 显示坐标点结果
label->setText(tr("(%1,%2)").arg(point.x() + 1).arg(point.y()));
// 设置label大小
label->resize(50, 20);
label->show();
}
else // 表示指针不在点位
{
label->hide();
}
}
实现了这个槽函数,第一个功能即完成了。
鼠标点击时,显示菜单
这个功能我相信大家都知道,左键点击,clicked 信号,大家都很熟悉,我就不再给大家查找文档。
// 这个也是初始化时我说后续说到的问题,它的功能就是实现点击显示菜单的的
// 关联离散点点击时显示删除节点信息
connect(seriesxPoint, &QScatterSeries::clicked, this, &MzChartView::slotPointClicked);
同理,有了现成的信号函数我们直接实现对应的槽函数即可。
// 鼠标点击点时,显示菜单
void MzChartView::slotPointClicked(const QPointF &point)
{
// 创建菜单
QMenu *menu = new QMenu(this);
// 删除单个节点
QAction *actionOne = new QAction("删除该节点",this);
// 删除全部节点
QAction *actionAll = new QAction("删除全部节点",this);
menu->addAction(actionOne);
menu->addAction(actionAll);
menu->move(QCursor::pos());
menu->show();
// 这里关联的两个事件都是点击后再发送我的信号,再转发到槽函数,和上面的表格一样,我这里不看似也是多次一举,但是这样子的实现可以
// 让代码更加健壮,更好的和其他功能复用
// 连接删除全部节点事件
connect(actionAll, &QAction::triggered, [=]() {
emit signalClearAll();
});
// 连接删除单个节点事件
connect(actionOne, &QAction::triggered, [=]() {
emit signalClearOne(point.x());
});
// 连接删除单个节点的信号和槽
// Qt::UniqueConnection 只建立一次连接,因为如果不限制每次生成菜单就会建立一次连接,导致会发送一次信号,而执行多次槽函数
connect(this, &MzChartView::signalClearOne, this, &MzChartView::clearOneData,Qt::UniqueConnection);
// 关联删除所有数据的方法
connect(this, &MzChartView::signalClearAll, this, &MzChartView::clearAllData, Qt::UniqueConnection);
}
删除单个节点和全部节点的方法如下:
// 清除单个数据
void MzChartView::clearOneData(const int index)
{
// 删除这个点的数据
measureResults.removeAt(index);
// 线条点清除
seriesx->clear();
seriesxLowErr->clear();
seriesxLowMon->clear();
seriesxUpErr->clear();
seriesxUpMon->clear();
seriesxPoint->clear();
axisx->setMax(10);
// 重新绘制图像
// 这个方法则是在集合中将那个需要删除的节点删除,然后根据集合重新绘制这个图形
reDrawChartView();
}
// 清空所有数据
void MzChartView::clearAllData()
{
// 数据清除
measureResults.clear();
// 线条点清除
seriesx->clear();
seriesxLowErr->clear();
seriesxLowMon->clear();
seriesxUpErr->clear();
seriesxUpMon->clear();
seriesxPoint->clear();
axisx->setMax(10);
}
重新绘制方法和新建绘制方法类似
// 重新绘制折线图
void MzChartView::reDrawChartView()
{
MeasureResult *measureResult = nullptr;
// 循环剩余的数据进行绘制
for (int i = 0 ; i < measureResults.size() ; i++ )
{
measureResult = measureResults[i];
if (i > 10)
{
this->chart()->axisX()->setMax(i);
}
// 每条线添加点
seriesx->append(QPointF(i, measureResult->getMeasureValue()));
seriesxPoint->append(QPointF(i, measureResult->getMeasureValue()));
seriesxUpMon->append(QPointF(i, measureResult->getUpMonitLimit()));
seriesxUpErr->append(QPointF(i, measureResult->getUpErrorLimit()));
seriesxLowMon->append(QPointF(i, measureResult->getLowerMonitLimit()));
seriesxLowErr->append(QPointF(i, measureResult->getLowerErrorLimit()));
}
}
至此,第二个功能就已经实现了。
右键删除所有节点
这个功能则和表格的功能实现一样,只需要实现 contextMenuEvent(QContextMenuEvent *event) 这个事件即可。相信大家都会了,代码如下:
// 右键点击事件
void MzChartView::contextMenuEvent(QContextMenuEvent *event)
{
// 创建菜单
QMenu *menu = new QMenu(this);
// 删除全部节点
QAction *actionAll = new QAction("删除全部节点", this);
menu->addAction(actionAll);
menu->move(QCursor::pos());
menu->show();
// 关联删除所有数据的方法
connect(this, &MzChartView::signalClearAll, this, &MzChartView::clearAllData,Qt::UniqueConnection);
// 连接删除全部节点事件
connect(actionAll, &QAction::triggered, [=]() {
// 清除线条
emit signalClearAll();
});
}
到此,折线图绘制和功能实现都已经完成。
测试和两者数据同步
这两个类写完之后,我们接下来要做的就是测试了。
定义一个测试类,继承几个窗口类中的一个,将我们的两个图绘制出来。我们将两个类都封装了一层,现在只需要创建两个类的对象,然后调用它们对应的方法即可。
先查看代码
drawGraph::drawGraph(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
this->resize(1200, 900);
// 创建表格
MzTableWidget *tableWidget = new MzTableWidget(this);
// 定义表格的位置
tableWidget->move(100, 550);
tableWidget->resize(1000, 300);
// 创建折线图
MzChartView *chartView = new MzChartView(this);
// 定义位置
chartView->move(100, 100);
chartView->resize(1000, 400);
// 定义添加按钮,用于测试
QPushButton *btn = new QPushButton(this);
btn->setText("添加数据");
btn->move(1000, 50);
// 添加数据测试关联事件
connect(btn, &QPushButton::clicked, [=]() {
MeasureResult *measureResult = new MeasureResult();
measureResult->setUpErrorLimit(95);
measureResult->setUpMonitLimit(93);
measureResult->setLowerMonitLimit(87);
measureResult->setLowerErrorLimit(85);
// 生成随机数,这里我自己设定了结果的上下限和随机生成结果,用于测试
QTime time = QTime::currentTime();
qsrand(time.msec() + time.second()*1000);
int n = qrand() % 10 + 85;
measureResult->setMeasureValue(n);
// 绘制表格
tableWidget->insertValue(measureResult);
// 绘制曲线图
chartView->drawChartView(measureResult);
});
// 添加清空按钮,用于测试
QPushButton *btn1 = new QPushButton(this);
btn1->setText("清空数据");
btn1->move(800, 50);
connect(btn1, &QPushButton::clicked, [=]() {
// 表格数据清空
tableWidget->clearAllData();
// 曲线图清空
chartView->clearAllData();
});
// 这下面的这个四个关联功能就是我之前在两个类中实现删除单个节点和所有节点时还特意自已实现信号函数的原因,
// 我想要实现的结果就是表格或者曲线图删除了节点,那么相连的图形也同步删除。
// 这样就可以实现同一个窗口下,不同的控件之间实现功能传递。
// 关联折线图和表格删除一条信息的信号,槽函数,达到两者同步
connect(chartView, &MzChartView::signalClearOne, tableWidget, &MzTableWidget::clearOneData);
connect(tableWidget, &MzTableWidget::singalClearOneData, chartView, &MzChartView::clearOneData);
// 关联折线图和表格删除所有信息的信号,槽函数,达到两者同步
connect(chartView, &MzChartView::signalClearAll, tableWidget, &MzTableWidget::clearAllData);
connect(tableWidget, &MzTableWidget::signalClearAll, chartView, &MzChartView::clearAllData);
}
至此,所有的功能已经完毕,该文章也已接近尾部,感谢大家观看。
你知道的越多,不知道的越多。我们下期再见。