首页 > 其他分享 >Qt实现自定义控件-按钮

Qt实现自定义控件-按钮

时间:2024-10-08 15:49:47浏览次数:7  
标签:控件 Qt 自定义 isoff animation radius event painter

背景:

想着自己实现一个好看一点的按钮,切换时加一点动画。也算巩固一下Qt的基本知识。

基本环境:

 

主要用到的类有:

QBrush:画刷,主要是画一些颜色啥的。

QPainter:画笔,可以画形状。比如带弧形的矩形,圆形,写字等。

QPropertyAnimation:动画相关。

关键逻辑:

重载paintEvent:实现渲染逻辑,在这里根据不同的状态画出不同的颜色。

重载mousePressEvent:鼠标点击时切换状态。

将QPropertyAnimation::valueChanged信号函数连接起来,获取动画运行时的值,然后重新绘制圆形。

上代码:

一些逻辑和类的用法见注释。

mybutton.h:

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QWidget>
#include <QPropertyAnimation>

class MyButton : public QWidget
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);
    bool GetIsOff(){return isoff;}; // 提供一个对外接口
signals:
    void isClicked();
    void notifyStatus(bool bOff); // 发一个带参数的信号
protected:
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override; // 鼠标点击事件
    void resizeEvent(QResizeEvent* event) override;  // 窗口大小发生改变的事件
private:
    bool isoff = true; // 根据状态去选择不同的颜色
    QBrush offBgBrush = Qt::black;
    QBrush offRBrush = Qt::red;
    QBrush onBgBrush = Qt::gray;
    QBrush onRBrush = Qt::green;
    QString offText = "OFF";
    QString onText = "ON";

    QPropertyAnimation *animation; // 动画相关
    int currentX = height()/2; // 圆形当前的位置
};

#endif // MYBUTTON_H

mybutton.cpp:

#include "mybutton.h"
#include <QMouseEvent>
#include <QPainter>

MyButton::MyButton(QWidget *parent)
    : QWidget{parent}
{
    setFixedSize(60,30);
    animation = new QPropertyAnimation(this);
    animation->setTargetObject(this);
    animation->setStartValue(height()/2);
    animation->setEndValue(width() - height()/2);
    animation->setEasingCurve(QEasingCurve::InOutCirc); // 设置移动的曲线。比如可以先慢后快。这里是设置回弹效果。
    animation->setDuration(500); // 移动的持续时间

    // 这里用了一个匿名函数
    connect(animation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value){
        currentX = value.toInt(); // 动画产生的时候更新当前位置
        update();
    });
}

void MyButton::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event); // 不使用event时,为了编译时不加告警,用一个宏控制。
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true); // 为了让圆弧边框光滑
    int radius = height()/2;

    painter.setPen(Qt::NoPen); // 把边框去掉. 好看一点。
    // 画矩形,两边是圆弧。
    painter.setBrush(isoff ? offBgBrush : onBgBrush);
    painter.drawRoundedRect(this->rect(), radius, radius);

    // 画圆
    painter.setBrush(isoff ? offRBrush : onRBrush);
    QPoint center; // 画圆的位置
    center.setY(radius);
    //center.setX(isoff ? radius : width() - radius); // 为on状态时,x设置为矩形的右边。也就是宽度-半径
    center.setX(currentX); // 根据动画算出来的坐标
    painter.drawEllipse(center, radius - radius/10, radius - radius/10);

    // 正中间显示字
    painter.setPen(Qt::white);
    painter.setFont(QFont("Arial", radius/2));
    painter.drawText(this->rect(), Qt::AlignCenter, isoff ? offText : onText);
}

// 相应点击事件,进行切换。
void MyButton::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        // 根据当前状态,调整动画的方向。
        isoff ? animation->setDirection(QAbstractAnimation::Forward) : animation->setDirection(QAbstractAnimation::Backward);
        animation->start();
        isoff = !isoff;
        emit isClicked();
        emit notifyStatus(isoff);
        update(); // 会触发绘图事件,重新绘图。
    }
}

void MyButton::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event); // 不使用event时,为了编译时不加告警,用一个宏控制。
    animation->setStartValue(height()/2);
    animation->setEndValue(width() - height()/2);
}

如何使用:

介绍两种使用方法:

代码中添加:

 方式二:

界面文件中直接添加,具体如下:

直接拖拽一个Widget -》右键“提升为” -》选择自定义的类-》点击“提升”

 据说有第三种方式,可以用插件,直接添加自定义的类。有兴趣的可以去研究一下。

测试:

 

 

标签:控件,Qt,自定义,isoff,animation,radius,event,painter
From: https://www.cnblogs.com/xcywt/p/18451787

相关文章

  • Pyqt5+SQLite
    通常在做业务逻辑时会遇到,如何在界面上对数据库信息进行操作的问题。这里我们选用SQLite,它是一种嵌入式数据库,以单个独立的文件形式存储数据,适用于Pyqt5的开发。下面做一个小案例,将数据库信息显示在界面中。1.创建数据库代码案例如下(创建一个用户信息表):conn=sqlite3.con......
  • Vue.js 自定义事件命名
    什么是Vue.js自定义事件命名?在Vue.js中,自定义事件是一种允许组件之间进行通信的重要机制。通过自定义事件,我们可以在父组件和子组件之间传递数据,实现组件的解耦和复用。Vue.js中的事件命名可以使用驼峰命名法或短横线命名法。但是,Vue.js官方强烈建议使用短横线命名法来定义自定义......
  • labview和QT编程
    LabViewLabView所面向的并非传统意义上的程序员。他的所有功能都可以通过组合某些组件来完成。程序的流程控制,比如循环之类的也是通过画图一样的操作来做的。所有的程序功能几乎都可以通过鼠标来构造出来。优点是做一个能运行的程序非常简单。做一个虚拟的仪器很容易。也不需要......
  • Nodered学习记录-MQTT
    安装EMQXEMQX(以前称为EMQ)是一个开源的、高度可扩展且高可用的分布式MQTT消息代理,专为物联网(IoT)、机器对机器(M2M)通信和移动应用程序设计。它支持MQTT和其他IoT协议如CoAP/LwM2M,能够处理数百万并发连接,并提供强大的消息路由能力。通过docker安装官方文档$dockerpullem......
  • 用自定义函数解决帝国cms的简介截取字符时出现html的问题
    帝国CMS在截取文章简介时出现HTML标签的问题可以通过自定义函数来解决。具体步骤如下:步骤1:自定义函数 NoHTML()打开 connect.php 文件找到 e/class/connect.php 文件并打开。添加自定义函数 NoHTML()在文件中添加以下函数://去除HTML标记function......
  • day11[Lagent 自定义你的 Agent 智能体]
    环境配置开发机选择30%A100,镜像选择为Cuda12.2-conda。首先来为Lagent配置一个可用的环境。LagentWebDemo使用使用Lagent的WebDemo来体验InternLM2.5-7B-Chat的智能体能力先使用LMDeploy部署InternLM2.5-7B-Chat,并启动一个APIServer然后,我们在另一个......
  • 如何修改PbootCMS默认面包屑导航样式及自定义设置方法
    在PbootCMS中,面包屑导航是一个重要的导航元素,帮助用户快速了解当前页面的位置和路径。为了满足不同的设计需求,可以通过自定义参数和修改样式来调整面包屑导航。下面详细介绍如何进行这些自定义操作。PbootCMS面包屑导航调用方式html {pboot:position}自定义参数常用参......
  • 记一次控件提升后,运行却不显示的Bug
    .h文件#ifndefVOLUMETOOLBTN_H#defineVOLUMETOOLBTN_H#include<QToolButton>#include<memory>classVolumeToolBtn:publicQToolButton{Q_OBJECTpublic:explicitVolumeToolBtn(QWidget*parent=nullptr);~VolumeToolBtn()override;......
  • cnBlogs的自定义样式
    存个备份.navbara:link,.navbara:active,.navbara:visited{color:#666;text-decoration:none}.navbara:hover{color:#666;text-decoration:underline}.navbar>nav.navbar-avatar{border-radius:50%}.post-item.avatar{......
  • QT5 C++槽函数的两种connect连接方式的区别,建议使用现代的连接方式
    QT5C++槽函数的两种connect连接方式的区别,建议使用现代的连接方式(1)QT5C++槽函数定义classMainWindow:publicQMainWindow{Q_OBJECT//......privateslots:voidslotSplitterMoved(int,int);//......}(2)使用旧的字符串connect连接方式,容易报错或者警告 连......