Qt はカスタムのコントロール スイッチ ボタンを作成します

携帯電話の APP には人気の要素がたくさんあります。スイッチ ボタンがとても気に入っています。Mobile QQ、360 Guards、Jinshan Duba などにはすべて、いくつかの操作を制御するための多くのスイッチがあります。Qt ウィジェット アプリケーション プロジェクトでは、いくつかのスイッチを適用しますプロジェクト内に同様のスイッチ ボタンを追加すると、プロジェクトに新鮮さがさらに増すと予想されます。

ほとんどのスイッチ ボタン コントロールを要約すると、基本的に 2 つのカテゴリがあり、最初のカテゴリは純粋なコード描画です。この種のコードの制御は比較的高度ですが、柔軟性はより優れています。2 番目のカテゴリはテクスチャで、プロのアーティストが用意したさまざまな状態の背景画像であり、コードを使用してインターフェイス上に画像を描画するだけで済みます。2 種類のスイッチ ボタンをカバーするために、一般的な 4 種類 (角丸長方形/内側の円/外側の円/絵) が意図的にカスタム スイッチ ボタンに統合されています。

実行結果:

この記事の特典として、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、C++ デザイン パターン、Q​​t プログラミング入門、QT シグナルとスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT など) を無料で受け取ることができます。データベースプログラミング、QTプロジェクト実戦、QSS、OpenCV、Quickモジュール、面接での質問など) ↓↓↓↓下記参照↓↓料金受け取りは記事下部をクリック↓↓

1: 純粋なコード描画

純粋なコードは、さまざまな色、間隔、テキストなどを柔軟に設定できるスイッチ ボタンを描画し、過剰なアニメーション スライド効果を生成することもできます。

スライド効果は、スライダーの X 軸開始座標を自動的に計算し、スライダーの X 軸開始座標がスライダーの X 軸終了座標に達したときにタイマーを停止するタイマー描画方法を使用して生成されます。

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:テクスチャ描画

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();
}

完全なコード:

スイッチボタン.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

スイッチボタン.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();
}

このカスタム コントロールは QFramework に統合されています。

QFramework の概要:

QFramework は一般的な Qt プログラム開発フレームワークで、メイン インターフェイス レイアウト、さまざまなカスタム コントロール、データベース処理、Excel エクスポート、データ印刷、シリアル通信、ネットワーク通信、プロトコル分析、グローバル ホットキー、電子メール送信、SMS 送信、Baidu マップ呼び出し、を統合しています。 ffmpeg+vlc 処理やその他の関数、一般的に使用される関数がクラス ライブラリにパッケージ化されており、ユーザーにとって使いやすい統一された直感的な呼び出しインターフェイスが提供されます。また、対応するパッケージ化されたライブラリには、対応するデモ プログラムが含まれています。

QFrameworkの基本機能:

1: バージョン制限なしで、4.7.0 から 5.7.0 までの Qt バージョンをサポートします。このフレームワークを使用すると、Qt のバージョンが異なるためにプログラムがコンパイルできないという煩わしさはもうなくなります。

2: 非常に高速でデータを Excel にエクスポートし、テーブル データまたはクエリ データをサポートします。コンポーネントに依存せず、Excel、WPS、その他のテーブル ソフトウェア バージョンをサポートします。100,000 行のデータと 8 つのフィールドのエクスポートに必要な時間はわずか 3 秒です。完了。エクスポートした表のスタイルに合わせてメインタイトルとサブタイトルをカスタマイズしたり、指定した条件に従ってエクスポートしたデータを赤色で強調表示したりすることができます。

3: PDF へのデータエクスポートと印刷機能、フォームデータまたはクエリデータのサポート、水平および垂直印刷、自動ページネーションのサポート。

4: データ ページング dbapi クラス。テーブル オブジェクト、テーブル名、ページめくりボタンを渡すだけです。ページめくりを処理するメソッドを繰り返し記述する必要はありません。

5: スイッチボタン、発光ボタン、ダッシュボードコントロール、音量コントロール、温度と湿度のコントロール、計器コントロールなどのさまざまなカスタムコントロール。

6: 新しいスーパー中国語-英語双ピン入力方法は、タッチ デバイスに非常に適しています。

7: グローバル ホットキー処理。

8: シリアルポートサーマルプリンター印刷。

9: qcustomplot 2D グラフィックス曲線描画 (マウス データ トラッキングを含む)。

10: マルチスレッドのメール送信、複数の受信メールボックスをサポートします。

11: マルチスレッド SMS 送信、複数の受信番号と長い SMS をサポートします。

12: Qffmpeg+Qvlc ビデオ処理。

13: フォントを取得し、文字を LED データ処理に変換します。

14: グローバル ログ出力クラス applog。動的にマウントおよびアンインストールできます。

15: グローバルプログラム制御クラスappkey。プログラムの使用時間、実行時間、デバイス数の制限などを制御できます。

16: Baidu マップ呼び出しインターフェイスをカプセル化し、デバイスのラベル付け、ルート クエリ、位置表示などをサポートします。

17: 自動クリーニング プログラムの初期のデータ クラス cleanapi は、クリーニングするデータベース テーブルの名前、実行間隔、および保持される最大レコード数を渡すだけです。これにより、システム全体に最新のデータが確実に保存されます。

18: NTPスクールタイムサービスプログラム。

19: グローバル スクリーンショット処理。ARM 上のプログラムを直接スクリーンショットするのに非常に便利です。

20: プログラム生存検出機能である Applive は、udp 通信を介してリアルタイムにハートビート コマンドを送信するため、プログラムを 7*24 時間実行でき、ARM 上でウォッチドッグ プログラム appdog を使用できます。

21: 実行経過時間 + 現在時刻 + リアルタイム CPU 使用率 + リアルタイム メモリ使用量など。

22: プログラムのメインインターフェイスの下部にある情報をカスタマイズします。

23: Echart チャートの対話型使用。

この記事の特典として、Qt 開発学習教材パッケージ、技術ビデオ (C++ 言語基礎、C++ デザイン パターン、Q​​t プログラミング入門、QT シグナルとスロット メカニズム、QT インターフェイス開発イメージ描画、QT ネットワーク、QT など) を無料で受け取ることができます。データベースプログラミング、QTプロジェクト実戦、QSS、OpenCV、Quickモジュール、面接での質問など) ↓↓↓↓下記参照↓↓料金受け取りは記事下部をクリック↓↓

おすすめ

転載: blog.csdn.net/m0_73443478/article/details/131014220