刚学Qt的时候,初步经历的第一个学习项目基本上都是LANQQ,初识时,不懂QSS,不懂布局,绘制界面最简单的方式成了使用designer拉满整个界面的控件,或者使用代码写了一些很蹩脚的布局。也是很羡慕别人哪些精致的界面,印象很深的是QQ登陆界面的下来列表,下面,我们简单的来介绍下怎样做到和QQ登陆界面一样的下拉列表。
先看一下效果:
没有做qss的美化,简单的实现了下功能,如果需要在显示名称的部分也需要显示头像的话,也是可以,这个在下一节自定义控件的时候再看。
简单的改造了一下上次的ListTemplate类,作为我们显示在QComboBox下拉框的载体,并自定义了msgItem。如下:
class MsgItem : public QWidget
{ Q_OBJECT
//可按照下面的方法自己添加需要的功能
Q_PROPERTY(QString name READ name WRITE setName DESIGNABLE true)
public:
explicit MsgItem(QWidget *parent = 0);
~MsgItem();
QString name() const;
void setName(const QString& name);
protected:
void mousePressEvent(QMouseEvent* event) override;
private slots:
void on_btnDeleteClicked();
signals:
void signal_selected(const QString& text);
void signal_delete(QWidget*);
private:
Ui::MsgItem *ui;
};
自定义的Item中有两个信号,一个是删除,一个是选中的时候通知上层目前选中的item的字符。
这边使用了mouseEvent。选择使用这个的原因是,相对于我们使用QListWidgetItem类获取其Widget要简单很多。鼠标点击的时候直接将其需要在上层显示的数据发给上层就好。实现如下:
void MsgItem::mousePressEvent(QMouseEvent *event)
{
emit signal_selected(ui->lbName->text());
}
载体就显得比较简单,只有一个方法和一个信号,方法用来测试,新增一个Item,信号是item发上来选中信号时,通知上层。
class ListWidget : public QListWidget
{
Q_OBJECT
public:
explicit ListWidget(QWidget *parent = 0);
~ListWidget();
private:
void AddWidgetMsgItem();
signals:
void signal_selected(const QString& text);
};
新增的方法如下,这边有一个需要注意的点。QComboBox如果选择可编辑的时候,会多一个QLineEdit控件,如果我们不选择可编辑,那么只能通过setCurrentText方法来设置它需要显示的数据,但是,前提条件是:
设置的数据要在它下面的item中能够找到,否则是不会显示的。
因此,当我们自定一的时候,一定要通过一写方法来设置它的itemText。
void ListWidget::AddWidgetMsgItem()
{
auto pMsgItem = new MsgItem();
QListWidgetItem *item = new QListWidgetItem;
item->setSizeHint( QSize(360, 60));
item->setText(pMsgItem->name()); //不加的会,则不会显示在界面上
this->addItem(item);
this->setItemWidget(item, pMsgItem);
connect(pMsgItem, &MsgItem::signal_selected, this, &ListWidget::signal_selected);
// connect(pMsgItem, &MsgItem::signal_delete, this, &ListWidget::slot_delete);
}
说了这么多,其实上面的所有东西我们以前已经使用过了,而下面的内容才是今天的重点。
首先我们自定义类ComboBox 继承自 QComboBox,(如果嫌麻烦也可以不同自定义类)然后定义一个槽函数来接收底层的List发上来的数据。要将我们上面实现的自定义的ListWidget来设置到ComboBox的下拉框中,其实是很简单的,如下:
auto list = new ListWidget;
bool br = connect(list, &ListWidget::signal_selected, this, &ComboBox::slot_seleted);
this->setModel(list->model());
this->setView(list);
是的,只有几行代码,就能够实现,由这些看来,自定义一些控件的时候并不是很难,难的是一想到要自定义控件,已经产生的哪种恐惧。。。
测试代码链接:https://gitee.com/Gqian_com/customcomponent/tree/master/combobox