QT:通过按钮调用qpaintEvent事件实现自定义绘图

2023-11-15

摘要

最近碰到了一个需要在qt中完成二维图像变换的作业,想到刚接触qt时学过qpainter来进行绘画操作,立马就着手码起来;作为一个小白,马上就发现了相应的问题:由于qt内部机制,绘画事件(paintEvent)仅允许在绘画事件下进行(比如我想在某个按钮槽函数下绘画是错误的。查阅了论坛上大部分文章发现很少涉及这样的操作,并且涉及到的操作对于我这种小白来说也是比较难的。

在一晚上的思考下,突然想起可以通过枚举来解决这问题,下面要介绍的就是通过枚举来实现自定义操作“画家的笔”。

代码

widget.h

#include <QWidget>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void paintEvent(QPaintEvent *event);



signals:
    void senddata();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
};

头文件声明绘图事件,之后再重写

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QMessageBox>

double X1,Y1,X2,Y2,X3,Y3;

enum func
{
  ok,
  pingyi1,
  pingyi2,
  pingyi3,
  pingyi4,
  xuanzhuan,
  duicheng,
  fangsuo,

}func1;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("图形变换");
    resize(800,600);

    //确定
    connect(ui->pushButton,&QPushButton::clicked,this,[=](){
        X1=ui->lineEdit->text().toDouble();
        Y1=ui->lineEdit_2->text().toDouble();
        X2=ui->lineEdit_3->text().toDouble();
        Y2=ui->lineEdit_4->text().toDouble();
        X3=ui->lineEdit_5->text().toDouble();
        Y3=ui->lineEdit_6->text().toDouble();

        if(ui->lineEdit->text().isEmpty()||ui->lineEdit_2->text().isEmpty()||ui->lineEdit_3->text().isEmpty()||ui->lineEdit_4->text().isEmpty()||
               ui->lineEdit_5->text().isEmpty()||ui->lineEdit_6->text().isEmpty())
        {
            QMessageBox::warning(this,"注意!","请输入正确的数据");
        }
        else
        {
            func1 = ok;
            update();
        }

    });

    //上移
    connect(ui->pushButton_2,&QPushButton::clicked,this,[=](){
        func1=pingyi1;
        Y1=Y1+20;
        Y2=Y2+20;
        Y3=Y3+20;
        update();
    });

    //下移
    connect(ui->pushButton_6,&QPushButton::clicked,this,[=](){
        func1=pingyi2;
        Y1=Y1-20;
        Y2=Y2-20;
        Y3=Y3-20;
        update();
    });
    //左移
    connect(ui->pushButton_7,&QPushButton::clicked,this,[=](){
        func1=pingyi3;
        X1=X1-20;
        X2=X2-20;
        X3=X3-20;
        update();
    });
    //右移
    connect(ui->pushButton_8,&QPushButton::clicked,this,[=](){
        func1=pingyi4;
        X1=X1+20;
        X2=X2+20;
        X3=X3+20;
        update();
    });

    //旋转
    connect(ui->pushButton_3,&QPushButton::clicked,this,[=](){
        func1=xuanzhuan;
        double temp1,temp2,temp3;

        temp1=X1*cos(0.523)-Y1*sin(0.523);
        Y1=X1*sin(0.523)+Y1*cos(0.523);
        X1=temp1;

        temp2=X2*cos(0.523)-Y2*sin(0.523);
        Y2=X2*sin(0.523)+Y2*cos(0.523);
        X2=temp2;

        temp3=X3*cos(0.523)-Y3*sin(0.523);
        Y3=X3*sin(0.523)+Y3*cos(0.523);
        X3=temp3;

        update();
    });

    //放缩
    connect(ui->pushButton_4,&QPushButton::clicked,this,[=](){
        func1=fangsuo;
        X1=X1*0.75;
        Y1=Y1*0.75;
        X2=X2*0.75;
        Y2=Y2*0.75;
        X3=X3*0.75;
        Y3=Y3*0.75;

        update();
    });

    //对称
    connect(ui->pushButton_5,&QPushButton::clicked,this,[=](){
        func1=duicheng;
        Y1=-Y1;
        Y2=-Y2;
        Y3=-Y3;
        update();
    });



}

void Widget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    // 反走样
    painter.setRenderHint(QPainter::Antialiasing, true);
    // 设置画笔颜色
    painter.setPen(QColor(0, 160, 230));

    //绘制绘图框
    painter.drawRect(QRect(QPoint(0,0),QPoint(height(),width()-100)));

    // 绘制直线
    painter.setPen(QColor(0, 0, 0));
    painter.drawLine(QLine(QPoint(height()/2,0),QPoint(height()/2,width()-100)));
    painter.drawLine(QLine(QPoint(0,(width()-100)/2),QPoint(height(),(width()-100)/2)));

    painter.translate(height()/2,(width()-100)/2);//重新设置坐标轴原点
    painter.scale(1,-1);//反转Y轴

    switch (func1) {
    case ok:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case pingyi1:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case pingyi2:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case pingyi3:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case pingyi4:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case xuanzhuan:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case fangsuo:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    case duicheng:
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X2,Y2)));
        painter.drawLine(QLine(QPoint(X2,Y2),QPoint(X3,Y3)));
        painter.drawLine(QLine(QPoint(X1,Y1),QPoint(X3,Y3)));
        break;
    default:
        break;
    }


}


Widget::~Widget()
{
    delete ui;
}

基本机制就是首先在绘图事件绘制基本的图形框,然后根据不同的图形变换功能func创建相应的枚举值,在connect的槽函数的lambda函数中给func赋值,再通过update函数刷新绘图事件,再在绘图事件函数下,判断func1的值是多少,进而完成相应的功能。

ui界面

ui界面如下,一切从简(为了完成作业

本人代码能力有限,刚学习不久,大佬可能有更好的方法欢迎指正;本文希望可以给和我一样的新人提供帮助。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT:通过按钮调用qpaintEvent事件实现自定义绘图 的相关文章

  • Qt 人工鼠标点击无法正常工作

    小玩具应用程序可以在这里找到 http gist github com 517445 http gist github com 517445 我正在尝试将人工鼠标事件发送到小部件 我使用QApplication sendEvent为此 接下
  • 在 Qt 服务器上验证用户身份

    我正在尝试使用 C QtTcpSocket 为个人项目 多人国际象棋游戏 实现身份验证系统 我的朋友建议了一种验证用户的方法 但我想问是否有更简单或更好的方法 来自 Python 背景 做这个项目主要是为了加深对 C 的理解 我将发布我朋友
  • 获取 QListView 中所有可见项目的简单方法

    我正在尝试使用 Qt Framework 开发一个图像库应用程序 应用程序从所选文件夹加载所有图像 并使用 QListView 控件显示这些图像 但现在我想通过仅加载用户可见的图像来减少内存消耗 由于没有直接函数来获取视图中的所有可见项目
  • 如何在QT上暂停和重新启动Qtimer

    我有 Ubuntu 我正在使用 IDEQT on C 我将暂停和恢复计时器 例如 void Ordonnancer les taches on pushButton clicked connect dataTimer SIGNAL time
  • Qt 为什么使用 QString::number() 而不是 QLocale().toString()?

    我正在开发的应用程序将在许多国家推出 并且需要支持他们的语言 我一直在回顾我的代码并替换以下每个实例 QString number and QString toDouble with QLocale toString and QLocale
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • 清除pyqt中布局中的所有小部件

    有没有办法清除 删除 布局中的所有小部件 self plot layout QtGui QGridLayout self plot layout setGeometry QtCore QRect 200 200 200 200 self r
  • QMainWindow 上的 Qt 布局

    我设计了一个QMainWindow with QtCreator s设计师 它由默认的中央小部件 aQWidget 其中包含一个QVBoxLayout以及其中的所有其他小部件 现在我想要的一切就是QVBoxLayout自动占据整个中央小部件
  • 使用 OpenGL 渲染 QImage

    与我相关的其他问题 https stackoverflow com questions 20126354 render qimage from sooffscreenrenderer in qglwidget 我认为更核心的问题是 如何渲染
  • 如何在针对 Windows XP 的情况下使用 VS2012 构建 Qt 4/5?

    我正在尝试使用 Visual Studio 2012 构建 Qt 4 8 5 Qt 5 2 1 针对 Windows XP SDK v7 1a 使用 VS2102 编译时 源代码与 SDK v7 1a 存在各种不兼容性 因此无法开箱即用 这
  • Qt 嵌入式触摸屏 QMouseEvents 在收到 MouseButtonRelease 之前未收到

    我在带有触摸屏的小型 ARM 嵌入式 Linux 设备上使用 Qt 4 8 3 我的触摸屏配置了 tslib 并对其进行了校准 因此 etc 中有一个 pointcal 文件 我的触摸事件的位置工作得很好 但无论如何我都会在鼠标按下或鼠标释
  • QTableView 并双击一个单元格

    我正在开发测试用例编辑器 该编辑器包含 USART 传输和接收数据包格式 编辑器是一个表格视图 发送和接收数据包的长度为八个字节 例如 0x01 0x02 0x03 0x08 它在我的第五和第六栏中 现在 我希望此列中的单元格为只读 但是当
  • Qt中用于线程间通信的类设计

    问题陈述 用相机跟踪物体并相应地移动相机的方位角和仰角 Process 相机获取物体的图像 处理相机的每一帧以查找物体 应该被跟踪 并将每帧中生成的信息传递给机械设备 万向节 以平移和倾斜方式移动摄像机 Design 主 Gui 在一个线程
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 为什么 QT 设计器重新调整大小或不允许我缩小或展开小部件或按钮?

    很多时候 在使用 QT 设计器时 我发现自己需要通过缩小或扩展来调整事物的大小 每当我尝试这样做时 程序都不允许我这样做 而只是恢复到将对象放置在窗口中时给我的原始默认大小 无论我的布局如何 为什么要这样做 是否有可能改变这一点 以便我可以
  • 在 Qt 中自动调整标签文本大小 - 奇怪的行为

    在 Qt 中 我有一个复合小部件 它由排列在 QBoxLayouts 内的多个 QLabels 组成 当小部件调整大小时 我希望标签文本缩放以填充标签区域 并且我已经在 resizeEvent 中实现了文本大小的调整 这可行 但似乎发生了某
  • QAbstractItemModel 如何表示树?

    我仍然很难理解 QAbstractItemModel 对项目的表示 有两种返回 QModelIndex 项的方法对我来说没有任何意义 QModelIndex QAbstractItemModel index int row int colu
  • 使 QLabel 的像素图透明

    我有一个带有 QLabel 和像素图的主窗口 我想让它透明 或不那么不透明 我正在使用下面的代码 ui gt label gt setAttribute Qt WA TranslucentBackground ui gt label gt
  • QT:模块“QtWebView”未安装

    我的操作系统是win10 QT版本是Qt5 7 mingw53 32 目标操作系统是win10 当我使用qmlscene执行qml文件时 发生了一些错误 qrc qml 3 模块 QtWebView 未安装 我的 qml 文件如下 impo
  • QML MouseArea 将事件传播到按钮

    我正在开发一个应用程序 其菜单类似于 Android 版 Gmail 收件箱应用程序菜单 基本上 当您按下按钮打开菜单时 它就会滑入视图 用户可以将其滑开或按菜单上的按钮 对于滑动我使用了代码SwipeArea from kovrov ht

随机推荐

  • React:状态提升案例-烧开水

    1 定义Boilingverdict组件 function Boilingverdict props if props celsius gt 100 return h1 水烧开了 h1 else return h1 水凉凉 h1 expor
  • ffmpeg基础一:解封装

    参考 零声学院 1 解封装流程 2 打开文件或媒体 获取文件或媒体的媒体信息AVFormatContext AVFormatContext是描述一个媒体文件或媒体流的构成和基本信息的结构体 AVFormatContext ifmt ctx
  • python绘制动态变化的图_用Jupyter Noteb中的matplotlib绘制动态变化图形

    我一直在寻找一个很好的解决方案 其中一个线程正在泵送数据 我们希望Jupyter笔记本不断更新图形 而不阻止任何事情 在查阅了十几个相关答案后 以下是一些发现 小心 如果你想要一个实时的图表 不要使用下面的魔术 如果笔记本使用以下内容 则图
  • 一个在PDO数据绑定上踩的坑

    不经常用PDO 一直不知道数据绑定的时候的一个细节 不可使用同一个变量名为不同的符号进行数据绑定 因为这样的话会导致在执行execute 时 不同符号都绑定了同一个值 最后一个赋予这个变量名的值 比如 letters array a b c
  • mysql商品实现多退少补_(转)mysql处理高并发,防止库存超卖

    原文链接 http blog csdn net caomiao2006 article details 38568825 今天王总又给我们上了一课 其实mysql处理高并发 防止库存超卖的问题 在去年的时候 王总已经提过 但是很可惜 即使当
  • JS逆向教程第一发

    JS逆向教程第一发 项目简介 本文适合爬虫新手初步接触js逆向时进行阅读 初步接触JS逆向 并不是很熟悉逆向操作的 可以以本文为参考 初步入门 如果有大佬 也欢迎批评指正 本文以企名科技这个网站为例 初步介绍JS逆向的基本操作 环境准备 此
  • Ubuntu20.04.4LTS安装CUDA11.6,cuDNN,TensorRT,PyCUDA,PyTorch

    从0到1的cuda安装 前言 这个CUDA是否选择最新版本和你是否用pytorch有关 你先去Pytorch查一下它最高支持的cuda版本是啥 不是一般都不是最新版 0 cuda卸载 1 cuda最新版本安装 1 检查所需版本 2 具体操作
  • JS-cookie和正则表达式

    一 cookie 1 什么是cookie 会话跟踪技术 2 作用 验证身份 存储信息 3 特点 大小限制 最多存4k 每个域下只能存50个cookie 有时间限制 只能存放字符串 只能访问同一个域内的cookie 4 读取和设置cookie
  • 【网络爬虫&自动化测试】Playwriht系列文章一

    Playwriht系列文章 一 Playwright Playwriht系列文章 一 一 Playwright是什么 二 使用步骤 1 基本使用 2 Browser BrowserType BrowserType launch kwargs
  • list容器模拟实现

    个人简介 作者简介 大家好 我是菀枯 支持我 点赞 收藏 留言 格言 不要在低谷沉沦自己 不要在高峰上放弃努力 前言 好久不见啊 今天我们的任务是自己从头到尾实现一个STL中的list容器 list的实现 list的介绍 之前我们实现了ST
  • JS Object类型变量赋值失败(普通模式静默失败/严格模式报错/触发setter)

    JS Object类型变量赋值 静默失败 严格模式报错 在回顾 你不知道的JavaScript 上卷的 第五章 5 1 2 属性设置和屏蔽 时候看到一个知识点 开发者一般情况都认为如果对 Prototype 上已经存在的属性进行 Put 赋
  • java sum_java math.sum

    Math random 100 num2 int Math random 100 sum 0 temp int Math random 10 2 if temp 0 sum sum m 除法运算 if preOperater equals
  • mysql 字段类型 负数_MySQL字段类型详解

    MySQL支持大量的列类型 它可以被分为3类 数字类型 日期和时间类型以及字符串 字符 类型 本节首先给出可用类型的一个概述 并且总结每个列类型的存储需求 然后提供每个类中的类型性质的更详细的描述 概述有意简化 更详细的说明应该考虑到有关特
  • UNIX环境高级编程 学习笔记 第四章 文件和目录

    4个stat函数 stat函数返回名为参数pathname的文件有关的信息结构 fstat函数获得已经在描述符fd上打开的文件的信息 lstat函数的参数pathname如果是一个符号链接文件 它返回符号链接的有关信息 而非该符号链接引用的
  • 解除BitLocker加密

    问题描述 硬盘设置BitLocker加密后 系统异常时必须输入BitLocker恢复密钥 才能使用windows高级功能进行修复 启用BitLocker硬盘加密后一定要保存好BitLocker密钥 加密状态下windows密码无法强制破解
  • Xilinx ISE 14.7 设置编辑器字体大小

    左上角 edit preference
  • 2013年5月23日(7-9ddraw裁剪器)

    进行裁剪步骤有4个 1 创建ddraw裁减器对象 CreateClipper 0 LPDIRECTDRAWCLIPPER NULL 2 创建裁剪队列 即RECT结构的矩形列表 blitter硬件只绘制裁剪区内的内容 其余的都剪掉 裁剪队列需
  • MATLAB对原始光斑进行运算

    clc clear all close all I imread ban jpg figure 1 subplot 1 3 1 imshow I 显示原始光斑 title 原始光斑 I1 imadjust I 0 2 0 6 subplot
  • liunx,centos7 下安装部署 Jenkins 持续集成工具,war包方式安装Jenkins

    Jenkins是一个开源软件项目 是基于Java开发的一种持续集成工具 用于监控持续重复的工作 旨在提供一个开放易用的软件平台 使软件的持续集成变成可能 下载地址 https bitnami com stack jenkins instal
  • QT:通过按钮调用qpaintEvent事件实现自定义绘图

    摘要 最近碰到了一个需要在qt中完成二维图像变换的作业 想到刚接触qt时学过qpainter来进行绘画操作 立马就着手码起来 作为一个小白 马上就发现了相应的问题 由于qt内部机制 绘画事件 paintEvent 仅允许在绘画事件下进行 比