Как перерисовать кнопку в Qt?
Хочу вывести кнопку которая будет иметь стандартный функционал кнопки (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()
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.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;
}
mainwindow.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
custombutton.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;
}
custombutton.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
Ответы (1 шт):
Автор решения: timob256
→ Ссылка
Вот тут дали отличный ответ :
вот пример :
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()
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.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
mainwindows.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();
}
}

