RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1425174
Accepted
timob256
timob256
Asked:2022-08-29 23:05:34 +0000 UTC2022-08-29 23:05:34 +0000 UTC 2022-08-29 23:05:34 +0000 UTC

如何在 Qt 中重绘按钮?

  • 772

我想显示一个按钮,它具有按钮的标准功能(QPushButton),但同时具有不同的外观

但是由于某种原因,他们不允许推断从 QPushButton 继承的类

在此处输入图像描述

这是代码(我无法弄清楚我做错了什么):

CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(myButton VERSION 0.1 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)

set(PROJECT_SOURCES
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
        custombutton.cpp
        custombutton.h
        lineitem.cpp
        lineitem.h
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(myButton
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
# Define target properties for Android with Qt 6 as:
#    set_property(TARGET myButton APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
#                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
else()
    if(ANDROID)
        add_library(myButton SHARED
            ${PROJECT_SOURCES}
        )
# Define properties for Android with Qt 5 after find_package() calls as:
#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
    else()
        add_executable(myButton
            ${PROJECT_SOURCES}
        )
    endif()
endif()

target_link_libraries(myButton PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

set_target_properties(myButton PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(myButton)
endif()

主文件

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
  

主窗口.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)

{
    _line = new lineItem(this);

    ui->setupUi(this);

    ui->gridLayout->addItem(_line);
}

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

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include "lineitem.h"


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    lineItem*  _line;

};
#endif // MAINWINDOW_H

    

自定义按钮.cpp

#include "custombutton.h"

customButton::customButton(QPushButton *parent)
    : QPushButton{parent}
{
    _myPushButton = qobject_cast<QPushButton*>(parent);
}

void customButton::setPosition(float radiusPos, float angle)
{

    if(radiusPos<0)
        _rPos = 0;
    else
        _rPos = radiusPos;

    if(angle>360)
        _angle = 360;
    else if(radiusPos<0)
        _angle = 0;
    else
        _angle = angle;

    _myPushButton->update();
}

QPointF customButton::getCenterPoint(float radPos, float angle)
{
    float r = getRadius(_myPushButton->rect());
    float xx=cos(qDegreesToRadians(angle+90))*r;
    float yy=sin(qDegreesToRadians(angle+90))*r;

    QPointF pt;
    xx=_myPushButton->rect().center().x()-xx*radPos;
    yy=_myPushButton->rect().center().y()-yy*radPos;
    pt.setX(xx);
    pt.setY(yy);
    return pt;
}


void customButton::setColors(const QColor &substrate, const QColor &item, const QColor &outline)
{
    _colorSubstrate = substrate;
    _colorItem = item;
    _colorOutline = outline;
}

void customButton::setValueRange(float minValue, float maxValue)
{
    _minValue = minValue;
    _maxValue = maxValue;
}

void customButton::setDegreeRange(float minDegree, float maxDegree)
{
    _minDegree = minDegree;
    _maxDegree = maxDegree;
}

void customButton::setSubstrate(bool val)
{
    _drawSubstrate = val;
}

void customButton::setThicknessOutline(float val)
{
    _thicknessOutline = val;
}

void customButton::setOutline(bool val)
{
    _drawOutline = val;
}

void customButton::setShadow(bool val)
{
    _drawShadow = val;
}

float customButton::getRadius(const QRectF &tmpRect)
{
    float r = 0;
    if(tmpRect.width() < tmpRect.height()*_wh)
        r = tmpRect.width()/(2.0*_wh);
    else
        r = tmpRect.height()/2.0;
    return r;
}

float customButton::getDegFromValue(float val)
{
    float a = (_maxDegree-_minDegree)/(_maxValue-_minValue);
    float b = -a*_minValue+_minDegree;
    return a*val+b;
}

void customButton::setScaleFactor(float val)
{
    _scaleFactor = val;
}

void customButton::setThickness(float val)
{
    _thickness = val;
}

void customButton::setProportions(float wh)
{
    _wh = wh;
}
    

自定义按钮.h

#ifndef BUTTONITEM_H
#define BUTTONITEM_H

#include <QObject>
#include <QButtonGroup>
#include <QPushButton>

#include <QPainter>
#include <QColor>
#include <QFont>
#include <QDebug>

#include <QPainterPath>
#include <QPointF>
#include <QRect>
#include <QGraphicsBlurEffect>
#include <QGraphicsItem>
#include <QtMath>
#include <QMessageBox>

class customButton : public QPushButton
{

public:
    explicit customButton(QPushButton *parent = nullptr);

    virtual void draw(QPainter *p) = 0;

    ///
    /// \brief setPosition установить радиус (1=100%) и угол (в градусах) определяющий расположение item на виджете
    ///
    void setPosition(float radiusPos , float angle);

    ///
    /// \brief getPoint расчитать центральную точку
    ///
    QPointF getCenterPoint(float radPos, float angle);

    ///
    /// \brief setColors: установить три цвета ( подложки, основной и обводки) для item
    ///
    void setColors(const QColor &substrate, const QColor &item, const QColor &outline);

    ///
    /// \brief setValueRange установить диапазон изменения значения
    ///
    void setValueRange(float minValue,float maxValue);

    ///
    /// \brief setDegreeRange установить диапазон изменения угла
    ///
    void setDegreeRange(float minDegree,float maxDegree);

    /// inner function

    ///
    /// \brief включить отрисовку подложки с заданным ранее цветом и прозрачностью
    ///
    void setSubstrate(bool val);

    ///
    /// \brief setThicknessOutline установить толщину обводки
    ///
    void setThicknessOutline(float val);

    ///
    /// \brief включить отрисовку подложки с заданным ранее цветом и прозрачностью
    ///
    void setOutline(bool val);

    ///
    /// \brief включить отрисовку "тени"
    ///
    void setShadow(bool val);

    ///
    /// \brief getRadius получить радиус окружности в которую вписан заданный прямоугольник
    ///
    float getRadius(const QRectF &tmpRect);

    ///
    /// \brief getDegFromValue
    ///
    float getDegFromValue(float val);

    ///
    /// \brief setScaleFactor установить коэффициент масштаба
    ///
    void setScaleFactor(float val);

    ///
    /// \brief setThickness установить толщину линии
    ///
    void setThickness(float val);

    ///
    /// \brief setProportions задать соотношение ширины к высоте в виджете с данным item
    ///
    void setProportions(float wh);

//    QWidget *_parentWidget;
    QPushButton *_myPushButton;


    QColor   _colorSubstrate    {Qt::black};
    QColor   _colorItem         {Qt::black};
    QColor   _colorOutline      {Qt::white};
    QColor   _colorCornerBound  {Qt::darkRed};

    QColor   _colorShadowB      {Qt::black};
    QColor   _colorShadowW      {Qt::white};

    QColor   _colorKaracurtWhite  {255, 255, 255, 255};
    QColor   _colorKaracurtYellow {255, 255,  0 , 255};
    QColor   _colorKaracurtSubstrate { 0, 0,  0 , 128};
    QColor   _colorKaracurtShadow { 0 ,  0 ,  0 , 200};


    float    _thicknessOutline  {5};
    float    _thickness         {3};

    float    _scaleFactor       {1};

    float    _rPos              {0.5};
    float    _angle             {0.5};

    float    _minValue          {0};
    float    _maxValue          {100};
    float    _minDegree         {0};
    float    _maxDegree         {360};

    bool     _drawSubstrate     {false};
    bool     _drawOutline       {false};
    bool     _drawShadow        {false};

    float    _wh                {1};


signals:

};

#endif // BUTTONITEM_H

    

lineitem.cpp

#include "lineitem.h"

lineItem::lineItem(QPushButton *parent)
    : customButton(parent)
{

}

void lineItem::draw(QPainter *p)
{
    p->save();

    QPointF center = getCenterPoint(_rPos, _angle);
    float r = getRadius(_myPushButton->rect())*_scaleFactor;

    if(_drawSubstrate)
    {
        p->setBrush(QBrush(_colorSubstrate));
        p->drawEllipse(center,(int)(r), (int)(r));
    }

    p->translate(center);

    p->setPen(Qt::NoPen);
    p->setBrush(QBrush(_color));
    p->drawRect(-r/1.5, -r/1.5, r*1.34, r*1.34);


    QVector<QPointF> tmpPoints;
    tmpPoints.append(QPointF(0.0 - r*0.46 , 0.0 + r*0.2 ));
    tmpPoints.append(QPointF(0.0 - r*0.36 , 0.0 + r*0.2 ));

    tmpPoints.append(QPointF(0.0 - r*0.26 , 0.0 - r*0.15 ));
    tmpPoints.append(QPointF(0.0 - r*0.06 , 0.0 + r*0.45 ));

    tmpPoints.append(QPointF(0.0 + r*0.06 , 0.0 - r*0.4  ));
    tmpPoints.append(QPointF(0.0 + r*0.26 , 0.0 + r*0.25 ));

    tmpPoints.append(QPointF(0.0 + r*0.36 , 0.0 + r*0.1 ));
    tmpPoints.append(QPointF(0.0 + r*0.46 , 0.0 + r*0.1 ));

    QPainterPath path;
    path.addPolygon(tmpPoints);

    p->setBrush(Qt::NoBrush);
    p->setPen(QPen(_color_line, 2*_thickness, Qt::SolidLine));
    p->drawPath(path);

    p->restore();
}
    

lineitem.h

#ifndef LINEITEM_H
#define LINEITEM_H

#include "custombutton.h"

class lineItem : public customButton
{
public:
    lineItem();

    explicit lineItem(QPushButton *parent = nullptr);

    virtual void draw(QPainter * p) override final;

    private:

        QColor   _color        {220, 0, 0, 227};
        QColor   _color_line {255,255,255,255};
};
#endif // LINEITEM_H
qt
  • 1 1 个回答
  • 33 Views

1 个回答

  • Voted
  1. Best Answer
    timob256
    2022-09-07T02:08:38Z2022-09-07T02:08:38Z

    这是一个很好的答案:

    https://blog.altuninvv.ru/programming/qt5/widgets/153-create-slider-slider-slider-button-in-qt5

    这是一个例子:

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.5)
    
    project(myButton3 VERSION 0.1 LANGUAGES CXX)
    
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    
    set(CMAKE_AUTOUIC ON)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
    find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
    
    set(PROJECT_SOURCES
            main.cpp
            mainwindow.cpp
            mainwindow.h
            qsliderbutton.cpp
            qsliderbutton.h
            mainwindow.ui
    )
    
    if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
        qt_add_executable(myButton3
            MANUAL_FINALIZATION
            ${PROJECT_SOURCES}
        )
    # Define target properties for Android with Qt 6 as:
    #    set_property(TARGET myButton3 APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
    #                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
    # For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
    else()
        if(ANDROID)
            add_library(myButton3 SHARED
                ${PROJECT_SOURCES}
            )
    # Define properties for Android with Qt 5 after find_package() calls as:
    #    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
        else()
            add_executable(myButton3
                ${PROJECT_SOURCES}
            )
        endif()
    endif()
    
    target_link_libraries(myButton3 PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
    
    set_target_properties(myButton3 PROPERTIES
        MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
        MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
        MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    )
    
    if(QT_VERSION_MAJOR EQUAL 6)
        qt_finalize_executable(myButton3)
    endif()
    

    主文件

    #include "mainwindow.h"
    
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
        return a.exec();
    }
    

    主窗口.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QVBoxLayout>
    #include "qsliderbutton.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindow; }
    QT_END_NAMESPACE
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private:
        Ui::MainWindow *ui;
    
        QSliderButton *sldBtn;
    };
    #endif // MAINWINDOW_H
    

    主窗口.cpp

    #include "mainwindow.h"
    #include "./ui_mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
        , ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        QVBoxLayout *vlay = new QVBoxLayout();
        QHBoxLayout *hlay1 = new QHBoxLayout();
    
        sldBtn =  new QSliderButton;
        hlay1->addWidget(sldBtn);
    
        hlay1->addStretch(1);
        vlay->addItem(hlay1);
    
        vlay->addStretch(1);
        ui->centralwidget->setLayout(vlay);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    qsliderbutton.h

    #ifndef QSLIDERBUTTON_H
    #define QSLIDERBUTTON_H
    
    #include <QWidget>
    #include <QMouseEvent>
    #include <QDebug>
    
    
    class QSliderButton : public QWidget {
        Q_OBJECT
    public:    
        explicit QSliderButton(QWidget* parent);
        QSliderButton();
    
    
        int getStatus() const;
        void setStatus(int value);
    
        static const int off = 0;
        static const int on  = 1;
    
    private:
        int status = 0;
    
    protected:
        virtual void paintEvent(QPaintEvent *event);
        virtual QSize sizeHint() const;
        virtual void mousePressEvent(QMouseEvent * event);
    
    };
    
    #endif // QSLIDERBUTTON_H
    

    qsliderbutton.cpp

    #include "qsliderbutton.h"
    #include <QPainter>
    
    QSliderButton::QSliderButton(QWidget *parent)
    {
        this->setParent(parent);
    }
    
    QSliderButton::QSliderButton()
    {
    }
    
    int QSliderButton::getStatus() const
    {
        return status;
    }
    
    void QSliderButton::setStatus(int value)
    {
        status = value;
        repaint();
    }
    
    void QSliderButton::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
    
        painter.setRenderHint(QPainter::Antialiasing, true);
    
        painter.setPen(QPen(QColor("#fff"), 0.1));
    
        QString bgColorTxt = "#ffffff";
        QColor bgColor = QColor(bgColorTxt);
    
        painter.setBrush(bgColor);
    
        painter.drawRoundedRect(QRectF(0, 0, 50, 20),10,10);
    
        QLinearGradient linearGradBtn(QPointF(0, 0),QPointF(16, 16));
    
        QString onColor = "#444";
        QColor mainColorOn = QColor(onColor);
        QColor subColorOn = QColor(onColor);
        subColorOn.setHsl(0,100,95,0);
    
    
        if (this->status==QSliderButton::on) {
            QLinearGradient linearGrad(QPointF(32, 2), QPointF(46, 16));
            linearGrad.setColorAt(0, subColorOn);
            linearGrad.setColorAt(1, mainColorOn);
    
            painter.setBrush(linearGrad);
    
            painter.drawEllipse( QRectF(30, 2, 17, 16) );
        } else {
            QLinearGradient linearGrad(QPointF(2, 2), QPointF(16, 16));
            linearGrad.setColorAt(0, subColorOn);
            linearGrad.setColorAt(1, mainColorOn);
    
            painter.setBrush(linearGrad);
    
            painter.drawEllipse( QRectF(2, 2, 16, 16) );
        }
    }
    QSize QSliderButton::sizeHint() const {
        return QSize(50, 20);
    }
    
    void QSliderButton::mousePressEvent(QMouseEvent *event)
    {
        if (event->button() == Qt::LeftButton ) {
            if (this->status==QSliderButton::on) {
                this->status = QSliderButton::off;
            } else {
                this->status = QSliderButton::on;
            }
            repaint();
        }
    }
    

    在此处输入图像描述

    • -1

相关问题

  • 在 Windows 7 上将文件连接到 Qt 项目时出现问题

  • QGraphicsView - Qt5 - MouseMoveEvent 没有触发?

  • 如何在背景中添加屏幕保护程序

  • 如何更改包含的 .ttf 字体的大小

  • QString("%1").arg(number + 1) 以 %03d 格式打印数字

  • QT Creator,信号和插槽 [关闭]

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5