Qt escribe un botón de interruptor de control personalizado

Hay muchos elementos populares en la aplicación en el teléfono móvil. Me gusta mucho el botón de cambio. Mobile QQ, 360 guards, Jinshan Duba, etc. todos tienen muchos interruptores para controlar algunas operaciones. En el proyecto de aplicación Qt widgets, aplique algunos botones de interruptor similares en el proyecto, se estima que también agregará mucha frescura al proyecto.

Resumiendo la mayoría de los controles de los botones de cambio, hay básicamente dos categorías, la primera categoría es el dibujo de código puro, este tipo de control del código es relativamente alto, pero la flexibilidad es mejor. La segunda categoría son las texturas, que son imágenes de fondo en varios estados preparadas por artistas profesionales. Solo necesita usar código para dibujar las imágenes en la interfaz. Para cubrir dos tipos de botones de cambio, los cuatro tipos comunes (rectángulo redondeado/círculo interior/círculo exterior/imagen) se integran deliberadamente en el botón de cambio personalizado.

resultado de ejecución:

Los beneficios de este artículo, gratis para recibir el paquete de materiales de aprendizaje de desarrollo Qt, video técnico, que incluye (base del lenguaje C ++, patrón de diseño C ++, introducción a la programación Qt, mecanismo de señal y ranura QT, dibujo de imagen de desarrollo de interfaz QT, red QT, QT programación de base de datos, combate real del proyecto QT, QSS, OpenCV, módulo rápido, preguntas de la entrevista, etc. )

1: dibujo de código puro

El código puro dibuja el botón de cambio, que puede configurar de manera flexible varios colores, intervalos, texto, etc., y también puede producir efectos de deslizamiento de animación excesivos.

El efecto deslizante se genera utilizando el método de dibujo del temporizador para calcular automáticamente la coordenada inicial del eje X del control deslizante y detener el temporizador cuando la coordenada inicial del eje X del control deslizante alcanza la coordenada final del eje X del control deslizante.

void SwitchButton::updateValue()
{
    if (checked) {
        if (startX < endX) {
            startX = startX + step;
        } else {
            startX = endX;
            timer->stop();
        }
    } else {
        if (startX > endX) {
            startX = startX - step;
        } else {
            startX = endX;
            timer->stop();
        }
    }
    update();
}

2: dibujo de textura

void SwitchButton::drawImage(QPainter *painter)
{
    painter->save();
    QPixmap pix; 

    if (!checked) {
        pix = QPixmap(imageOff);
    } else {
        pix = QPixmap(imageOn);
    } 

    //自动等比例平滑缩放居中显示
    int targetWidth = pix.width();
    int targetHeight = pix.height();
    pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); 

    int pixX = rect().center().x() - targetWidth / 2;
    int pixY = rect().center().y() - targetHeight / 2;
    QPoint point(pixX, pixY);
    painter->drawPixmap(point, pix); 
    painter->restore();
}

Código completo:

switchbutton.h

#ifndef SWITCHBUTTON_H
#define SWITCHBUTTON_H

/**
 * 作者:feiyangqingyun(QQ:517216493) 2016-11-6
 * 1:可设置开关按钮的样式 圆角矩形/内圆形/外圆形/图片
 * 2:可设置选中和未选中时的背景颜色
 * 3:可设置选中和未选中时的滑块颜色
 * 4:可设置显示的文本
 * 5:可设置滑块离背景的间隔
 * 6:可设置圆角角度
 */

#include <QWidget>

class QTimer;

class SwitchButton: public QWidget
{
    Q_OBJECT
public:
    enum ButtonStyle {
        ButtonStyle_Rect = 0,     //圆角矩形
        ButtonStyle_CircleIn = 1, //内圆形
        ButtonStyle_CircleOut = 2,//外圆形
        ButtonStyle_Image = 3     //图片
    };

    SwitchButton(QWidget *parent = 0);
    ~SwitchButton();

protected:
    void mousePressEvent(QMouseEvent *);
    void resizeEvent(QResizeEvent *);
    void paintEvent(QPaintEvent *);
    void drawBg(QPainter *painter);
    void drawSlider(QPainter *painter);
    void drawText(QPainter *painter);
    void drawImage(QPainter *painter);

private:
    bool checked;               //是否选中
    ButtonStyle buttonStyle;    //开关按钮样式

    QColor bgColorOff;          //关闭时背景颜色
    QColor bgColorOn;           //打开时背景颜色

    QColor sliderColorOff;      //关闭时滑块颜色
    QColor sliderColorOn;       //打开时滑块颜色

    QColor textColorOff;        //关闭时文本颜色
    QColor textColorOn;         //打开时文本颜色

    QString textOff;            //关闭时显示的文字
    QString textOn;             //打开时显示的文字

    QString imageOff;           //关闭时显示的图片
    QString imageOn;            //打开时显示的图片

    int space;                  //滑块离背景间隔
    int rectRadius;             //圆角角度

    int step;                   //每次移动的步长
    int startX;                 //滑块开始X轴坐标
    int endX;                   //滑块结束X轴坐标
    QTimer *timer;              //定时器绘制

private slots:
    void updateValue();

public:
    bool getChecked()const
    {
        return checked;
    }
    ButtonStyle getButtonStyle()const
    {
        return buttonStyle;
    }

    QColor getBgColorOff()const
    {
        return bgColorOff;
    }
    QColor getBgColorOn()const
    {
        return bgColorOn;
    }

    QColor getSliderColorOff()const
    {
        return sliderColorOff;
    }
    QColor getSliderColorOn()const
    {
        return sliderColorOn;
    }

    QColor getTextColorOff()const
    {
        return textColorOff;
    }
    QColor getTextColorOn()const
    {
        return textColorOn;
    }

    QString getTextOff()const
    {
        return textOff;
    }
    QString getTextOn()const
    {
        return textOn;
    }

    QString getImageOff()const
    {
        return imageOff;
    }
    QString getImageOn()const
    {
        return imageOn;
    }

    int getSpace()const
    {
        return space;
    }
    int getRectRadius()const
    {
        return rectRadius;
    }

public slots:
    //设置是否选中
    void setChecked(bool checked);
    //设置风格样式
    void setButtonStyle(ButtonStyle buttonStyle);

    //设置背景颜色
    void setBgColor(QColor bgColorOff, QColor bgColorOn);
    //设置滑块颜色
    void setSliderColor(QColor sliderColorOff, QColor sliderColorOn);
    //设置文本颜色
    void setTextColor(QColor textColorOff, QColor textColorOn);

    //设置文本
    void setText(QString textOff, QString textOn);

    //设置背景图片
    void setImage(QString imageOff, QString imageOn);

    //设置间隔
    void setSpace(int space);
    //设置圆角角度
    void setRectRadius(int rectRadius);

signals:
    void checkedChanged(bool checked);
};

#endif // SWITCHBUTTON_H

switchbutton.cpp

#include "switchbutton.h"
#include "qpainter.h"
#include "qevent.h"
#include "qtimer.h"
#include "qdebug.h"

SwitchButton::SwitchButton(QWidget *parent): QWidget(parent)
{
    checked = false;
    buttonStyle    = ButtonStyle_Rect;

    bgColorOff = QColor(225, 225, 225);
    bgColorOn = QColor(250, 250, 250);

    sliderColorOff = QColor(100, 100, 100);
    sliderColorOn = QColor(100, 184, 255);

    textColorOff = QColor(255, 255, 255);
    textColorOn = QColor(10, 10, 10);

    textOff = "";
    textOn = "";

    imageOff = ":/image/btncheckoff1.png";
    imageOn = ":/image/btncheckon1.png";

    space = 2;
    rectRadius = 5;

    step = width() / 50;
    startX = 0;
    endX = 0;

    timer = new QTimer(this);
    timer->setInterval(5);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));

    setFont(QFont("Microsoft Yahei", 10));
}

SwitchButton::~SwitchButton()
{

}

void SwitchButton::mousePressEvent(QMouseEvent *)
{
    checked = !checked;
    emit checkedChanged(checked);

    //每次移动的步长为宽度的 50分之一
    step = width() / 50;

    //状态切换改变后自动计算终点坐标
    if (checked) {
        if (buttonStyle == ButtonStyle_Rect) {
            endX = width() - width() / 2;
        } else if (buttonStyle == ButtonStyle_CircleIn) {
            endX = width() - height();
        } else if (buttonStyle == ButtonStyle_CircleOut) {
            endX = width() - height() + space;
        }
    } else {
        endX = 0;
    }

    timer->start();
}

void SwitchButton::resizeEvent(QResizeEvent *)
{
    //每次移动的步长为宽度的 50分之一
    step = width() / 50;

    //尺寸大小改变后自动设置起点坐标为终点
    if (checked) {
        if (buttonStyle == ButtonStyle_Rect) {
            startX = width() - width() / 2;
        } else if (buttonStyle == ButtonStyle_CircleIn) {
            startX = width() - height();
        } else if (buttonStyle == ButtonStyle_CircleOut) {
            startX = width() - height() + space;
        }
    } else {
        startX = 0;
    }

    update();
}

void SwitchButton::paintEvent(QPaintEvent *)
{
    //绘制准备工作,启用反锯齿
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    if (buttonStyle == ButtonStyle_Image) {
        //绘制图片
        drawImage(&painter);
    } else {
        //绘制背景
        drawBg(&painter);
        //绘制滑块
        drawSlider(&painter);
        //绘制文字
        drawText(&painter);
    }
}

void SwitchButton::drawBg(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    if (!checked) {
        painter->setBrush(bgColorOff);
    } else {
        painter->setBrush(bgColorOn);
    }

    if (buttonStyle == ButtonStyle_Rect) {
        painter->drawRoundedRect(rect(), rectRadius, rectRadius);
    } else if (buttonStyle == ButtonStyle_CircleIn) {
        QRect rect(0, 0, width(), height());
        //半径为高度的一半
        int radius = rect.height() / 2;
        //圆的宽度为高度
        int circleWidth = rect.height();

        QPainterPath path;
        path.moveTo(radius, rect.left());
        path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180);
        path.lineTo(rect.width() - radius, rect.height());
        path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180);
        path.lineTo(radius, rect.top());

        painter->drawPath(path);
    } else if (buttonStyle == ButtonStyle_CircleOut) {
        QRect rect(space, space, width() - space * 2, height() - space * 2);
        painter->drawRoundedRect(rect, rectRadius, rectRadius);
    }

    painter->restore();
}

void SwitchButton::drawSlider(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    if (!checked) {
        painter->setBrush(sliderColorOff);
    } else {
        painter->setBrush(sliderColorOn);
    }

    if (buttonStyle == ButtonStyle_Rect) {
        int sliderWidth = width() / 2 - space * 2;
        int sliderHeight = height() - space * 2;
        QRect sliderRect(startX + space, space, sliderWidth , sliderHeight);
        painter->drawRoundedRect(sliderRect, rectRadius, rectRadius);
    } else if (buttonStyle == ButtonStyle_CircleIn) {
        QRect rect(0, 0, width(), height());
        int sliderWidth = rect.height() - space * 2;
        QRect sliderRect(startX + space, space, sliderWidth, sliderWidth);
        painter->drawEllipse(sliderRect);
    } else if (buttonStyle == ButtonStyle_CircleOut) {
        QRect rect(0, 0, width() - space, height() - space);
        int sliderWidth = rect.height();
        QRect sliderRect(startX, space / 2, sliderWidth, sliderWidth);
        painter->drawEllipse(sliderRect);
    }

    painter->restore();
}

void SwitchButton::drawText(QPainter *painter)
{
    painter->save();

    if (!checked) {
        painter->setPen(textColorOff);
        painter->drawText(width() / 2, 0, width() / 2 - space, height(), Qt::AlignCenter, textOff);
    } else {
        painter->setPen(textColorOn);
        painter->drawText(0, 0, width() / 2 + space * 2, height(), Qt::AlignCenter, textOn);
    }

    painter->restore();
}

void SwitchButton::drawImage(QPainter *painter)
{
    painter->save();

    QPixmap pix;

    if (!checked) {
        pix = QPixmap(imageOff);
    } else {
        pix = QPixmap(imageOn);
    }

    //自动等比例平滑缩放居中显示
    int targetWidth = pix.width();
    int targetHeight = pix.height();
    pix = pix.scaled(targetWidth, targetHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    int pixX = rect().center().x() - targetWidth / 2;
    int pixY = rect().center().y() - targetHeight / 2;
    QPoint point(pixX, pixY);
    painter->drawPixmap(point, pix);

    painter->restore();
}

void SwitchButton::updateValue()
{
    if (checked) {
        if (startX < endX) {
            startX = startX + step;
        } else {
            startX = endX;
            timer->stop();
        }
    } else {
        if (startX > endX) {
            startX = startX - step;
        } else {
            startX = endX;
            timer->stop();
        }
    }

    update();
}

void SwitchButton::setChecked(bool checked)
{
    if (this->checked != checked) {
        this->checked = checked;
        emit checkedChanged(checked);
        update();
    }
}

void SwitchButton::setButtonStyle(SwitchButton::ButtonStyle buttonStyle)
{
    this->buttonStyle = buttonStyle;
    update();
}

void SwitchButton::setBgColor(QColor bgColorOff, QColor bgColorOn)
{
    this->bgColorOff = bgColorOff;
    this->bgColorOn = bgColorOn;
    update();
}

void SwitchButton::setSliderColor(QColor sliderColorOff, QColor sliderColorOn)
{
    this->sliderColorOff = sliderColorOff;
    this->sliderColorOn = sliderColorOn;
    update();
}

void SwitchButton::setTextColor(QColor textColorOff, QColor textColorOn)
{
    this->textColorOff = textColorOff;
    this->textColorOn = textColorOn;
    update();
}

void SwitchButton::setText(QString textOff, QString textOn)
{
    this->textOff = textOff;
    this->textOn = textOn;
    update();
}

void SwitchButton::setImage(QString imageOff, QString imageOn)
{
    this->imageOff = imageOff;
    this->imageOn = imageOn;
    update();
}

void SwitchButton::setSpace(int space)
{
    this->space = space;
    update();
}

void SwitchButton::setRectRadius(int rectRadius)
{
    this->rectRadius = rectRadius;
    update();
}

Este control personalizado está integrado en QFramework.

Introducción a QFramework:

QFramework es un conjunto de marco general de desarrollo de programas Qt, diseño de interfaz principal integrado, varios controles personalizados, procesamiento de base de datos, exportación de velocidad de Excel, impresión de datos, comunicación en serie, comunicación en red, análisis de protocolo, teclas de acceso rápido globales, envío de correo electrónico, envío de SMS, mapa de Baidu llamada, procesamiento ffmpeg+vlc y otras funciones, las funciones de uso común se empaquetan en una biblioteca de clases, proporcionando una interfaz de llamada unificada e intuitiva, que es conveniente para los usuarios, y la biblioteca empaquetada correspondiente tiene un programa de demostración correspondiente.

Funciones básicas de QFramework:

1: admite cualquier versión de Qt de 4.7.0 a 5.7.0, sin restricciones de versión. Con este marco, no habrá más molestias de que el programa no se pueda compilar debido a las diferentes versiones de Qt.

2: exporte datos para sobresalir a una velocidad muy alta, admita datos de tablas o datos de consulta, no confíe en ningún componente, admita cualquier excel, wps y otras versiones de software de tablas, exporte 100,000 filas de datos y 8 campos solo necesitan 3 segundos para completo. El título principal y el subtítulo se pueden personalizar para el estilo de tabla exportado, y los datos exportados se pueden resaltar en rojo según las condiciones especificadas.

3: exportación de datos a pdf y funciones de impresión, datos de formulario de soporte o datos de consulta, soporte de impresión horizontal y vertical, paginación automática.

4: clase dbapi de paginación de datos, simplemente pase el objeto de la tabla, el nombre de la tabla y el botón de cambio de página. No es necesario escribir métodos repetidos para manejar el cambio de página.

5: varios controles personalizados, como botones de interruptor, botones luminosos, controles de tablero, controles de volumen, controles de temperatura y humedad, controles de instrumentos, etc.

6: El nuevo método de entrada Super Chinese-English Shuangpin es muy adecuado para dispositivos táctiles.

7: Procesamiento global de teclas de acceso directo.

8: Impresión de impresora térmica de puerto serie.

9: dibujo de curva de gráficos 2D qcustomplot (incluido el seguimiento de datos del mouse).

10: envío de correo multiproceso, admite múltiples buzones de recepción.

11: envío de SMS multihilo, compatible con múltiples números de recepción y SMS largos.

12: Procesamiento de video Qffmpeg+Qvlc.

13: toma fuentes, convierte caracteres en procesamiento de datos LED.

14: Applog de clase de salida de registro global, que se puede montar y desinstalar dinámicamente.

15: Clave de aplicación de clase de control de programa global, que puede controlar el tiempo de uso, el tiempo de ejecución, el límite de la cantidad de dispositivos, etc. del programa.

16: Encapsule la interfaz de llamada de mapa de Baidu, admita el etiquetado de dispositivos, consulte la ruta, muestre la ubicación, etc.

17: La primera clase de datos cleanapi del programa de limpieza automática, simplemente ingrese el nombre de la tabla de la base de datos que se va a limpiar, el intervalo de ejecución y la cantidad máxima de registros retenidos. Esto asegura que todo el sistema almacene los datos más recientes.

18: Programa de servicio de tiempo escolar NTP.

19: procesamiento de captura de pantalla global, es muy conveniente capturar directamente el programa en el ARM.

20: Applive, la función de detección de supervivencia del programa, envía comandos de latidos del corazón en tiempo real a través de la comunicación udp, de modo que el programa puede ejecutarse 7*24 horas, y el programa de vigilancia appdog se puede usar en ARM.

21: tiempo de ejecución transcurrido + tiempo actual + uso de CPU en tiempo real + uso de memoria en tiempo real, etc.

22: Personaliza la información en la parte inferior de la interfaz principal del programa.

23: Uso interactivo de gráficos Echart.

Los beneficios de este artículo, gratis para recibir el paquete de materiales de aprendizaje de desarrollo Qt, video técnico, que incluye (base del lenguaje C ++, patrón de diseño C ++, introducción a la programación Qt, mecanismo de señal y ranura QT, dibujo de imagen de desarrollo de interfaz QT, red QT, QT programación de base de datos, combate real del proyecto QT, QSS, OpenCV, módulo rápido, preguntas de la entrevista, etc. )

Supongo que te gusta

Origin blog.csdn.net/m0_73443478/article/details/131014220
Recomendado
Clasificación