【Qt】自定义控件

        在实际的项目开发中,通常情况下使用QSS即可改变原生控件外观,而QSS是通过Qt的样式引擎解析并设置样式参数,在paintEvent中通过这些样式参数绘制的。尽管如此,Qt的原生控件或许仍旧满足不了我们的需求,所以经常会遇到需要自定义控件的场合。例如需要一个开关样式的按钮,Qt中并没有提供。下面就分享一下Qt自定义控件的一些方法。

自定义控件的方法

        在Qt中自定义控件的方法有多种,常用的方法有:

1.组合控件

        顾名思义,组合控件就是将多个控件元素组合为一个整体,然后以这个整体为单位进行界面编程。

        下面是一个非常简单的组合控件的示例,他将一个标签控件和按钮控件组合为一个整体:

#include 

class MyCustomWidget : public QWidget {
public:
    MyCustomWidget(QWidget *parent = nullptr) : QWidget(parent) {
        QLabel *label = new QLabel("Hello, World!");
        QPushButton *button = new QPushButton("Click Me");

        QVBoxLayout *layout = new QVBoxLayout();
        layout->addWidget(label);
        layout->addWidget(button);
        setLayout(layout);

        connect(button, &QPushButton::clicked, this, &MyCustomWidget::onButtonClicked);
    }

private slots:
    void onButtonClicked() {
        qDebug() << "Button clicked!";
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    MyCustomWidget widget;
    widget.show();

    return app.exec();
}

        以上代码,是一个非常简单的组合控件示例,在点击按钮时可以更改标签控件的文字。如果做更复杂的组合控件,或许需要将内部控件的一些公共方法提取到该组合控件中,或者需要自定义信号等等。

2.自行绘制控件

        自行绘制控件相较于组合控件稍微复杂些,至少需要自行实现绘图事件。根据实际情况选择需要继承的基类,一般情况下继承QWidget,QWidget是所有界面类的基类。当然,也可以继承QPushButton、QLabel等等控件,根据实际情况而定。

        下面是通过继承QWidget自定义电池的示例代码。

        头文件: 

class PowerFrame:public QWidget{
    Q_OBJECT
public:
    explicit PowerFrame(QWidget* parent=nullptr);
    ~PowerFrame();
    void setPower(int power);
    void setCharge(bool isCharging);
protected:
    void paintEvent(QPaintEvent *) override;
private:
    ColorChange* colorChange;
    QString _startColor="#FF0000";
    QString _endColor="#00FF00";
    QString _borderColor = "#818181";
    QString _charingColor = "#FFFFFF";
    int _min=0;
    int _max=100;
    int _currentNum;
    RGB_COLOR _currentColor;
    bool _isCharging = false;
};

源文件 

PowerFrame::PowerFrame(QWidget* parent):QWidget(parent){
    colorChange = new ColorChange();
    colorChange->setRange(_min,_max);
    colorChange->setStartColor(_startColor);
    colorChange->setEndColor(_endColor);
}
PowerFrame::~PowerFrame(){
    delete colorChange;
}
void PowerFrame::setPower(int currentNum){
    if(currentNum>=0&¤tNum<=100){
        _currentNum = currentNum;
        _currentColor = colorChange->getColor(currentNum);
        update();
    }
}
void PowerFrame::setCharge(bool isCharging){
    _isCharging = isCharging;
    update();
}
void PowerFrame::paintEvent(QPaintEvent *){
    setFixedSize(height()*2.3,height());
    QPainter painter(this);
    painter.save();
    painter.setRenderHint(QPainter::Antialiasing,true);
    QPen pen;
    pen.setColor(QColor(_borderColor));
    pen.setWidthF(2);
    painter.setPen(pen);
    QRectF re(1,1,rect().width()-5,rect().height()-2);
    painter.drawRoundedRect(re,2,2);
    painter.setBrush(QBrush(QColor(_borderColor)));
    painter.setPen(Qt::NoPen);
    QRectF re1(rect().width()-4,(height()-10)/2.0,4,10);
    painter.drawRoundedRect(re1,2,2);
    painter.setBrush(QBrush(QColor(_currentColor.r,_currentColor.g,_currentColor.b)));
    QRectF re2(3,3,(rect().width()-9)/100.0*_currentNum,rect().height()-6);
    painter.drawRoundedRect(re2,2,2);
    if(_isCharging){
        double w = width()-5;
        QPointF robotArrow[6]={
            QPointF(w/4.0*2,height()/5.0),
            QPointF(w/4.0*2,height()/5.0*2),
            QPointF(w/4.0*3,height()/5.0),
            QPointF(w/4.0*2,height()/5.0*4),
            QPointF(w/4.0*2,height()/5.0*3),
            QPointF(w/4.0,height()/5.0*4),
        };
        painter.setBrush(QBrush(QColor(_charingColor)));
        painter.drawPolygon(robotArrow,6);
    }
    painter.restore();
}

        上面是一个非常简单的绘制电池电量控件的代码。比较遗憾的是,该示例中并没有自定义信号,并发射它。通常来说,自定义控件都会需要定义至少一个信号,用于向外界传递该控件一些状态的变化。另外该类的成员变量ColorChange指针,为颜色渐变类的指针;RGB_COLOR为存储RGB值的结构体。

3.以上两种结合

        可以参考自定义标题栏文章:

        链接:【Qt】自定义标题栏_qmainwindow自定义标题栏_卡钦斯基的博客-CSDN博客

你可能感兴趣的:(qt,开发语言)