说起下拉框,想必大家都比较熟悉,在我们注册一些网站的时候,会出现大量的地区数据供我们选择,这个时候出现的就是下拉框列表,再比如字体选择的时候也是使用的下拉框,如图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. 使用python将数据写入excel

    先来个简单的例子: #!/usr/bin/python #coding=utf-8 # ======================================================== ...

  2. CodeForces 510C Fox And Names (拓扑排序)

    <题目链接> 题目大意: 给你一些只由小写字母组成的字符串,现在按一定顺序给出这些字符串,问你怎样从重排字典序,使得这些字符串按字典序排序后的顺序如题目所给的顺序相同. 解题分析:本题想到 ...

  3. CentOS7下使用yum安装MariaDB

    从CentOS 7开始,使用 MariaDB 替代默认的 MySQL.MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MyS ...

  4. 第n次搭建 SSM 框架

    什么说第 N 次搭建SSM框架呢? 刚学习java的时候,搭建 SSM 框架想做一个个人项目之类的,后来没搭起来,也就拖延了,进入公司之后,接触的第一个项目就是SSM的,模仿了一下,也能搭个简简单单的 ...

  5. fiddler 抓取 htts 失败

    1.清除C:\Users\Administrator\AppData\Roaming\Microsoft\Crypto\RSA 目录下所有文件(首次安装fiddler请忽略) 2.清除电脑上的根证书, ...

  6. browser-sync + http-proxy-middleware 配置代理跨域

    写代理js文件下面是文件内容 /** * Module dependencies. */ var browserSync = require('browser-sync').create() var ...

  7. [Ubuntu]修改文件夹及所有子文件夹权限

    sudo chmod -R 777 FILE_NAME 使FILE_NAME文件或文件夹具有读写和执行的权限.

  8. VB.NET或C#报错:You must hava a license to use this ActiveX control.

    VB.NET或者C# winform开发时,如果使用了Microsoft Visual Basic 6.0 ActiveX,并动态创建该控件实例,那么程序移植到没有安装Visual Basic 6.0 ...

  9. vue 源码学习二 实例初始化和挂载过程

    vue 入口 从vue的构建过程可以知道,web环境下,入口文件在 src/platforms/web/entry-runtime-with-compiler.js(以Runtime + Compil ...

  10. 总结css常用方法

    1.自定义滚动条 .test-1::-webkit-scrollbar {/*滚动条整体样式*/ width: 10px; /*高宽分别对应横竖滚动条的尺寸*/ height: 1px; } .tes ...