QT学习教程(二十五)

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

#include <QtGui> 
#include <cmath> 
using namespace std; 
#include "plotter.h"

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


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 中使用的很像:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/zoomin.png</file>
<file>images/zoomout.png</file>
</qresource>
</RCC>

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

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()把图片显示到控件上。

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

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

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

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 按钮使之有效状态。

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

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

void Plotter::clearCurve(int id)
{
curveMap.remove(id); refreshPixmap();
}

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

QSize Plotter::minimumSizeHint() const
{
return QSize(6 * Margin, 4 * Margin);
}

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

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

QSize Plotter::sizeHint() const
{
return QSize(12 * Margin, 8 * Margin);
}

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/89699.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89699.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式笔记_结构型_装饰器模式

1.装饰器模式介绍装饰器模式是一种结构型设计模式&#xff0c;允许你动态地给对象添加行为&#xff0c;而无需修改其代码。它的核心思想是将对象放入一个“包装器”中&#xff0c;这个包装器提供了额外的功能&#xff0c;同时保持原有对象的接口不变。想象一下&#xff0c;你有…

day25 力扣90.子集II 力扣46.全排列 力扣47.全排列 II

子集II给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况。示例 1&…

Solidity 中的`bytes`

在 Solidity 中&#xff0c;bytes 和 bytes32 都是用来保存二进制数据的类型&#xff0c;但它们的长度、使用场景、Gas 成本完全不同。✅ 一句话区分类型一句话总结bytes32定长 32 字节&#xff0c;适合做哈希、地址、标识符等固定长度数据。bytes动态长度字节数组&#xff0c;…

初学者STM32—PWM驱动电机与舵机

一、简介 上一节课主要学习了输出比较和PWM的基本原理和结构&#xff0c;本节课就主要以实践为主通过STM32最小系统板和驱动器控制舵机和直流电机。 上一节课的坐标 初学者STM32—输出比较与PWM-CSDN博客 二、舵机 舵机是一种根据输入PWM信号占空比来控制输出角度的装置 输…

C++中的异常处理机制:try-catch

一、基本概念 异常&#xff08;Exception&#xff09;&#xff1a;程序执行过程中发生的非正常情况&#xff0c;比如除以零、访问越界、内存不足等。 异常处理&#xff08;Exception Handling&#xff09;&#xff1a;对异常情况进行捕获、分析&#xff0c;并采取补救措施&…

如何从 Windows 11 或 10 远程访问 Ubuntu 24.04 或 22.04 桌面

了解如何使用 RDP(远程桌面协议)从 Windows 11 或 10 远程连接 Ubuntu 24.04 Noble 或 22.04 LTS Jammy JellyFish 桌面的步骤。 Windows 提供了一个便捷的功能,称为远程桌面连接,它使用 RDP 协议来远程连接 PC。当从 Windows 系统建立远程桌面连接时,使用起来非常简单,…

Linux 服务器中,Tab 键自动补全功能失效

在 Linux 服务器中&#xff0c;Tab 键自动补全功能失效通常与 bash-completion 组件缺失或配置异常有关。以下是解决问题的两个关键 YUM 指令及操作步骤&#xff1a;1. 安装 bash-completion 组件 sudo yum install -y bash-completion说明&#xff1a; bash-completion 是提供…

SpringBoot服装推荐系统实战

Spring Boot 服装推荐系统实例 以下是基于Spring Boot实现的服装推荐系统的30个实例代码示例,涵盖核心功能和实现方法。 用户注册与登录功能 @RestController @RequestMapping("/api/auth") public class AuthController {@Autowiredprivate UserService userSer…

WIN10系统优化篇(一)

你是否疑惑为什么别人家的电脑运行速度飞快&#xff0c;而自己的却卡顿难用&#xff1f;其实&#xff0c;很多时候 Windows 系统可以通过简单的优化措施来提升使用体验。本文根据项目实战多年对 Win10 优化经验&#xff0c;将帮你找出系统卡顿的原因&#xff0c;并给出针对性的…

Flutter状态管理篇之ChangeNotifier基础篇(一)

目录 前言 一、什么是ChangeNotifier 二、ChangeNotifier 的基本用法 三、结合Flutter UI 使用 四、结合 Provider 的高级用法 五、ChangeNotifier 的优势与注意事项 5.1 优势 5.2 注意事项 六、与 ValueNotifier 的比较 七、实际应用场景 八、总结 前言 在 Flutter…

react17更新哪些新特性

React 17 是一个“无新特性”的发布版本&#xff0c;它的主要目标是为未来的 React 版本打好基础&#xff0c;同时改善与旧版本共存和升级的体验。虽然没有引入新的开发者 API&#xff0c;但它在内部做了很多重要的改进。以下是 React 17 的核心更新内容和特性&#xff1a;&…

Unity 常见数据结构分析与实战展示 C#

Unity 常见数据结构分析与实战展示 提示&#xff1a;内容纯个人编写&#xff0c;欢迎评论点赞&#xff0c;来指正我。 文章目录Unity 常见数据结构分析与实战展示1. 引言2. Unity 数据结构概述3. 常见数据结构1. 数组&#xff08;Array&#xff09;2. 列表&#xff08;List&…

【Linux网络编程】应用层协议 - HTTP

目录 初识HTTP协议 认识URL HTTP协议的宏观格式 Socket封装 TcpServer HttpServer 整体设计 接收请求 web根目录与默认首页 发送应答 完善页面 HTTP常见Header HTTP状态码 HTTP请求方法 cookie与session Connection 抓包 初识HTTP协议 应用层协议一定是基于…

技术演进中的开发沉思-36 MFC系列: 对话框

MFC这个章节里&#xff0c;不能忽视的是对话框的开发。如果把 MFC 程序比作一栋办公楼&#xff0c;那对话框就是「会客室」—— 它是程序与用户面对面交流的地方&#xff1a;用户在这里输入数据&#xff0c;程序在这里展示信息&#xff0c;彼此的互动都从这个空间开始。今天围绕…

(李宏毅)deep learning(五)--learning rate

一&#xff0c;关于learning rate的讨论&#xff1a;&#xff08;1&#xff09;在梯度下降的过程中&#xff0c;当我们发现loss的值很小的时候&#xff0c;这时我们可能以为gradident已经到了local min0&#xff08;低谷&#xff09;,但是很多时候&#xff0c;loss很小并不是因…

pytorch:tensorboard和transforms学习

tensorboard:可视化数据 在anaconda安装&#xff1a; pip install tensorboard2.12.0最好使用这个版本 不然后面调用会报错 因为版本过高的原因 然后还碰到了安装的时候 安装到C盘去了 但是我用的虚拟环境是在E盘&#xff1a;此时去C盘把那些新安装的复制过来就好了 附录我C盘的…

常用的100个opencv函数

以下是OpenCV中最常用的100个函数及其作用与注意事项的全面整理&#xff0c;按功能模块分类&#xff0c;结合官方文档与工业实践优化排序。各函数均标注Python&#xff08;cv2&#xff09;和C&#xff08;cv::&#xff09;命名&#xff0c;重点参数以加粗突出&#xff1a; &…

【C++】红黑树,详解其规则与插入操作

各位大佬好&#xff0c;我是落羽&#xff01;一个坚持不断学习进步的大学生。 如果您觉得我的文章有所帮助&#xff0c;欢迎多多互三分享交流&#xff0c;一起学习进步&#xff01; 也欢迎关注我的blog主页: 落羽的落羽 一、红黑树的概念与规则 红黑树是一种更加特殊的平衡二…

Camera相机人脸识别系列专题分析之十七:人脸特征检测FFD算法之libhci_face_camera_api.so 296点位人脸识别检测流程详解

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: Camera相机人脸识别系列专题分析之十七:人脸特征检测FFD算法之libhci_face_camera_api.so 296点位人脸识别检测流程详解 目录 一、背景 二、:FFD算法libhci_face_camera_api.s…

PostgreSQL 16 Administration Cookbook 读书笔记:第7章 Database Administration

编写一个要么完全成功要么完全失败的脚本 事务&#xff08;transaction&#xff09;可以实现all or nothing。不过这里指的是psql的-和--single-transaction选项。可以实现transaction wrapper&#xff1a; 此选项只能与一个或多个 -c 和/或 -f 选项组合使用。它会导致 psql 在…