说起下拉框,想必大家都比较熟悉,在我们注册一些网站的时候,会出现大量的地区数据供我们选择,这个时候出现的就是下拉框列表,再比如字体选择的时候也是使用的下拉框,如图1所示。下拉框到处可见,作为一个图形库,qt也提供了QtComboBox类来供我们使用,但是有些时候简单的下拉列表已经满足不了我们的需求,如图2所示,是一个下拉表格,这个时候就需要我们自己定制一下QComboBox。

图1

图2

上边说了我们需求的变化,接下来我就讲述一下关于QComboBox定制的一些内容,本片文章我就只讲述两种常用的下拉选项控制,分别是列表表格

一、列表的实现

首先我上一张qq的登录框,如图3所示,下拉列表里不仅仅是一个文字描述或者复选框,而是含有图片文字和关闭按钮的复杂窗口,那么这个时候简单的QComboBox是完成不了这项功能的,要做到像qq这样美观的功能是需要我们自己做一定的处理

图3

列表窗口定制步骤如下:

1、首先我们需要自定义一个窗口,上边有我们需要操作的内容,这个窗口讲会是QComboBox下拉框中的一项,我自己定义的类名为CActionContentWidget,头文件如下:

 class CActionContentWidget : public QWidget
{
Q_OBJECT
signals:
void IconClicked();
void showText(const QString &); public:
CActionContentWidget(const QString & text, QWidget * parent = nullptr);
~CActionContentWidget(); public:
void SetContentText(const QString & text);//设置显示文字
void SetItemIcon(const QString & icon, const QString & hover);//设置图标 public:
void SetBackgroundRole(bool hover); protected:
virtual void enterEvent(QEvent *) Q_DECL_OVERRIDE;//暂时没用
virtual void leaveEvent(QEvent *) Q_DECL_OVERRIDE;//暂时没用
virtual bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE;
virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE; virtual void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE; private:
void InitializeUI(); private:
bool m_Mouse_press = false;
QWidget * m_ContentWidget = nullptr;
QPushButton * m_ActIcon = nullptr;
QLabel * m_ActText = nullptr;
};

这个窗口支持鼠标hover事件,并且我自己实现了鼠标按下和弹起方法,为的是自己控制QComboBox下拉框的隐藏,接口SetBackgroundRole是控制窗口背景色变化的函数,由于enterEvent和leaveEvent方法在成为了代理窗口后,事件触发我自己也没有搞清楚是怎么回事,因此我使用了installEventFilter方法把该窗口的事件放到父窗口去处理,在窗口中判断鼠标当前位置和CActionContentWidget 窗口之间的关系来判断鼠标是否进入该窗口。

图4

2、如图4所示,是我实现的结果预览,接下来我们需要把定制的窗口放到QComboBox的下拉框中,代码如下:

 class combobox : public QWidget
{
Q_OBJECT public:
combobox(QWidget *parent = );
~combobox(); protected:
virtual bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE; private:
void ConstructList();//列表定制
void ConstructTable();//表格定制 private:
Ui::comboboxClass ui;
};

ConstructList方法是列表的定制,也就是上图4所示的效果,ConstructTable方法内封装的是定制表格,后续我会讲解。

3、上边提到定制的窗口和鼠标位置的判断是在父窗口中进行的,那么接下来我就解释下父窗口的eventFIlter方法。代码比较简单,我就不一一进行解释了

 bool combobox::eventFilter(QObject * watched, QEvent * event)
{
if (watched->inherits("QWidget") && event->type() == QEvent::Paint)
{
if (CActionContentWidget * actionItem = dynamic_cast<CActionContentWidget *>(watched))
{
if (actionItem->rect().contains(actionItem->mapFromGlobal(QCursor::pos())))
{
actionItem->SetBackgroundRole(true);
}
else
{
actionItem->SetBackgroundRole(false);
}
}
} return QWidget::eventFilter(watched, event);
}

4、ConstructList列表实现,代码如下:

 void combobox::ConstructList()
{
QListWidget * listWidget = new QListWidget;
listWidget->setViewMode(QListView::ListMode); for (int i = ; i < ; i++)
{
CActionContentWidget * itemWidget = new CActionContentWidget("fawefawe");
connect(itemWidget, &CActionContentWidget::showText, this, [this, listWidget](const QString & text){
ui.comboBox->hidePopup();
if (ui.comboBox->isEditable())
{
ui.comboBox->setCurrentText(text);
}
else
{
for (int c = ; c < listWidget->count(); ++c)
{
CActionContentWidget * itemWidget = dynamic_cast<CActionContentWidget *>(listWidget->itemWidget(listWidget->item(c)));
if (itemWidget == sender())
{
ui.comboBox->setCurrentIndex(c);
}
}
}
});
itemWidget->SetItemIcon(":/combobox/Resources/icon1.jpg", ":/combobox/Resources/icon1.jpg");
itemWidget->setFixedHeight();
itemWidget->setFixedWidth();
QListWidgetItem * item = new QListWidgetItem(listWidget);
item->setText(QStringLiteral("%1").arg(i));
// item->setCheckState(Qt::Checked);
listWidget->setItemWidget(item, itemWidget);
listWidget->addItem(item);
itemWidget->installEventFilter(this);
} ui.comboBox->setModel(listWidget->model());
ui.comboBox->setView(listWidget);
ui.comboBox->setEditable(true);//是否支持下拉框可编辑
ui.comboBox->setMaxVisibleItems(); setStyleSheet("QComboBox{border:1px solid gray;}"
"QComboBox QAbstractItemView::item{height:45px;}" //下拉选项高度
"QComboBox::down-arrow{image:url(:/combobox/Resources/icon1.jpg);}" //下拉箭头
"QComboBox::drop-down{border:0px;}"); //下拉按钮
}

其中的setStyleSheet是用来设置下拉框中每一项的信息的,我们自己定制的窗口只是覆盖在原有窗口之上而已,原有的窗口还是存在的,因此我们的窗口必须和定制的窗口大小一样,负责会出现一些意外的情况。初次之外还需要注意的是:设置下拉框是否可编辑,如图5帮助文档所描述,QComboBox在可编辑状态下可以通过setCurrentText来设置displayText,但是如果不可编辑,他则会显示当前原有窗口的text,而非我们自己定制的窗口内容,因此我在showText信号的处理槽中,判断了下下拉框是否可编辑,并做相应的处理。

图5

还有几个设置下拉框属性的接口,我就不一一细说了,想了解的同学自己看帮助文档吧。其中setModel和setView是两居重点的代码,千万不能忘记,这两句代码是把QComboBox的视图和数据跟QListWidget绑定在一起了。QListWidget还支持ViewMode::IconMode这种现实模式,但是我们的下拉框定制用不到,因此我就不讲解这个了。

5、到此我们的列表定制就完成了。

二、表格实现

看明白了列表的实现,表格的实现就不在话下,不过我们列表的实现和表格的实现我在实现的时候还是有一定的区别的,有兴趣的同学可以接着往下看。首先就说下拉框的隐藏这一事件就和列表不一样,表格我是使用QTableWidget,内容使用QCheckBox,我自己重写了QCheckBox,并重新是了hitButton这个方法,因为当这个方法返回false时,鼠标点击不会选中/取消选中选择框,这个时候事件循环应该是传递到了父窗口上,而窗口把弹框隐藏了,这样做显然不满足我们的需求,有时候我们可能需要进行多个选择。说完需求之后我们来看代码。

1、首先我自己重写了QCheckBox,头文件代码如下:

 class CheckBox : public QCheckBox
{
public:
CheckBox(QWidget * parent = nullptr) :QCheckBox(parent){}
~CheckBox(){};; protected:
virtual void checkStateSet() Q_DECL_OVERRIDE;
virtual bool hitButton(const QPoint & pos) const Q_DECL_OVERRIDE;
virtual void nextCheckState() Q_DECL_OVERRIDE;
};

大多数函数都是没有做处理,仅仅对hitButton方法做了重写,返回值直接返回true。这个时候就我们就可以进行多项选择,而弹框也不会消失。最终的实现效果如图6所示

图6

2、ConstructTable方法的实现如下:

 void combobox::ConstructTable()
{
setStyleSheet("QComboBox QAbstractItemView {selection-background-color: transparent;}"); QTableWidget * tableWidget = new QTableWidget(, );
tableWidget->verticalHeader()->setVisible(false);
tableWidget->horizontalHeader()->setVisible(false);
tableWidget->setShowGrid(false);
for (int i = ; i < ; ++i)
{
tableWidget->setColumnWidth(i, );
tableWidget->setRowHeight(i, );
for (int j = ; j < ; ++j)
{
/* CActionContentWidget *itemWidget = new CActionContentWidget("fawefawe");
itemWidget->SetItemIcon(":/combobox/Resources/icon1.jpg", ":/combobox/Resources/icon1.jpg");
itemWidget->setFixedHeight(50);
itemWidget->setFixedWidth(50);*/
CheckBox * itemWidget = new CheckBox;
itemWidget->setFixedSize(, );
itemWidget->setStyleSheet(QString("QCheckBox {background-color:lightgray;}"
"QCheckBox:checked{background-color:white;}"));
connect(itemWidget, &QCheckBox::clicked, this, [this]{
QObject * sender = this->sender();
if (QCheckBox * item = dynamic_cast<QCheckBox *>(sender))
{
QString text = ui.comboBox->currentText();
if (text.isEmpty() == false)
{
if (item->isChecked())
{
if (text.split("|").indexOf(item->text()) == -)
{
text.append("|" + item->text());
}
}
else
{
text.remove("|" + item->text());
text.remove(item->text());
if (text.size() != && text.at() == '|')
{
text.remove(, );
}
}
}
else
{
if (item->isChecked())
{
text.append(item->text());
}
}
ui.comboBox->setCurrentText(text);
}
});
itemWidget->setText(QStringLiteral("好%1").arg(i));
itemWidget->setCheckable(true);
// tableWidget->setItem(i, j, new QTableWidgetItem(QStringLiteral("热分%1").arg(i)));
tableWidget->setCellWidget(i, j, itemWidget); itemWidget->installEventFilter(this);
}
} ui.comboBox->setModel(tableWidget->model());
ui.comboBox->setView(tableWidget);
// ui.comboBox->setEditable(true);
}

上边的代码都比较简单,我就不多了,我只说一个点,在设置表格列宽度的时候设置的为49,因为表格具有boder,如果设置50就会超出tableWidget,而出现左右滚动的现象

demo下载链接:http://download.csdn.net/detail/qq_30392343/9587529

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!! 

 

很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。

Qt之QComboBox定制的更多相关文章

  1. Qt之QComboBox定制(二)

    上一篇文章Qt之QComboBox定制讲到了qt实现自定义的下拉框,该篇文章主要实现了列表式的下拉框,这一节我还将继续讲解QComboBox的定制,而这一节我将会讲述更高级的用法,不仅仅是下拉列表框, ...

  2. 通过Qt样式表定制程序外观(比较通俗易懂)

    1. 何为Qt样式表[喝小酒的网摘]http://blog.hehehehehe.cn/a/10270.htm2. 样式表语法基础3. 方箱模型4. 前景与背景5. 创建可缩放样式6. 控制大小7. ...

  3. Qt之QComboBox(基本应用、代理设置)(转)

    QComboBox下拉列表比较常用,用户可以通过选择不同的选项来实现不同的操作,如何实现自己的下拉列表呢? 很多人在问QComboBox如何设置选项的高度.代理等一些问题!今天就在此分享一下自己的一些 ...

  4. Qt之QComboBox(基本应用、代理设置)

    QComboBox下来列表比较常用,用户可以通过选择不同的选项来实现不同的操作,如何实现自己的下拉列表呢? 很多人在问QComboBox如何设置选项的高度.代理等一些问题!今天就在此分享一下自己的一些 ...

  5. Qt中QComboBox中自定义界面使用stylesheet实现下拉按钮独立效果

    使用QSS自定义控件界面时,QT中控件QCombobox含有两个子控件drop-down和down-arrow.一般而言,当改变QCombox时,很多效果都会出来,但是,针对下拉按钮和下拉图标的自定义 ...

  6. QT之QComboBox

    1.addItems需要注意的事项: 1.在QT中设置maxVisibleItems的值,设置Items的最大可显示的值.(一般默认为10) 2.在每次需要清除已经添加的tems的时候需要注意,ui. ...

  7. 牛逼哄哄的Qt库

    目录 一.有价值 - 好的网站 - 好的文章 二.Qt开源库-工具 - QtXlsx--excel读写库 三.Qt开源库-控件 - libqxt编译 - Qwt - QCustomPlot - 其他 ...

  8. csdn的下载链接token

    qt之QComboBox定制 http://www.cnblogs.com/swarmbees/p/5710714.html http://download.csdn.net/detail/qq_30 ...

  9. QT定制有标题的扁平化下拉框控件

    关键字:QT,QComboBox,QLineEdit,QListView,QPushButton,QMenu,QWidgetAction,setStyleSheet OS:Windows 7 方法一: ...

随机推荐

  1. codeforces contest1082

    C 维护前缀和 题意 每一个id给一个权值序列,从每个id选出数量相同的权值,对他们进行求和,使得他们的和最大 题解 注意负数对结果没有贡献,直接跳过. 当时写的比较挫,连排序都写错了!cf的编译器比 ...

  2. Mac上使用jenkins+git持续集成浅析

    本文旨在让同学们明白如何让jenkis在mac笔记本上运行,并实际与一个最简单的git地址交互并执行简单的jenkins任务,如果学习本文,需要先按照https://www.cnblogs.com/x ...

  3. input type='file' 上传文件 判断图片的大小是否合格与witdh 和 height 是否合格

    function CheckFiles(obj) { var array = new Array('gif', 'jpeg', 'png', 'jpg'); //可以上传的文件类型 if (obj.v ...

  4. sql server 2012 减少日志

    USE [master] GO ALTER DATABASE 数据库名 SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE 数据库名 SET RECO ...

  5. Vue(二十八)el-cascader 动态加载 - 省市区组件

    1.后台接口为点击加载下一级 ,传省市区id <template> <el-cascader v-model="selectedOptions" placehol ...

  6. HTML入门14

    HTML表单 这块部分开始强调表单也是用的比较多的部分,好好补漏啊啊啊啊 表单用来做交互,处理所有方面结构到样式,到自定义小部件. form元素,严禁嵌套表单,表单嵌套会使得表单得行为不可预知,引入f ...

  7. ES6新增的常用数组方法(forEach,map,filter,every,some)

    ES6新增的常用数组方法 let arr = [1, 2, 3, 2, 1]; 一 forEach => 遍历数组 arr.forEach((v, i) => { console.log( ...

  8. 4.24Linux(4)

    2019-4-24 21:35:13 学完了Linux装python编译安装感觉有种控制电脑的感觉!感觉好爽!!!! 主要是Linux用习惯就感觉好爽!!! 越努力,越幸运!永远不要高估自己!! 等学 ...

  9. day03笔记

    1.list操作stus = ['xiaohei','xiaobai','xiaohuang','cxdser'] #数组.list.array#增加stus.append('原宝')#在list末尾 ...

  10. 【技术分享】BurpSuite 代理设置的小技巧

    作者:三思之旅 预估稿费:300RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 在Web渗透测试过程中,BurpSuite是不可或缺的神器之一.BurpSuite的核心是 ...