很多时候我们会发现输入的一长串内容不得不全部删除重新输入,这时比起一直按着退格键不放一个清除内容按钮更受欢迎。
今天我将介绍三种为QLineEdit添加清除内容按钮的方法,其中两种方法有较强的功能针对性,另一种方法则是通用的,不仅可以用来实现清除输入内容,还可以扩展出其他功能。
本文索引
方法1:setClearButtonEnabled显示清除按钮
这是Qt5.2之后提供的方法,当使用了setClearButtonEnabled(true);
之后会在 QLineEdit的右侧显示一个图标为QStyle::SP_DialogResetButto
的QAction,点击后会清除输入内容:
// 方案1
auto edit1 = new QLineEdit;
edit1->setClearButtonEnabled(true);
效果:
看到右边那个图标,如果是Qt自带的话会是一个类似扫把的图形,如果使用了系统主题那么会有些许差异,点击它,输入内容就会全部清除。
方法2:使用QAction实现清除按钮
如前所述,setClearButtonEnabled
其实只是让实现存在的QAction显示出来而已,所以我们也可以自己实现这一过程。
要实现这一功能,需要Qt5.2之后提供的addAction
方法。它负责把一个QAction添加到edit的指定位置。
不过要注意的是,这个QAction只能显示出图标,文字内容的显示不出的。
// 方案2
auto clearAction = new QAction;
clearAction->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogResetButton));
auto edit2 = new QLineEdit;
// QLineEdit::TrailingPosition表示将action放置在右边
edit2->addAction(clearAction, QLineEdit::TrailingPosition);
QObject::connect(clearAction,
&QAction::triggered,
edit2,
[edit2]{ edit2->setText(""); });
因为我们知道lineedit默认使用的清除按钮的图标,也知道如何清除输入,所以可以自己实现这一过程。
这是效果,与方法1时几乎没什么区别:
不过方法二的威力不止于此,基于我们可以使用自己的QAction,那么就可以定制一些操作,比如使用我们自己的图标:
clearAction->setIcon(QIcon(":/clear.png"));
这种方法相比前一种略显复杂,然而却提供了更好的扩展性。
接下来要介绍的最后一种方法更加的灵活,你不仅可以显示自定义图标,还可以显示自定义文字,当然作为代价它比第二种方法要复杂不少。
方法3:自定义QLineEdit为其添加按钮
这种方法对Qt的版本没有什么要求,所以它也足够通用。
想要在QLineEdit上添加一个widget一点也不复杂,首先我们要弄清以下几个原理:
- qt的widget和layout是可以堆叠的,之前在实现半透明遮罩中有提过
- 你可以为QLineEdit设置layout,如你所料layout会堆叠在edit的输入框上
- edit的layout会只使用控件的最小尺寸,这样不会导致将整个输入框遮盖掉
- edit的可输入区域是可以设置的,你可以合理的设置输入区的大小避免文字进入layout之下被遮盖
所以如果我们想为QLineEdit或是其派生类添加一个widget比如QPushButton,那么需要如下几部:
- 创建你需要的widget以及一个布局管理器
- 添加拉伸因子和widget至布局管理器,拉伸因子可以不添加,只要设置好布局管理器的排列方向即可
- 设置布局管理器里组件的排列方向并把布局管理器添加到QLineEdit
- 获取你添加的widget的宽度,然后在加上合适的边框距离,将QLineEdit的输入区域限制在合理的大小
说起来简单做起来难,我们边看代码边讲解。
我们先看类的定义,ButtonEdit
是一个带有按钮的QLineEdit:
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QString>
#include <QIcon>
class ButtonEdit: public QLineEdit {
Q_OBJECT
public:
explicit ButtonEdit(const QString &btnText, QWidget *parent = nullptr);
explicit ButtonEdit(const QIcon &icon, QWidget *parent = nullptr);
~ButtonEdit() override = default;
private:
// 设置文本按钮或图标按钮的大小和外观
void setTextButton();
void setIconButton();
// 将按钮添加到edit
void addButton();
QPushButton *button;
Q_SIGNALS:
void buttonClicked(bool);
};
// 按钮和输入内容的边距
constexpr int buttonMargin = 3;
我们的类可以从一个string或者icon构建,当edit的按钮被点击那么我们就发出buttonClicked
信号。
也许你会觉得对于按钮的设置分成两类没什么必要。事实不然,图形应用的开发有很多麻烦事,而其中比较头疼的要数如何让控件保持一个恰到好处的尺寸,而对于图标的处理和文本是不一样的,所以有分开的必要。当然,如果你不介意文字或者图标只显示一半或者突出到编辑框的话也可以跳过这一步。
下面我们来看下类成员的实现,构造函数没什么亮点,无非构造button,然后交由其他成员去处理:
ButtonEdit::ButtonEdit(const QString &btnText, QWidget *parent)
: QLineEdit(parent)
{
button = new QPushButton(btnText);
setTextButton();
addButton();
}
ButtonEdit::ButtonEdit(const QIcon &icon, QWidget *parent)
: QLineEdit(parent)
{
button = new QPushButton;
button->setIcon(icon);
setIconButton();
addButton();
}
接着是addButto