先看效果图:
看源码:
1. 设置基本样式:
MComboBox::MComboBox(QWidget *parent) : QComboBox(parent)
{
// 设置样式表,修改下拉框的样式,同时修改下拉列表中的滚动条样式
setStyleSheet(QString("QComboBox{ "
"background:transparent; "
"border:1px solid #009ae7; "
"color:rgb(255,255,255); "
"font-size:20px; "
"} "
"QComboBox::drop-down { "
" width: 20px; "
" border:none; "
"} "
"QComboBox::down-arrow { "
" width:14px; "
" height:8px; "
" border-image: url(:/img/cbArrow.png); "
"} "
"QComboBox::down-arrow:on { "
" top: 1px; "
" left: 1px; "
"} "
"QComboBox QFrame{ "
" background-color:#4be26e; "
" border:none; "
"} "
"QComboBox QAbstractItemView "
"{ "
" outline:0px; "
"} "
"QComboBox QAbstractItemView::item "
"{ "
" height: 54px; "
" color: #ffffff; "
" border-bottom: 1px solid #009ae7; "
"} "
"QComboBox QAbstractItemView::item:selected"
"{ "
" background:transparent; "
"} "
"QScrollBar::vertical{ background:transparent; margin: 0px 0px 0px 0px; width: 8px; } "
"QScrollBar::handle:vertical{ border-image: url(:/img/scroll.png); } "
"QScrollBar::add-line:vertical{ height: 0px; } "
"QScrollBar::sub-line:vertical{ height: 0px; } "
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: transparent;} "
));
// 嵌入一个编辑框,调整下拉框显示的文字为右对齐
QLineEdit* edt = new QLineEdit();
edt->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
edt->setReadOnly(true);
// 取消编辑框双击选中的效果
connect(edt, &QLineEdit::selectionChanged, [=](){edt->setSelection(edt->text().length() - 1, 0);});
// 使用事件过滤器添加编辑框点击,显示下拉框的效果
edt->installEventFilter(this);
setLineEdit(edt);
//用于下拉框item的样式美化,使用改代理后,上面的样式表可以完成下拉表的样式展示
QStyledItemDelegate* itemDelegate = new QStyledItemDelegate();
setItemDelegate(itemDelegate);
//下面两句可以设置下拉背景为透明
view()->parentWidget()->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
view()->parentWidget()->setAttribute(Qt::WA_TranslucentBackground);
// 设置下拉列表可以实现类似触屏的上下拖拽
QListView* v = static_cast<QListView*>(view());
v->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
// ui->lstUserList->verticalScrollBar()->setSingleStep(10);
QScroller::grabGesture(v, QScroller::LeftMouseButtonGesture);
v->setFlow(QListView::TopToBottom);
// 设置最大显示5条内容
setMaxVisibleItems(5);
}
2. 下拉列表自适应宽度,同时调整下拉项的文字右对齐
void MComboBox::adjustItemWidth()
{
if(count() <= 0)
return;
QStandardItemModel* md = static_cast<QStandardItemModel*>(view()->model());
int max_len=0;
QString max_str;
QFont ft = font();
ft.setPixelSize(22);
QFontMetrics fm(ft);
// 计算下拉列表应该占用的宽度
for(int i=0; i < count(); i++)
{
int len = fm.width(itemText(i));
if(max_len < len)
{
max_len = len;
max_str = itemText(i);
}
// 调整下拉列表的item子项右对齐
md->item(i)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
// 防止内容太长,超出显示屏,导致无法正常显示
int x = mapToGlobal(rect().topRight()).x();
max_len = (max_len <= x ? max_len : x);
// 设置下拉列表的固定宽度
view()->parentWidget()->setFixedWidth(max_len);
}
3. 重写父类的showPopup函数,调整下拉列表位置。
void MComboBox::showPopup()
{
// 显示前调整下拉列表
adjustItemWidth();
QComboBox::showPopup();
// 获取下拉列表窗口对象
QWidget* fm = view()->parentWidget();
// 获取下拉列表显示的全局位置
QPoint fmPt = fm->mapToGlobal(fm->pos());
// qDebug() << fmPt;
// 将下来框移动到右对齐的位置
QPoint pt = fm->mapFromGlobal( QPoint(fmPt.x() - (fm->width() - width()), fmPt.y()) );
// qDebug() << pt;
fm->move(pt);
}
4. 过滤编辑框的点击事件,响应点击编辑框时,显示下拉列表
bool MComboBox::eventFilter(QObject *obj, QEvent *event)
{
bool b = QComboBox::eventFilter(obj, event);
// 过滤编辑框点击事件,在编辑框点击时显示下拉列表
QLineEdit* ed = lineEdit();
if(obj == ed && event->type() == QEvent::MouseButtonRelease)
{
if(!view()->isVisible())
{
showPopup();
}
else
{
hidePopup();
}
}
return b;
}
以上为全部效果实现方式,在使用时提升QComboBox为自定义的MComboBox即可。
附上软件源码下载地址:https://download.youkuaiyun.com/download/chenxipu123/10966933
吐槽一下:优快云不让设置资源所需的下载积分,所以源码没法免费共享。