n,在这里我们先把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(""); });
效果如下:
这种方案是最复杂的,但也是最灵活的,我们可以定制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()->stan