Qt自定义控件 —— 颜色选择组合控件

        在开始阅读本文之前,如果您有学习创建Qt自定义控件并在其他项目中引用的需求,请参考:

Linux系统下在Qt Creator中创建自定义控件并在其他项目中引用https://blog.csdn.net/YMGogre/article/details/128920804


目录

1、应用场景:

2、所需资源:

3、界面布局:

3.1、各布局/控件属性:

4、源代码:

4.1、h文件

4.2、cpp文件

4.3、ui文件

5、使用方法:

6、注意事项:

7、源码下载:


1、应用场景:

  • 当我们需要一个组合控件可以通过键盘输入或者打开Qt的颜色对话框来设置其他控件的颜色时;

2、所需资源:

(无,本质即 Qt 的几个自带控件的组合)

3、界面布局:

整体布局如下图所示,该自定义控件由一个GraphicsView、一个LineEdit、一个PushButton组成。窗口整体设置了 baseSize 为 140 × 25

3.1、各布局/控件属性:

MyPalette属性
horizontalLayout属性
ColorDisplay属性
ColorLineEdit属性
btn_SelectColor属性

4、源代码:

4.1、h文件

/* mypalette.h */

#ifndef MYPALETTE_H
#define MYPALETTE_H

#include <QObject>
#include <QWidget>
#include <QColorDialog>
#include <QColor>
#include <QPalette>
#include <QString>
#include <QRegExpValidator>
#include <QtUiPlugin/QDesignerExportWidget>
#include <QEvent>
#include <QMouseEvent>
#include <QPushButton>

namespace Ui {
class MyPalette;
}

class QDESIGNER_WIDGET_EXPORT MyPalette : public QWidget
{
    Q_OBJECT

public:
    explicit MyPalette(QWidget *parent = nullptr);
    ~MyPalette();
    QColor currentColor();
    void setColor(int r, int g, int b, int a = 255);
    void setColor(QColor color);

protected:
    bool eventFilter(QObject *watchedm, QEvent *event) override;    //重写事件过滤器方法

signals:
    void colorchanged(QColor);              //自定义颜色改变信号

private:
    Ui::MyPalette *ui;
    QColor color = QColor(Qt::white);
};

#endif // MYPALETTE_H

4.2、cpp文件

/* mypalette.cpp */

#include "mypalette.h"
#include "ui_mypalette.h"

MyPalette::MyPalette(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyPalette)
{
    ui->setupUi(this);
    //QGraphicsView的鼠标事件会传递给它所显示的QGraphicsScene,然后再传递给场景中的QGraphicsItem。我们设置该控件属性:传递给父对象做鼠标事件处理
    ui->ColorDisplay->setAttribute(Qt::WA_TransparentForMouseEvents);

    /*****************************************
     * 为自定义控件的子控件安装该自定义控件的事件过滤器
     ****************************************/
    ui->ColorLineEdit->installEventFilter(this);
    ui->btn_SelectColor->installEventFilter(this);
    /*使用正则表达式限制输入(正确输入格式应当形如 ———— "255; 255; 255",最后允许跟随一个分号以及一个0~255的alpha通道值)
     * (2[0-4][0-9];?\\s?)  ———— 限制输入200~249正整数(尾部允许跟随0~1个分号";"和空格" ")
     * (25[0-5];?\\s?)      ———— 限制输入250~255正整数(尾部允许跟随0~1个分号";"和空格" ")
     * (1[0-9][0-9];?\\s?)  ———— 限制输入100~199正整数(尾部允许跟随0~1个分号";"和空格" ")
     * ([1-9]?[0-9];?\\s?)  ———— 限制输入0~99正整数(尾部允许跟随0~1个分号";"和空格" ")
    */
    ui->ColorLineEdit->setValidator(new QRegExpValidator(QRegExp("^((2[0-4][0-9];\\s?)|(25[0-5];\\s?)|(1[0-9][0-9];\\s?)|([1-9]?[0-9];\\s?)){0,3}((2[0-4][0-9])|(25[0-5])|(1[0-9][0-9])|([1-9]?[0-9]))?$")));

    connect(ui->ColorLineEdit, &QLineEdit::textChanged, this, [=](){
        //使用正则表达式删除字符串中所有空格
        QString colorStr = ui->ColorLineEdit->text().remove(QRegExp("\\s"));
        //使用split方法按";"分号分割字符串为字符串数组
        QStringList colorStrList = colorStr.split(";");
        //当LineEdit只有rgb的值时
        if(colorStrList.size() == 3)
        {
            //使用字符串数组内容初始化一个QColor对象并赋值给color成员变量
            color = QColor(colorStrList[0].toInt(), colorStrList[1].toInt(), colorStrList[2].toInt());
            //当颜色改变时,发送“颜色改变信号”
            emit colorchanged(color);
        }
        //当LineEdit除了rgb的值还有alpha通道的值时
        else if(colorStrList.size() == 4)
        {
            //使用字符串数组内容初始化一个QColor对象并赋值给color成员变量
            color = QColor(colorStrList[0].toInt(), colorStrList[1].toInt(), colorStrList[2].toInt(), colorStrList[3].toInt());
            //当颜色改变时,发送“颜色改变信号”
            emit colorchanged(color);
        }
        //获取调色板
        QPalette pal = ui->ColorDisplay->palette();
        //设置调色板
        pal.setColor(QPalette::Base, color);
        //设置控件底色
        ui->ColorDisplay->setPalette(pal);
    });

    //当文本框编辑结束时,根据color成员变量显示其RGB字符串
    connect(ui->ColorLineEdit, &QLineEdit::editingFinished, this, [=](){
        //当alpha通道值为255(默认)时,LineEdit默认不显示alpha通道值
        if(color.alpha() == 255)
        {
            QString colorStr = QString::number(color.red()) + "; " + QString::number(color.green()) + "; " + QString::number(color.blue());
            ui->ColorLineEdit->setText(colorStr);
        }
        else
        {
            QString colorStr = QString::number(color.red()) + "; " + QString::number(color.green()) + "; " + QString::number(color.blue()) + "; " + QString::number(color.alpha());
            ui->ColorLineEdit->setText(colorStr);
        }
    });

    connect(ui->btn_SelectColor, &QPushButton::clicked, this, [=](){
        //打开一个颜色对话框并将其返回值交给局部变量_color
        QColor _color = QColorDialog::getColor();
        //判断返回的颜色是否有效
        if(_color.isValid())
        {
            //有效则改变颜色并发送信号
            color = _color;
            //当颜色改变时,发送“颜色改变信号”
            emit colorchanged(color);
        }
        //根据对话框返回的颜色修改颜色展示方块的颜色
        QPalette pal = ui->ColorDisplay->palette();
        //设置调色板
        pal.setColor(QPalette::Base, color);
        //设置控件底色
        ui->ColorDisplay->setPalette(pal);
        //根据对话框返回的颜色获取RGB三色字符串
        QString colorStr = QString::number(color.red()) + "; " + QString::number(color.green()) + "; " + QString::number(color.blue());
        ui->ColorLineEdit->setText(colorStr);
    });
}

/**
 * @brief 获取当前颜色方法
 * @return QColor   ———— 返回当前QColor颜色对象
 */
QColor MyPalette::currentColor()
{
    return color;
}

/**
 * @brief 设置颜色方法
 * @param int r ———— 红色
 * @param int g ———— 绿色
 * @param int b ———— 蓝色
 * @param int a ———— Alpha通道值(0完全透明~255完全不透明)
 */
void MyPalette::setColor(int r, int g, int b, int a)
{
    if(a == 255)
    {
        //设置RGB三色字符串
        QString colorStr = QString::number(r) + "; " + QString::number(g) + "; " + QString::number(b);
        //setText()方法也会触发QLineEdit的textChanged信号
        ui->ColorLineEdit->setText(colorStr);
    }
    else
    {
        //设置RGB三色字符串
        QString colorStr = QString::number(r) + "; " + QString::number(g) + "; " + QString::number(b) + "; " + QString::number(a);
        //setText()方法也会触发QLineEdit的textChanged信号
        ui->ColorLineEdit->setText(colorStr);
    }
}

/**
 * @brief 设置颜色方法
 * @param QColor color ———— QColor颜色对象
 */
void MyPalette::setColor(QColor color)
{
    if(color.alpha() == 255)
    {
        //设置RGB三色字符串
        QString colorStr = QString::number(color.red()) + "; " + QString::number(color.green()) + "; " + QString::number(color.blue());
        //setText()方法也会触发QLineEdit的textChanged信号
        ui->ColorLineEdit->setText(colorStr);
    }
    else
    {
        //设置RGB三色字符串
        QString colorStr = QString::number(color.red()) + "; " + QString::number(color.green()) + "; " + QString::number(color.blue()) + "; " + QString::number(color.alpha());
        //setText()方法也会触发QLineEdit的textChanged信号
        ui->ColorLineEdit->setText(colorStr);
    }
}

/**
 * @brief 重写事件过滤器方法
 * @attention 这里简要说下为什么要重写该方法,这是因为当我们的自定义控件中有其他子控件时,
 * 点击子控件的点击响应是相应到子控件上的,而通常我们希望所有子控件的父对象(也就是自定义控
 * 件本身)也会在点击这些子控件时有响应
 * @param QMouseEvent *event ———— 事件对象
 */
bool MyPalette::eventFilter(QObject *watched, QEvent *event)
{
  //拦截子控件的鼠标按下或释放事件
  if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease)
  {
    //QEvent类型转换为QMouseEvent类型
    QMouseEvent *mouseevent = static_cast<QMouseEvent *>(event);
    this->QWidget::mousePressEvent(mouseevent);    //调用基类的mousePressEvent方法
    //如果事件的被监视对象是QPushButton
    if(qobject_cast<QPushButton *>(watched))
      this->setFocus();     //设置自定义控件本身获得焦点

    return false;     //传递事件给子控件,让其正常响应点击
    //return true;    //事件处理完毕(不传递事件给子控件,只响应自定义控件本身被选中)
  }
  //其他类型的事件交由基类处理
  return QWidget::eventFilter(watched, event);
}

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

4.3、ui文件

UI文件仅能在设计模式下编辑,这里仅供布局参考!

<!-- mypalette.ui -->

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MyPalette</class>
 <widget class="QWidget" name="MyPalette">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>299</width>
    <height>188</height>
   </rect>
  </property>
  <property name="baseSize">
   <size>
    <width>140</width>
    <height>25</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <property name="autoFillBackground">
   <bool>true</bool>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <property name="spacing">
    <number>0</number>
   </property>
   <property name="leftMargin">
    <number>0</number>
   </property>
   <property name="topMargin">
    <number>0</number>
   </property>
   <property name="rightMargin">
    <number>0</number>
   </property>
   <property name="bottomMargin">
    <number>0</number>
   </property>
   <item>
    <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0">
     <property name="spacing">
      <number>2</number>
     </property>
     <property name="leftMargin">
      <number>0</number>
     </property>
     <property name="topMargin">
      <number>0</number>
     </property>
     <property name="rightMargin">
      <number>0</number>
     </property>
     <property name="bottomMargin">
      <number>0</number>
     </property>
     <item>
      <widget class="QGraphicsView" name="ColorDisplay">
       <property name="sizePolicy">
        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
         <horstretch>0</horstretch>
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
       <property name="minimumSize">
        <size>
         <width>16</width>
         <height>16</height>
        </size>
       </property>
       <property name="maximumSize">
        <size>
         <width>16</width>
         <height>16</height>
        </size>
       </property>
       <property name="baseSize">
        <size>
         <width>16</width>
         <height>16</height>
        </size>
       </property>
       <property name="autoFillBackground">
        <bool>true</bool>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLineEdit" name="ColorLineEdit">
       <property name="autoFillBackground">
        <bool>true</bool>
       </property>
       <property name="text">
        <string>255; 255; 255</string>
       </property>
       <property name="maxLength">
        <number>18</number>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QPushButton" name="btn_SelectColor">
       <property name="sizePolicy">
        <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
         <horstretch>0</horstretch>
         <verstretch>0</verstretch>
        </sizepolicy>
       </property>
       <property name="minimumSize">
        <size>
         <width>16</width>
         <height>16</height>
        </size>
       </property>
       <property name="maximumSize">
        <size>
         <width>16</width>
         <height>16</height>
        </size>
       </property>
       <property name="baseSize">
        <size>
         <width>16</width>
         <height>16</height>
        </size>
       </property>
       <property name="autoFillBackground">
        <bool>true</bool>
       </property>
       <property name="text">
        <string>...</string>
       </property>
      </widget>
     </item>
    </layout>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

5、使用方法:

  • 颜色选择组合控件封装了一个自定义信号 colorchanged,该信号会在颜色发生改变时被发送,使用该信号连接你的槽函数即可;

        colorchanged 信号是一个带参信号,可以传递一个 QColor 对象。比如说我们可以通过类似于以下的代码去设置一个 PushButton 控件的颜色:

connect(ui->myPalette, &MyPalette::colorchanged, this, [=](QColor color){
    QPalette pal = ui->btn->palette();
    //注:使用QPalette::Button枚举值设置按钮颜色时,alpha通道值是无效的
    pal.setColor(QPalette::Button, color);
    ui->btn->setPalette(pal);
});
  • 通过 currentColor() 成员方法可以在代码里获取对象的颜色属性,该方法返回一个 QColor 对象;
  • 通过 setColor() 成员方法可以在代码里设置对象的颜色属性,该方法有一个重载;

        当然,setColor() 成员方法也会触发发送 colorchanged 信号。

6、注意事项:

请参考文章:Qt自定义控件 —— 子控件与父控件的鼠标事件问题https://blog.csdn.net/YMGogre/article/details/129357734

💠本文提供的代码是已经解决了上面文章中涉及的问题后的代码。

7、源码下载:

CSDN下载:Qt自定义控件-颜色选择组合控件-C++文档类资源-CSDN文库https://download.csdn.net/download/YMGogre/87541452

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt自定义控件大全Designer源码是一个包含了多种自定义控件的全套源码,它主要用于在Qt设计师中使用。Qt是一个跨平台的C++应用程序开发框架,提供了丰富的图形界面控件,但有时候我们可能需要自定义一些特殊的控件来满足我们的需求。 Qt自定义控件大全Designer源码包含了很多常用的自定义控件,如自定义按钮、进度条、滑块、验证码输入框等等。这些控件的设计和实现已经封装好,我们只需要将源码添加到我们的项目中,然后在Qt设计师中直接使用即可。 使用Qt自定义控件大全Designer源码有以下几个优点: 1.提供了丰富的自定义控件选择Qt自定义控件大全Designer源码包含了多样化的控件,可以满足不同项目的需求。无论是一些简单的控件,还是一些复杂的控件,我们都可以找到合适的选择。 2.减少开发时间和工作量:使用源码中的自定义控件可以减少我们从头开始设计和实现的工作,节省了大量的开发时间和工作量。我们只需要将源码添加到项目中并正确配置,就可以直接在设计师中使用这些自定义控件。 3.提高应用程序的美观性和用户体验:Qt自定义控件大全Designer源码中的控件经过精心设计和实现,具有良好的界面效果和用户交互体验。使用这些自定义控件可以为我们的应用程序提供更加美观和友好的界面。 总之,Qt自定义控件大全Designer源码是一个提供了多种自定义控件的全套源码,使用它可以快速、方便地实现各种自定义控件,提高应用程序的开发效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值