首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Qt实现切换按钮

使用Qt实现切换按钮
EN

Code Review用户
提问于 2020-09-08 11:40:14
回答 1查看 1.2K关注 0票数 2

下面是实现切换按钮的代码。

在包含以下代码之后,在我的嵌入式应用程序中,处理能力消耗了90%以上。有没有办法降低这种处理能力。

ToggleButton.h

代码语言:javascript
运行
复制
#ifndef TOGGLEBUTTON_H
#define TOGGLEBUTTON_H

#include <QtWidgets/QAbstractButton>


class QPropertyAnimation;

class ToggleButton :public QAbstractButton
{
    Q_OBJECT
        Q_PROPERTY(int mOffset READ offset WRITE setOffset);
public:
    explicit ToggleButton(int trackRadius, int thumbRadius, QWidget* parent = nullptr);
    ~ToggleButton();

    QSize sizeHint() const override;

protected:
    void paintEvent(QPaintEvent *) override;
    void resizeEvent(QResizeEvent*) override;
    void mouseReleaseEvent(QMouseEvent  *) override;
    void enterEvent(QEvent *event) override;
    void setChecked(bool checked);

    int offset();
    void setOffset(int value);

private:
    qreal mOffset;
    qreal mBaseOffset;
    qreal mMargin;
    qreal mTrackRadius;
    qreal mThumbRadius;
    qreal mOpacity;
    QPropertyAnimation* mAnimation;

    QHash<bool, qreal> mEndOffset;
    QHash<bool, QBrush> mTrackColor;
    QHash<bool, QBrush> mThumbColor;
    QHash<bool, QColor> mTextColor;
    QHash<bool, QString> mThumbText;

};

#endif // TOGGLEBUTTON_H

ToggleButton.cpp

代码语言:javascript
运行
复制
#include "toggleButton.h"
#include <QtCore/QEvent>
#include <QtCore/QCoreApplication>
#include <QtCore/QPropertyAnimation> 
#include <QtGui/QPainter> 
#include <QtGui/QMouseEvent> 

///<summary>
/// Toggle button has 2 different design. In the first design, if the ball (thumb) radius is 
/// larger than the slide (track) radius, a flat ball slides and colors from the slide according to 
/// the on / off situation. In the second design, if the ball radius is smaller than the slide radius, 
/// the ball moves according to the on / off status inside the slide and includes the check and uncheck marks.
///</summary>
ToggleButton::ToggleButton(int trackRadius, int thumbRadius, QWidget* parent)
    : QAbstractButton(parent)
{
    setCheckable(true);
    setSizePolicy(QSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed));
    mTrackRadius = trackRadius;
    mThumbRadius = thumbRadius;
    mAnimation = new QPropertyAnimation(this);
    mAnimation->setTargetObject(this);

    mMargin = 0 > (mThumbRadius - mTrackRadius) ? 0 : (mThumbRadius - mTrackRadius);
    mBaseOffset = mThumbRadius > mTrackRadius ? mThumbRadius : mTrackRadius;
    mEndOffset.insert(true, 4 * mTrackRadius + 2 * mMargin - mBaseOffset); // width - offset
    mEndOffset.insert(false, mBaseOffset);
    mOffset = mBaseOffset;
    QPalette palette = this->palette();

    if (mThumbRadius > mTrackRadius)
    {
        mTrackColor.insert(true, palette.highlight());
        mTrackColor.insert(false, palette.dark());
        mThumbColor.insert(true, palette.highlight());
        mThumbColor.insert(false, palette.light());
        mTextColor.insert(true, palette.highlightedText().color());
        mTextColor.insert(false, palette.dark().color());
        mThumbText.insert(true, "");
        mThumbText.insert(false, "");
        mOpacity = 0.5;
    }
    else
    {
        mTrackColor.insert(true, palette.highlight());
        mTrackColor.insert(false, palette.dark());
        mThumbColor.insert(true, palette.highlightedText());
        mThumbColor.insert(false, palette.light());
        mTextColor.insert(true, palette.highlight().color());
        mTextColor.insert(false, palette.dark().color());
        mThumbText.insert(true, QChar(0x2714)); // check character
        mThumbText.insert(false, QChar(0x2715)); // uncheck character
        mOpacity = 1.0;
    }
}


ToggleButton::~ToggleButton()
{
    delete mAnimation;
}

QSize ToggleButton::sizeHint() const
{
    int w = 4 * mTrackRadius + 2 * mMargin;
    int h = 2 * mTrackRadius + 2 * mMargin;

    return QSize(w, h);
}

void ToggleButton::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    QPainter::RenderHints m_paintFlags = QPainter::RenderHints(QPainter::Antialiasing |
        QPainter::TextAntialiasing);
    p.setRenderHints(m_paintFlags, true);
    p.setPen(Qt::NoPen);
    bool check = isChecked();
    qreal trackOpacity = mOpacity;
    qreal textOpacity = 1.0;
    qreal thumbOpacity = 1.0;
    QBrush trackBrush;
    QBrush thumbBrush;
    QColor textColor;

    if (this->isEnabled())
    {

        trackBrush = mTrackColor[check];
        thumbBrush = mThumbColor[check];
        textColor = mTextColor[check];
    }
    else
    {
        trackOpacity *= 0.8;
        trackBrush = this->palette().shadow();
        thumbBrush = this->palette().mid();
        textColor = this->palette().shadow().color();
    }

    p.setBrush(trackBrush);
    p.setOpacity(trackOpacity);
    p.drawRoundedRect(mMargin, mMargin, width() - 2 * mMargin, height() - 2 * mMargin, mTrackRadius, mTrackRadius);

    p.setBrush(thumbBrush);
    p.setOpacity(thumbOpacity);
    p.drawEllipse(mOffset - mThumbRadius, mBaseOffset - mThumbRadius, 2 * mThumbRadius, 2 * mThumbRadius);

    p.setPen(textColor);
    p.setOpacity(textOpacity);
    QFont font = p.font();
    font.setPixelSize(1.5*mThumbRadius);
    p.setFont(font);


    // Since the antialiasasing provided by the drawText function is incompetent,
    // DrawPath function preferred. But since the drawPath function is not capable of aligment,
    // Pixel offsets calculated to provide aligment.
    QPainterPath textPath;
    qreal pixelOffset = (qreal)mThumbRadius * (1 - 1 / 1.414);
    textPath.addText(mOffset - mThumbRadius + pixelOffset, mBaseOffset + mThumbRadius - pixelOffset, font, mThumbText.value(check));
    p.drawPath(textPath);
   mAnimation->setDuration(100);
   if(mAnimation->state() != mAnimation->Running)
   {
     mAnimation->setPropertyName("mOffset");
   }
   mAnimation->setStartValue(mOffset);
   mAnimation->setEndValue(mEndOffset[isChecked()]);
   mAnimation->start();


    /*p.drawText(QRectF(mOffset - mThumbRadius,
        mBaseOffset - mThumbRadius,
        2 * mThumbRadius,
        2 * mThumbRadius),
        Qt::AlignCenter,
        mThumbText.value(check));*/
}

void ToggleButton::resizeEvent(QResizeEvent* e)
{
    QAbstractButton::resizeEvent(e);
    mOffset = mEndOffset.value(isChecked());
}

void ToggleButton::mouseReleaseEvent(QMouseEvent  *e)
{
    QAbstractButton::mouseReleaseEvent(e);
    if (e->button() == Qt::LeftButton)
    {
        mAnimation->setDuration(120);
        mAnimation->setPropertyName("mOffset");
        mAnimation->setStartValue(mOffset);
        mAnimation->setEndValue(mEndOffset[isChecked()]);
        mAnimation->start();
    }
}

void ToggleButton::enterEvent(QEvent * event)
{
    setCursor(Qt::PointingHandCursor);
    QAbstractButton::enterEvent(event);
}

void ToggleButton::setChecked(bool checked)
{
    QAbstractButton::setChecked(checked);
    mOffset = mEndOffset.value(checked);
}

int ToggleButton::offset()
{
    return mOffset;
}

void ToggleButton::setOffset(int value)
{
    mOffset = value;
    update();
}

main.cpp

代码语言:javascript
运行
复制
#include "toggleButton.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QHBoxLayout>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget *widget = new QWidget;
    widget->setWindowFlags(Qt::FramelessWindowHint);
    QHBoxLayout layout;
    widget->setLayout(&layout);
    ToggleButton *toggleButton1 = new ToggleButton(10, 8);
    ToggleButton *toggleButton2 = new ToggleButton(10, 12);
    layout.addWidget(toggleButton1);
    layout.addWidget(toggleButton2);
    widget->show();
    return a.exec();
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-09-14 08:40:24

由于mAnimation在paintEvent()方法中需要更多的处理。因此,从paintEvent()中删除Create动画。

只在mouseReleaseEvent()方法中生成动画。

代码语言:javascript
运行
复制
 mAnimation->setDuration(100);
 if(mAnimation->state() != mAnimation->Running)
 {
    mAnimation->setPropertyName("mOffset");
 }
 mAnimation->setStartValue(mOffset);
 mAnimation->setEndValue(mEndOffset[isChecked()]);
 mAnimation->start();
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/249076

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档