重写QComboBox

效果:

cpp 复制代码
//头文件
#ifndef CUTOMCOMBOBOX_H
#define CUTOMCOMBOBOX_H
#include <QObject>
#include <QWidget>
#include <QComboBox>
#include <QEvent>
#include <QListWidget>
#include <QPushButton>
#include <QVBoxLayout>
class CutomComboBox;
class CustomFrame : public QFrame
{
    Q_OBJECT
public:
    CustomFrame(QWidget* parent = nullptr);
    void popShow();
    void setItemList(const QStringList &value);
protected:
    bool eventFilter(QObject *obj, QEvent *event) override;

signals:
    void sendIndex(int index);
private:
    bool isDropDown = false;
    QStringList itemList;
    int curIndex = 0;
#define FRAME_QSS R"(QFrame { border-radius: 100px; background-color: white; border:none;})"
#define BTNSEL_QSS R"(
    QPushButton:hover{background-color:#f5f7fa;border:none;font-family:Arial;font-size: 15px; font-weight: bold; }
    QPushButton{background-color:#f5f7fa;color:#409eff;border:none;font-family:Arial;font-size: 15px;font-weight: bold; }
    )"
#define BTNUNSET_QSS R"(
    QPushButton:hover{background-color:#f5f7fa;border:none;font-family:Arial;font-size: 15px;font-weight: bold; }
    QPushButton{background-color:#ffffff;color:black;border:none;font-family:Arial;font-size:15px;font-weight: bold; }
    )"
};

class CutomComboBox : public QComboBox
{
    Q_OBJECT
public:
    CutomComboBox(QWidget *parent = nullptr);
public slots:
    void setList(QStringList list);
protected:
    void paintEvent(QPaintEvent *e) override;
    void enterEvent(QEvent *event) override;
    void leaveEvent(QEvent *event) override;
    void showPopup() override;
private:
    bool isHover = false;
    bool isDropDown = false;
    int  itemH = 10;
    CustomFrame popFrame;
    void drawOutLine(QPainter* painter);
    void drawText(QPainter* painter);
    void drawArrow(QPainter* painter, bool up);
#define DROPTRI_QSS R"(
    QComboBox {
    border: 1px solid gray;
    border-radius: 5px;
    padding: 5px;
    background-color: white;
    }
    QComboBox::drop-down {
    border: none;
    width: 30px;
    background: transparent;
    }
    QComboBox::down-arrow {
    image: url(':/png/png/drop-down.png');
    width: 15px;
    height: 15px;
    }
    )"
};

#endif // CUTOMCOMBOBOX_H
cpp 复制代码
//源文件
#include "cutomcombobox.h"
#include <QPainter>
#include <QDebug>
#include <QPropertyAnimation>
#include <QMetaObject>

CutomComboBox::CutomComboBox(QWidget *parent):QComboBox(parent)
{
    this->setStyleSheet(DROPTRI_QSS);
    connect(&popFrame,&CustomFrame::sendIndex,[=](int index){
        this->setCurrentIndex(index);
    });
}

void CutomComboBox::setList(QStringList list)
{
    this->addItems(list);
    popFrame.setItemList(list);

}

void CutomComboBox::paintEvent(QPaintEvent *e)
{
    QComboBox::paintEvent(e);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    drawOutLine(&painter);
    drawText(&painter);
}

void CutomComboBox::enterEvent(QEvent *event)
{
    isHover = true;
    update();
    QComboBox::enterEvent(event);
}

void CutomComboBox::leaveEvent(QEvent *event)
{
    isHover = false;
    update();
    QComboBox::leaveEvent(event);
}

void CutomComboBox::showPopup()
{
    QPoint pos = this->mapToGlobal(QPoint(0, this->height()));
    popFrame.setFixedWidth(this->width());
    popFrame.move(pos);
    popFrame.popShow();
}

void CutomComboBox::drawOutLine(QPainter* painter)
{
    painter->save();
    QRect rect = this->rect();
    QColor clr = isHover?QColor("#409EFF"):Qt::gray;
    QPen pen(clr);
    pen.setWidth(1);
    painter->setPen(pen);
    painter->setBrush(QColor("#ffffff"));
    painter->drawRoundedRect(rect.adjusted(0, 0, -30,0), 1, 1);
    painter->restore();
}

void CutomComboBox::drawText(QPainter *painter)
{
    painter->save();
    QFont font("Arial", 10);
    painter->setFont(font);
    painter->setPen(QColor("#409eff"));
    QRect rect = this->rect();
    QString text = this->currentText();
    if(text.isEmpty()){
        text = "请输入内容";
        painter->setPen(Qt::gray);
    }
    QTextOption textOption;
    textOption.setAlignment(Qt::AlignCenter);
    painter->drawText(rect,text,textOption);
    painter->restore();
}


CustomFrame::CustomFrame(QWidget *parent):QFrame(parent)
{
    this->setFrameShape(QFrame::Panel);
    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setStyleSheet(FRAME_QSS);
    this->adjustSize();
    this->installEventFilter(this);
};


void CustomFrame::setItemList(const QStringList &value)
{
    itemList = value;
}

bool CustomFrame::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type()==QEvent::WindowDeactivate){
        this->hide();
    }
    return QFrame::eventFilter(obj,event);
};

void CustomFrame::popShow()
{
    if(this->layout()!=nullptr){
        delete this->layout();
    }
    QVBoxLayout* vLay = new QVBoxLayout;
    vLay->setContentsMargins(0,0,0,0);
    vLay->setSpacing(0);
    for(int c=0;c<itemList.size();++c){
        QPushButton* btn = new QPushButton(itemList.at(c));
        btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
        btn->setFixedHeight(60);
        btn->setFlat(true);
        if(c==curIndex){
            btn->setStyleSheet(BTNSEL_QSS);
        }else
        {
            btn->setStyleSheet(BTNUNSET_QSS);
        }
        connect(btn,&QPushButton::clicked,[=](){
            this->curIndex = c;
            emit sendIndex(c);
            this->hide();
            isDropDown = false;
        });
        vLay->addWidget(btn);
    }
    this->setLayout(vLay);
    this->show();
    isDropDown = true;
}
相关推荐
Ciderw5 分钟前
Go中的三种锁
开发语言·c++·后端·golang·互斥锁·
人才程序员2 小时前
【C++拓展】vs2022使用SQlite3
c语言·开发语言·数据库·c++·qt·ui·sqlite
OKkankan2 小时前
实现二叉树_堆
c语言·数据结构·c++·算法
Ciderw3 小时前
MySQL为什么使用B+树?B+树和B树的区别
c++·后端·b树·mysql·面试·golang·b+树
yerennuo3 小时前
windows第七章 MFC类CWinApp介绍
c++·windows·mfc
ExRoc4 小时前
蓝桥杯真题 - 填充 - 题解
c++·算法·蓝桥杯
利刃大大4 小时前
【二叉树的深搜】二叉树剪枝
c++·算法·dfs·剪枝
肖田变强不变秃5 小时前
C++实现有限元计算 矩阵装配Assembly类
开发语言·c++·矩阵·有限元·ansys
c++初学者ABC6 小时前
学生管理系统C++版(简单版)详解
c++·结构体·学生管理系统
kucupung6 小时前
【C++基础】多线程并发场景下的同步方法
开发语言·c++