QT学习教程(二十五)

双缓冲技术(Double Buffering )( 2 、公有函数实现)

cpp 复制代码
#include <QtGui> 
#include <cmath> 
using namespace std; 
#include "plotter.h"

以上代码为文件的开头,在这里把std 的名空间加入到当前的全局命名空间。这样在使用<cmath>里的函数时,就不用前缀 std::了,如可以直接使用函数 floor(),而不用写成 std::floor()。

cpp 复制代码
Plotter::Plotter(QWidget *parent) : QWidget(parent)
{
setBackgroundRole(QPalette::Dark); setAutoFillBackground(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setFocusPolicy(Qt::StrongFocus);
rubberBandIsShown = false;

zoomInButton = new QToolButton(this);
zoomInButton->setIcon(QIcon(":/images/zoomin.png")); zoomInButton->adjustSize();
connect(zoomInButton, SIGNAL(clicked()), this, SLOT(zoomIn()));

zoomOutButton = new QToolButton(this);
zoomOutButton->setIcon(QIcon(":/images/zoomout.png")); zoomOutButton->adjustSize();
connect(zoomOutButton, SIGNAL(clicked()), this, SLOT(zoomOut()));

setPlotSettings(PlotSettings());
}
 

在构造函数中,调用setBackGroundRole(QPalette::Dark),当对控件进行放大需要重新绘制时,提供给Qt 一个缺省的颜色填充新的区域,为了能够使用这个机制,还调用了 setAutoFillBackground(true)。函数setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)让控件在水平和垂直两个方向上都可以进行伸缩。如果控件需要占据屏幕上很大的控件,经常设置这个属性。缺省的设置是两个方向都是 QSizePolicy::Preferred,意思是控件的实际尺寸和它的 sizeHint一致,控件最小只能缩小到它的最小的 sizeHint,并能够无限放大。

调用setFocusPolicy(Qt::StrongFocus)可以使控件通过鼠标点击或者Tab 得到焦点。当 Plotter 控件得到焦点时,它可以接受键盘敲击事件。Plotter 控件能够理解一些键盘事件,如+放大,-为缩小,可以向上下左右平移。

在构造函数中,我们还创建了两个QToolButton,每一个按钮都有一个图标。点击这些图标可以放大或者缩小显示的图像。图标保存在资源文件中,为了任何程序都可以使用 Plotter 控件,需要在.pro 添加资源条目:

RESOURCES = plotter.qrc

资源文件是一个XML 格式的文本文件,和在Spreadsheet 中使用的很像:

cpp 复制代码
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/zoomin.png</file>
<file>images/zoomout.png</file>
</qresource>
</RCC>

调用QToolButton::adjustSize()调整按钮的大小为它们的sizeHint。在这里按钮不在布局中 ,在控件大小改变的时候,又程序计算它们的位置。由于没有了布局管理,因为我们必须在按钮的构造函数中确定按钮的父控件。调用setPlotSettings()函数用来完成控件的初始化。函数代码如下:

cpp 复制代码
void Plotter::setPlotSettings(const PlotSettings &settings)
{
zoomStack.clear(); zoomStack.append(settings); curZoom = 0;
zoomInButton->hide(); zoomOutButton->hide();
 
refreshPixmap();
}

函数setPlotSettings()确定显示控件时的PlotSettings。它在Plotter 构造函数中调用,也可以被Plotter 的用户调用。开始的时候,Plotter 使用的是缺省的放缩值。用户进行放大一次,就有一个新的PlotSettings 对象加入到堆栈中。这个堆栈中有两个变量:

zoomStack 是保存PlotSettings 对象的一个数组;

curZoom 是当前使用的 PlotSettings 的一个索引值。

调用setPlotSettings()后,zoomStack 中只有一项,zoomIn 和zoomOut 按钮隐藏。如果我们调用函数zoomIn()和zoomOut(),这两个函数中调用了按钮的show()函数,它们才能显示出来。(通常,调用父控件的 show()函数就显示所有的子控件。但是如果我们显式调用了子控件的hide(),必须要显示调用其show()函数显示它,否则就会一直隐藏)

调用refreshPixmap()来更新显示。通常,我们调用 update()就可以,这里有些不一样,因为我们要保持QPixmap 一直最新的状态。更新了图片后,refreshPixmap()再调用update()把图片显示到控件上。

cpp 复制代码
void Plotter::zoomOut()
{
if (curZoom > 0) {
--curZoom;
zoomOutButton->setEnabled(curZoom > 0); zoomInButton->setEnabled(true); zoomInButton->show();
refreshPixmap();
}
}

如果图片放大了,调用 zoomOut()缩小它。它缩小比例系数,如果还能进一步缩小,zoomOut

按钮一直有效。显示zoomIn 按钮使之按钮有效,调用refreshPixmap()刷新控件。

cpp 复制代码
void Plotter::zoomIn()
{
if (curZoom < zoomStack.count() - 1) {
++curZoom;
zoomInButton->setEnabled(curZoom < zoomStack.count() - 1); zoomOutButton->setEnabled(true);
zoomOutButton->show(); refreshPixmap();
}
}

如果用户放大后又缩小控件,下一个放缩系数的 PlotSettings 就进入zoomStack。我们就可以再放大控件。函数zoomIn 增加放缩系数,zoomIn 按钮显示出来,只要能够放大,按钮会一直有效。同事显示zoomOut 按钮使之有效状态。

cpp 复制代码
void Plotter::setCurveData(int id, const QVector<QPointF> &data)
{
curveMap[id] = data; refreshPixmap();
 
}

函数setCurveData()设置一个指定id 的曲线数据。如果曲线中有一个同样的 id,那么就用新的数据替代旧数据。如果没有指定的id,则增加一个新的曲线。曲线的数据类型为QMap<int, QVector<QPointF> >

cpp 复制代码
void Plotter::clearCurve(int id)
{
curveMap.remove(id); refreshPixmap();
}

函数clearCurve()删除一个指定id 的曲线。

cpp 复制代码
QSize Plotter::minimumSizeHint() const
{
return QSize(6 * Margin, 4 * Margin);
}

函数minimumSizeHint()和sizeHint()很像,确定控件的理想的尺寸。minimumSizeHint()

确定控件的最大尺寸。布局管理器排列控件时不会超过控件的最大尺寸。由于Margin 值为 50,所以我们返回的值为 300×200,包括四个边界的宽度和 Plot 本身。如果再小,尺寸太小Plot 就不能正常显示了。

cpp 复制代码
QSize Plotter::sizeHint() const
{
return QSize(12 * Margin, 8 * Margin);
}

在sizeHint()中,我们返回控件的理想尺寸,用 Margin 常数作为倍数,长宽的比例为 3:2,与minimumSizeHint()中比例一致。

以上是Plotter 的公有函数和槽函数。

相关推荐
Felix_One3 天前
Qt 串口通信避坑指南:QSerialPort 的 5 个常见问题
qt
blasit6 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
西岸行者11 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意11 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码11 天前
嵌入式学习路线
学习
毛小茛11 天前
计算机系统概论——校验码
学习
babe小鑫11 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
范特西.i11 天前
QT聊天项目(8)
开发语言·qt
winfreedoms11 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下11 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs