三种方法为QLineEdit添加清除内容按钮 (2)

也许你会觉得对于按钮的设置分成两类没什么必要。事实不然,图形应用的开发有很多麻烦事,而其中比较头疼的要数如何让控件保持一个恰到好处的尺寸,而对于图标的处理和文本是不一样的,所以有分开的必要。当然,如果你不介意文字或者图标只显示一半或者突出到编辑框的话也可以跳过这一步。

下面我们来看下类成员的实现,构造函数没什么亮点,无非构造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(); }

接着是addButton,在这里我们先把button添加进layout,随后又设置了输入区域的大小避免输入内容被遮住:

void ButtonEdit::addButton() { connect(button, &QPushButton::clicked, this, &ButtonEdit::buttonClicked); // 按钮已经是edit的一部分了,不应该再能被单独聚焦,否则可能导致误触 button->setFocusPolicy(Qt::NoFocus); // 设置鼠标,否则点击按钮时仍然会显示输入内容是的鼠标图标 button->setCursor(Qt::ArrowCursor); auto btnLayout = new QHBoxLayout; btnLayout->addStretch(); btnLayout->addWidget(button); // 设置组件右对齐,按钮会显示在edit的右侧 btnLayout->setAlignment(Qt::AlignRight); btnLayout->setContentsMargins(0, 0, 0, 0); setLayout(btnLayout); // 设置输入区域的范围,从edit的最左到按钮的最左(包含了按钮设置的buttonMargin) setTextMargins(0, 0, button->width(), 0); }

下面就是如何设置button的大小和样式了,大小我们设置和图标/文本的大小一样大,然后两边加上buttonMargin。

对于图标按钮我们还要设置按钮背景平时不可见,毕竟图标周围有个buttonMargin宽度的框不太好看:

// 帮助函数,设置按钮的width,大小策略为fixed,不可放大或缩小 static void setButtonSize(QPushButton *button, int width) { auto policy = button->sizePolicy(); policy.setHorizontalPolicy(QSizePolicy::Fixed); button->setSizePolicy(policy); // 固定宽度,加上边距 button->setFixedWidth(width + buttonMargin*2); } void ButtonEdit::setTextButton() { if (!button) { return; } // 获得当前字体下文本内容的像素宽度 auto width = QWidget::fontMetrics().width(button->text()); setButtonSize(button, width); } void ButtonEdit::setIconButton() { if (!button) { return; } // 获取图标的width简单得多 auto width = button->iconSize().width(); setButtonSize(button, width); // 设置背景和边框在非点击时不可见 button->setFlat(true); }

现在工作完成了,不管我们添加什么样的图标还是多长的文本,按钮都可以保证有一个合适的大小,输入内容也不会被按钮遮住。

现在我们看下使用:

// 方案3 // 使用文本按钮 auto edit3_1 = new ButtonEdit("clear"); QObject::connect(edit3_1, &ButtonEdit::buttonClicked, edit3_1, [edit3_1]{ edit3_1->setText(""); }); // 使用图标按钮 auto edit3_2 = new ButtonEdit(QApplication::style()->standardIcon(QStyle::SP_DialogResetButton)); QObject::connect(edit3_2, &ButtonEdit::buttonClicked, edit3_2, [edit3_2]{ edit3_2->setText(""); });

效果如下:

三种方法为QLineEdit添加清除内容按钮

这种方案是最复杂的,但也是最灵活的,我们可以定制button的外观,通过buttonClicked信号我们可以定制按钮按下后的行为。所以我在上一节才说这是扩展性最好的方法。

不过方案二和三都有一个显著的缺点,即使输入框中没有内容按钮或QAction也会一直显示,有些时候这不是我们需要的行为。解决办法也很简单,合理利用QLineEdit的信号加上QWidget::hide和QAction::setVisible就能实现按钮的隐藏,这一功能的实现就当做练习吧。

最终的显示效果

现在我们将三种方法合并显示在一起,以便大家看到各个方案带来的显示效果:

#include <QLineEdit> #include <QApplication> #include <QWidget> #include <QAction> #include <QObject> #include <QIcon> #include <QFormLayout> #include <QStyle> #include "ButtonEdit" int main(int argc, char *argv[]) { QApplication app(argc, argv); // 方案1 auto edit1 = new QLineEdit; edit1->setClearButtonEnabled(true); // 方案2 auto clearAction = new QAction; clearAction->setIcon(QIcon(":/clear.png")); auto edit2 = new QLineEdit; edit2->addAction(clearAction, QLineEdit::TrailingPosition); QObject::connect(clearAction, &QAction::triggered, edit2, [edit2]{ edit2->setText(""); }); // 方案3 // 使用文本按钮 auto edit3_1 = new ButtonEdit("clear"); QObject::connect(edit3_1, &ButtonEdit::buttonClicked, edit3_1, [edit3_1]{ edit3_1->setText(""); }); // 使用图标按钮 auto edit3_2 = new ButtonEdit(QApplication::style()->standardIcon(QStyle::SP_DialogResetButton)); QObject::connect(edit3_2, &ButtonEdit::buttonClicked, edit3_2, [edit3_2]{ edit3_2->setText(""); }); auto win = new QWidget; auto layout = new QFormLayout; layout->addRow("方案1:", edit1); layout->addRow("方案2:", edit2); layout->addRow("方案3_1:", edit3_1); layout->addRow("方案3_2:", edit3_2); win->setLayout(layout); win->show(); return app.exec(); }

当无输入内容时:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssfxx.html