0


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

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

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



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

标签: qt ui c++

本文转载自: https://blog.csdn.net/YMGogre/article/details/128955257
版权归原作者 YMGogre 所有, 如有侵权,请联系我们删除。

“Qt自定义控件 —— 颜色选择组合控件”的评论:

还没有评论