前言
记录下Qt的自定义QComboBox下拉选项添加删除按钮功能。
提示:以下是本篇文章正文内容,下面案例可供参考
1.效果展示
2.comboview.h
代码如下(示例):
#ifndef COMBOVIEW_H
#define COMBOVIEW_H
#include <QDebug>
#include <QStyle>
#include <QLayout>
#include <QLineEdit>
#include <QComboBox>
#include <QListView>
#include <QScrollBar>
#include <QListWidget>
#include <QPushButton>
#include <QMouseEvent>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
class ComboView : public QListWidget
{
Q_OBJECT
public:
explicit ComboView(QWidget * parent=nullptr);
QRect visualRect(const QModelIndex &index) const override;
};
class ComboItem : public QWidget
{
Q_OBJECT
public:
explicit ComboItem(const QString &text,QWidget *parent = nullptr);
QString text() const;
signals:
void itemClicked(const QString &text);
private:
QString textValue;
QPushButton *btn;
};
class ComboDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ComboDelegate(QObject *parent=nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
};
class MyComboBox : public QComboBox
{
Q_OBJECT
public:
explicit MyComboBox(QWidget *parent = nullptr);
//设置下拉选项
void setRemovableItems(const QStringList &items);
//显示弹框
void showPopup() override;
void hidePopup() override;
void MyAddItem(const QString &text);
void addCurruntText(QString text);
void addKeyEnterText();
signals:
void itemChange();
protected:
void keyReleaseEvent(QKeyEvent *event);
private:
QListWidget *itemList;
};
#endif // COMBOVIEW_H
3.comboview.cpp
代码如下(示例):
#include "comboview.h"
ComboView::ComboView(QWidget *parent)
: QListWidget(parent)
{
}
QRect ComboView::visualRect(const QModelIndex &index) const
{
QRect rect = QListWidget::visualRect(index);
int width = this->width();
if(verticalScrollBar()->isVisible()){
width -= verticalScrollBar()->width();
}
rect.setWidth(width);
return rect;
}
ComboItem::ComboItem(const QString &text, QWidget *parent)
: QWidget(parent),
textValue(text)
{
btn = new QPushButton(this);
btn->setFixedSize(18,18);
btn->setStyleSheet("QPushButton{background-color: transparent; border: none;border-image: url(style/icons/delete.png);}"
"QPushButton:hover{border-image: url(style/icons/delete_hover.png);}");
QHBoxLayout *layout = new QHBoxLayout(this);
layout->addStretch();
layout->addWidget(btn);
layout->setContentsMargins(5,0,5,0);
layout->setSpacing(0);
this->setLayout(layout);
connect(btn,&QPushButton::clicked,[this]{
emit itemClicked(textValue);
});
}
QString ComboItem::text() const
{
return textValue;
}
ComboDelegate::ComboDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
void ComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem opt(option);
//去掉焦点带来的虚线框
opt.state &= ~QStyle::State_HasFocus;
initStyleOption(&opt, index);
QStyledItemDelegate::paint(painter, opt, index);
}
MyComboBox::MyComboBox(QWidget *parent)
: QComboBox(parent),
itemList(new ComboView(this))
{
// itemList->setTextElideMode(Qt::ElideNone);
setModel(itemList->model());
setView(itemList);
setEditable(true);
setItemDelegate(new ComboDelegate(this));
setMaxVisibleItems(5);
}
void MyComboBox::setRemovableItems(const QStringList &items)
{
//combox的additem insertitem不是虚函数
//实现里时调用的model->insertRow,但是懒得再去重写listmodel-view,就新增一个接口
itemList->clear();
if(items.isEmpty())
return;
for(int i = 0;i < items.count();i++){
MyAddItem(items.at(i));
}
}
void MyComboBox::MyAddItem(const QString &text)
{
QListWidgetItem* widget_item = new QListWidgetItem(itemList);
ComboItem *item = new ComboItem(text,itemList);
widget_item->setData(Qt::DisplayRole,text);
itemList->setItemWidget(widget_item, item);
connect(item,&ComboItem::itemClicked,this,[this,item,widget_item](){
//take移除item后没有刷新弹框大小,干脆隐藏掉先
hidePopup();
itemList->takeItem(itemList->row(widget_item));
delete widget_item;
if(itemList->count() <= 5){
for (int i = 0; i < itemList->count(); i++){
QWidget *nwidget = itemList->itemWidget(itemList->item(i));
QHBoxLayout *layout = (QHBoxLayout *)nwidget->layout();
layout->setContentsMargins(5,0,5,0);
nwidget->setLayout(layout);
}
}
emit itemChange();
});
if(itemList->count() > 5){
for (int i = 0; i < itemList->count(); i++){
QWidget *nwidget = itemList->itemWidget(itemList->item(i));
QHBoxLayout *layout = (QHBoxLayout *)nwidget->layout();
layout->setContentsMargins(5,0,15,0);
nwidget->setLayout(layout);
}
}
}
void MyComboBox::addCurruntText(QString text)
{
for (int i = 0; i < count(); ++i) {
ComboItem *m_widget = qobject_cast<ComboItem *>(itemList->itemWidget(itemList->item(i)));
if(!m_widget) removeItem(i);
}
for (int i = 0; i < count(); ++i) {
if(itemText(i) == text) return;
}
MyAddItem(text);
setCurrentIndex(this->count()-1);
}
void MyComboBox::addKeyEnterText()
{
QString text = currentText();
addCurruntText(text);
}
void MyComboBox::keyReleaseEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Enter|| event->key() == Qt::Key_Return){
addKeyEnterText();
}
else {
QComboBox::keyPressEvent(event);
}
}
void MyComboBox::showPopup()
{
QComboBox::showPopup();
}
void MyComboBox::hidePopup()
{
QStyle * const style = this->style();
QStyleOptionComboBox opt;
initStyleOption(&opt);
view()->scrollTo(view()->currentIndex(),
style->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)
? QAbstractItemView::PositionAtCenter
: QAbstractItemView::EnsureVisible);
QComboBox::hidePopup();
}
总结
参考了网上的资料,自己修改了一些自己需要的功能,记录一下以后可能还会用到,也方便其他人需要的参考一下。