简述
许多人在使用Qt的时候,特别是在准备做一个像登录框一样的界面的时候。在账号栏我们多见到像下图一样的情况。
本文就重点关于账号栏是实现进行讨论。大家一般第一印象就感觉应该用QComBoBox实现。但仅仅只使用QComBoBox是无法达到下图的效果的。
实现
在考虑如何实现的时候,我们要自定义一个组件来代替下拉框中的QComBoBox原生组件
下面看一下我们的例子,在这个例子我们会实现一个QLabel和一个QPushButton的横向布局并重新实现一些事件。
#ifndef LOGINWINDOWACCOUNTITEM_H
#define LOGINWINDOWACCOUNTITEM_H
//这是一个用于自定义QComboBox的代理控件
//主要会包含一个QLabel和一个QPushButton
#include <QWidget>
#include <QMouseEvent>
class QLabel;
class QPushButton;
class LoginWindowAccountItem : public QWidget
{
Q_OBJECT
public:
LoginWindowAccountItem(QWidget *parent=0);
~LoginWindowAccountItem();
//set - get accountName
QString getAccountName() const;
void setAccountName(const QString&);
signals:
void sgn_removeAccount(QString);//移除这个账户,QString为当前accountName的值
void sgn_showAccount(QString);//展示我们刚才所选的这个Item
public slots:
void slt_removeAccountItem();//删除账户槽
protected:
//重写鼠标按下与释放,以此来实现点击item进行当前item的替换
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
private:
const int ContentsMargin = 5;//内边距
bool isMousePress;
QLabel *accountName;
QPushButton *deleteIconButton;
};
#endif // LOGINWINDOWACCOUNTITEM_H
下面是cpp文件
#include "loginwindowaccountitem.h"
#include <qlabel.h>
#include <QPushButton>
#include <qpixmap.h>
#include <QHBoxLayout>
LoginWindowAccountItem::LoginWindowAccountItem(QWidget *parent)
: QWidget(parent),isMousePress(false),accountName(new QLabel()),deleteIconButton(new QPushButton())
{
connect(deleteIconButton, &QPushButton::clicked, this, &LoginWindowAccountItem::slt_removeAccountItem);
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(accountName);
layout->addStretch();
layout->addWidget(deleteIconButton);
layout->setContentsMargins(ContentsMargin, ContentsMargin, ContentsMargin, ContentsMargin);
layout->setSpacing(ContentsMargin);
this->setLayout(layout);
return;
}
//set - get accountName
QString LoginWindowAccountItem::getAccountName() const
{
return accountName->text();
}
void LoginWindowAccountItem::setAccountName(const QString& text)
{
accountName->setText(text);
return;
}
//移除这个账户,发送移除这个账户的信号,信号内容为当前这个item的accountName
void LoginWindowAccountItem::slt_removeAccountItem()
{
QString removeAccountName = accountName->text();
emit sgn_removeAccount(removeAccountName);
return;
}
//重写鼠标按下与释放,以此来实现点击item进行当前item的替换
void LoginWindowAccountItem::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
isMousePress = true;
}
return;
}
void LoginWindowAccountItem::mouseReleaseEvent(QMouseEvent *event)
{
if (isMousePress)
{
QString accountName = this->accountName->text();
emit sgn_showAccount(accountName);
isMousePress = false;
}
return;
}
LoginWindowAccountItem::~LoginWindowAccountItem()
{
}
好了,现在我们已经完成了代理控件的编写,下面我们来看一下在自定义的登录框中的账户栏的实现
#ifndef LOGINWINDOW_H
#define LOGINWINDOW_H
#include <QWidget>
#include "ui_loginwindow.h"
class QListWidget;
class QMessageBox;
class LoginWindow : public QWidget
{
Q_OBJECT
public:
LoginWindow(QWidget *parent = 0);
~LoginWindow();
public slots:
void slt_removeLoginAccount(const QString&);
void slt_showSelectedAccount(const QString&);
private:
Ui::LoginWindow *ui;
QListWidget *accountList;//用来替代QComBoBox的下拉框
};
#endif // LOGINWINDOW_H
下面是cpp文件
#include "loginwindow.h"
#include "loginwindowaccountitem.h"
#include <QListWidget>
#include <QLineEdit>
#include <qmessagebox.h>
#include <qdebug.h>
LoginWindow::LoginWindow(QWidget *parent)
: QWidget(parent),accountList(new QListWidget()),ui(new Ui::LoginWindow)
{
ui->setupUi(this);
ui->accountComboBox->setEditable(true);//开启lineedit编辑
//设置占位符文本
ui->accountComboBox->lineEdit()->setPlaceholderText(u8"用户名/手机/邮箱");
ui->accountComboBox->setModel(accountList->model());
ui->accountComboBox->setView(accountList);
//静态实现的下拉框中的账户,一般写项目的时候不会这样显示定义数量
for (int i = 0; i < 3; ++i)
{
LoginWindowAccountItem* item = new LoginWindowAccountItem();
item->setAccountName(QString(u8"thisItemIs")+QString::number(i) );
connect(item, &LoginWindowAccountItem::sgn_removeAccount, this, &LoginWindow::slt_removeLoginAccount);
connect(item, &LoginWindowAccountItem::sgn_showAccount, this, &LoginWindow::slt_showSelectedAccount);
QListWidgetItem *listItem = new QListWidgetItem(accountList);
accountList->setItemWidget(listItem, item);
}
}
void LoginWindow::slt_removeLoginAccount(const QString& text)
{
QMessageBox msgBox(QMessageBox::Information, tr(u8"提示"), tr(u8"确认删除这个账户!"), QMessageBox::Yes | QMessageBox::Cancel, NULL);
if (msgBox.exec() == QMessageBox::Yes)
{
int listCount = accountList->count();
QListWidgetItem* tempItem;
LoginWindowAccountItem *tempAccountItem;
QString removeItemAccountName;
//找到这个item并删除
for (int i = 0; i < listCount; ++i)
{
tempItem = accountList->item(i);
tempAccountItem = static_cast<LoginWindowAccountItem *>(accountList->itemWidget(tempItem));
removeItemAccountName=tempAccountItem->getAccountName();
if (removeItemAccountName == text)
{
accountList->takeItem(i);
ui->accountComboBox->setEditText("");
delete tempItem;
break;
}
}
}
}
void LoginWindow::slt_showSelectedAccount(const QString& text)
{
ui->accountComboBox->setEditText(text);
ui->accountComboBox->hidePopup();
return;
}
LoginWindow::~LoginWindow()
{
delete ui;
}
在这里主函数的编码就不给出了,相信大家有这个基础的。
好,现在我们可以看一下效果图,由于没有进行任何的美化和修饰,可能视觉效果不是太好。但本文主要是总结一下这个实现的方法。美化的部分,可以后期加载QSS文件进行美化