B站的标签创建框 之前投稿时候,发现B站的标签创建框很有意思,如下图所示。按回车生成标签,点击标签或者按退格删除标签。
文章图片
第一次见到这东西(在下孤陋寡闻),觉得挺有意思,而且挺有用的。趁着端午节假日休闲的下午,把它还原一下。
自己的标签框 以下是还原效果图
文章图片
还是有挺多缺漏,比如删除和添加时候,滚动条好像没有滚到最合适的位置,不过因为要吃饭了,等之后用到再修改吧。还有按钮的叉叉,实在懒得找图片,所以干脆不搞了。
文章图片
设计思路 现在开始写下我还原的思路(这只是我的个人想法,肯定有更好的,不要被局限住了)。
首先可以无限添加,那么肯定有个ScrollArea,然后接着就是标签,为了方便响应点击,选用了Button。至于输入,因为没有做多行,所以毫不犹豫选用LineEdit。同时,为了方便插入和删除,Button和LineEdit可以统一放入Layout,方便Take和Insert。
当回车按下时,在LineEdit前插入一个Button(直接获取Layout的Count然后扣去编辑框就对了)。为了方便点击时候删除Button,把所有Button统一插入ButtonGroup去响应事件。接着就是响应LineEdit的Backspace,所以我们得继承LineEdit,然后在按键事件那边发射一个信号。
继承QLineEdit,响应Backspace
#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_OBJECTpublic:
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::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;
}
}
}
【记录|Qt自定义控件-----仿B站标签创建框】滚动条这边因为还要资源文件,所以就没贴出来了,需要的自己写下style很快的。
如果有更好的方法或者建议,欢迎评论区讨论。
文章图片
推荐阅读
- QT|QT中自定义注释模板整理
- Qt|Qt : 自定义委托类.子类化QStyledItemDelegate
- qt|C++图形用户界面开发框架Qt 6.x入门级教程 - 开发工具简介
- Qt基础|c++ qt自定义搜索编辑框
- c++|2011-2012工作总结
- c++|PTA堆栈—有效括号判断
- codeforce|Codeforces Round #774 (Div. 2) D. Weight the Tree
- CPU底层|【CPU底层那些事(数组和指针真的一样吗()】)
- linux|GNU ARM 汇编指令(转)