之前投稿时候,发现B站的标签创建框很有意思,如下图所示。按回车生成标签,点击标签或者按退格删除标签。
第一次见到这东西(在下孤陋寡闻),觉得挺有意思,而且挺有用的。趁着端午节假日休闲的下午,把它还原一下。
还是有挺多缺漏,比如删除和添加时候,滚动条好像没有滚到最合适的位置,不过因为要吃饭了,等之后用到再修改吧。还有按钮的叉叉,实在懒得找图片,所以干脆不搞了。
现在开始写下我还原的思路(这只是我的个人想法,肯定有更好的,不要被局限住了)。
首先可以无限添加,那么肯定有个ScrollArea,然后接着就是标签,为了方便响应点击,选用了Button。至于输入,因为没有做多行,所以毫不犹豫选用LineEdit。同时,为了方便插入和删除,Button和LineEdit可以统一放入Layout,方便Take和Insert。
当回车按下时,在LineEdit前插入一个Button(直接获取Layout的Count然后扣去编辑框就对了)。为了方便点击时候删除Button,把所有Button统一插入ButtonGroup去响应事件。接着就是响应LineEdit的Backspace,所以我们得继承LineEdit,然后在按键事件那边发射一个信号。
#ifndef CUSTOMEDIT_H
#define CUSTOMEDIT_H
#include
#include
class CustomEdit : public QLineEdit
{
Q_OBJECT
public:
explicit CustomEdit(QWidget* parent = nullptr);
~CustomEdit();
protected:
void keyPressEvent(QKeyEvent *event) override;
signals:
void BackspaceSignal();
};
#endif // CUSTOMEDIT_H
#include "CustomEdit.h"
#include
CustomEdit::CustomEdit(QWidget *parent) : QLineEdit(parent)
{
}
CustomEdit::~CustomEdit()
{
}
void CustomEdit::keyPressEvent(QKeyEvent *event)
{
QLineEdit::keyPressEvent(event);
if(event->key() == Qt::Key_Backspace )
{
if(text().isEmpty())
{
emit(BackspaceSignal());
}
}
}
#ifndef EDITLABEL_H
#define EDITLABEL_H
#include
#include
#include "CustomEdit.h"
#include
#include
namespace Ui {
class EditLabel;
}
class EditLabel : public QWidget
{
Q_OBJECT
public:
explicit EditLabel(QWidget *parent = nullptr);
~EditLabel();
protected:
void paintEvent(QPaintEvent* event) override;
void keyPressEvent(QKeyEvent *event) override;
private:
Ui::EditLabel *ui;
QWidget* m_pCanvas;
QScrollArea* m_pScroll;
CustomEdit* m_pEdit;
QHBoxLayout* m_pHLayout;
QButtonGroup* m_pBtnGroup;
private slots:
void DeleteItem();
void DeleteButton(QAbstractButton *button);
};
#endif // EDITLABEL_H
#include "EditLabel.h"
#include "ui_EditLabel.h"
#include
#include
#include
#include
#include
EditLabel::EditLabel(QWidget *parent) :
QWidget(parent),
ui(new Ui::EditLabel)
{
ui->setupUi(this);
m_pCanvas = new QWidget;
m_pScroll = new QScrollArea(this);
m_pScroll->resize(200, 50);
m_pScroll->setWidget(m_pCanvas);
m_pScroll->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_pScroll->setWidgetResizable( true );
m_pEdit = new CustomEdit(this);
m_pHLayout = new QHBoxLayout(m_pCanvas);
m_pBtnGroup = new QButtonGroup(this);
m_pHLayout->addWidget(m_pEdit);
m_pHLayout->setMargin(1);
setObjectName(QStringLiteral("editlabel"));
m_pCanvas->setObjectName(QStringLiteral("canvas"));
m_pScroll->setObjectName(QStringLiteral("scroll"));
m_pEdit->setObjectName(QStringLiteral("edit"));
setStyleSheet(QStringLiteral("QWidget#editlabel{border: none;}"));
m_pCanvas->setStyleSheet(QStringLiteral("QWidget#canvas{background-color:white;}"));
m_pScroll->setStyleSheet(QStringLiteral("QScrollArea#scroll{border:1px solid rgb(241, 91, 108); border-radius: 6px;background-color:white;padding: 2px;}"));
m_pEdit->setStyleSheet(QStringLiteral("QLineEdit#edit{border: none;font-family:Microsoft Yahei; font-size: 14px;}"));
m_pScroll->setAlignment(Qt::AlignLeft | Qt::AlignTop);
m_pScroll->setFixedHeight(50);
m_pEdit->setFixedSize(150, 20);
m_pEdit->setPlaceholderText(QObject::tr("按回车键创建标签"));
connect(m_pEdit, &CustomEdit::BackspaceSignal, this, &EditLabel::DeleteItem);
connect(m_pBtnGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked), this, &EditLabel::DeleteButton);
}
EditLabel::~EditLabel()
{
delete ui;
}
void EditLabel::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void EditLabel::keyPressEvent(QKeyEvent *event)
{
QWidget::keyPressEvent(event);
if(event->key() == Qt::Key_Return && m_pEdit->hasFocus())
{
QString content = m_pEdit->text();
QFont font;
font.setFamily("Microsoft Yahei");
font.setPointSize(14);
QFontMetrics fm(font); // 获取字体像素宽高
QPushButton* pBtn = new QPushButton(m_pScroll);
pBtn->setFont(font);
pBtn->setText(content);
pBtn->setFixedSize(fm.horizontalAdvance(content) + 5, fm.height());
pBtn->setStyleSheet(QStringLiteral("QPushButton{border-radius:5px;background-color:rgb(241,91,108);}"));
pBtn->setCursor(QCursor(Qt::PointingHandCursor));
int cnt = m_pHLayout->count();
m_pHLayout->insertWidget(cnt - 1, pBtn, Qt::AlignCenter);
m_pBtnGroup->addButton(pBtn);
m_pEdit->clear(); // 输入完一次后要清空
m_pScroll->horizontalScrollBar()->setValue(m_pScroll->horizontalScrollBar()->maximum()); // 滚到当前最大值
}
}
void EditLabel::DeleteItem()
{
int cnt = m_pHLayout->count();
if(cnt <= 1) return;
auto item = m_pHLayout->itemAt(cnt - 2);
m_pHLayout->removeItem(item);
item->widget()->setParent(nullptr);
delete item;
item = nullptr;
}
void EditLabel::DeleteButton(QAbstractButton *button)
{
int cnt = m_pHLayout->count();
cnt -= 1;
for(int i = 0; i < cnt; i++)
{
auto item = m_pHLayout->itemAt(i);
if(item->widget() == button)
{
m_pHLayout->removeItem(item);
item->widget()->setParent(nullptr);
delete item;
item = nullptr;
return;
}
}
}
滚动条这边因为还要资源文件,所以就没贴出来了,需要的自己写下style很快的。
如果有更好的方法或者建议,欢迎评论区讨论。