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

Qt之QComboBox定制图1

    Qt之QComboBox定制图2

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

一、列表的实现

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

Qt之QComboBox定制图3

    列表窗口定制步骤如下:

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

 1 class CActionContentWidget : public QWidget
 2 {
 3     Q_OBJECT
 4 signals:
 5     void IconClicked();
 6     void showText(const QString &);
 7 
 8 public:
 9     CActionContentWidget(const QString & text, QWidget * parent = nullptr);
10     ~CActionContentWidget();
11 
12 public:
13     void SetContentText(const QString & text);//设置显示文字
14     void SetItemIcon(const QString & icon, const QString & hover);//设置图标
15 
16 public:
17     void SetBackgroundRole(bool hover);
18 
19 protected:
20     virtual void enterEvent(QEvent *) Q_DECL_OVERRIDE;//暂时没用
21     virtual void leaveEvent(QEvent *) Q_DECL_OVERRIDE;//暂时没用
22     virtual bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE;
23     virtual void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
24 
25 
26     virtual void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
27 
28 private:
29     void InitializeUI();
30 
31 private:
32     bool m_Mouse_press = false;
33     QWidget * m_ContentWidget = nullptr;
34     QPushButton * m_ActIcon = nullptr;
35     QLabel * m_ActText = nullptr;
36 };

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

Qt之QComboBox定制图4

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

 1 class combobox : public QWidget
 2 {
 3     Q_OBJECT
 4 
 5 public:
 6     combobox(QWidget *parent = 0);
 7     ~combobox();
 8 
 9 protected:
10     virtual bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE;
11 
12 private:
13     void ConstructList();//列表定制
14     void ConstructTable();//表格定制
15 
16 private:
17     Ui::comboboxClass ui;
18 };

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

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

 1 bool combobox::eventFilter(QObject * watched, QEvent * event)
 2 {
 3     if (watched->inherits("QWidget") && event->type() == QEvent::Paint)
 4     {
 5         if (CActionContentWidget * actionItem = dynamic_cast<CActionContentWidget *>(watched))
 6         {
 7             if (actionItem->rect().contains(actionItem->mapFromGlobal(QCursor::pos())))
 8             {
 9                 actionItem->SetBackgroundRole(true);
10             }
11             else
12             {
13                 actionItem->SetBackgroundRole(false);
14             }
15         }
16     }
17 
18     return QWidget::eventFilter(watched, event);
19 }

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

 1 void combobox::ConstructList()
 2 {
 3     QListWidget * listWidget = new QListWidget;
 4     listWidget->setViewMode(QListView::ListMode);
 5 
 6     for (int i = 0; i < 5; i++)
 7     {
 8         CActionContentWidget * itemWidget = new CActionContentWidget("fawefawe");
 9         connect(itemWidget, &CActionContentWidget::showText, this, [this, listWidget](const QString & text){
10             ui.comboBox->hidePopup();
11             if (ui.comboBox->isEditable())
12             {
13                 ui.comboBox->setCurrentText(text);
14             }
15             else
16             {
17                 for (int c = 0; c < listWidget->count(); ++c)
18                 {
19                     CActionContentWidget * itemWidget = dynamic_cast<CActionContentWidget *>(listWidget->itemWidget(listWidget->item(c)));
20                     if (itemWidget == sender())
21                     {
22                         ui.comboBox->setCurrentIndex(c);
23                     }
24                 }
25             }
26         });
27         itemWidget->SetItemIcon(":/combobox/Resources/icon1.jpg", ":/combobox/Resources/icon1.jpg");
28         itemWidget->setFixedHeight(45);
29         itemWidget->setFixedWidth(150);
30          QListWidgetItem * item = new QListWidgetItem(listWidget);
31         item->setText(QStringLiteral("%1").arg(i));
32     //    item->setCheckState(Qt::Checked);
33         listWidget->setItemWidget(item, itemWidget);
34         listWidget->addItem(item);
35         itemWidget->installEventFilter(this);
36     }
37 
38     ui.comboBox->setModel(listWidget->model());
39     ui.comboBox->setView(listWidget);
40     ui.comboBox->setEditable(true);//是否支持下拉框可编辑
41     ui.comboBox->setMaxVisibleItems(3);
42 
43     setStyleSheet("QComboBox{border:1px solid gray;}"
44         "QComboBox QAbstractItemView::item{height:45px;}" //下拉选项高度
45         "QComboBox::down-arrow{image:url(:/combobox/Resources/icon1.jpg);}" //下拉箭头
46         "QComboBox::drop-down{border:0px;}"); //下拉按钮
47 }
View Code

相关文章: