目录
- 前言
- 1、功能描述
- 2、代码实现
- 2.1 头文件
- 2.2 源码文件
- 2.3 设计思路
- 3、示例
- 4、总结
前言
本文主要介绍一个自定义控件,支持换行和点击事件的Label。起因是有这样一个需求,在一个复杂系统中有一个页面可以显示该系统中所有设备的名字,并且点击名字可以进入设备详情页。软件最初用QPushButton显示设备名字,但因为大部分设备的名字比较长,可显示的文字又太少,因此产品经理提出希望设备名称可以换行显示。于是有了本文介绍的这个自定义控件。
1、功能描述
QPushButton作为按钮,其基本功能是支持点击事件,支持设置按钮标题,支持设置按钮图标。参照QPushButton的基本功能,本自定义控件也实现了点击事件通知,设置图标,设置文本的功能,除此之外,本控件还支持设置是否换行。
2、代码实现
2.1 头文件
#ifndef ZCLICKABLELABEL_H
#define ZCLICKABLELABEL_H
#include <QLabel>
#include <QIcon>
#include <QHBoxLayout>
class ZClickableLabel : public QWidget
{
Q_OBJECT
public:
explicit ZClickableLabel(QWidget *parent = NULL);
/**
* @brief setIcon 设置图标
* @param icon 图标
*/
void setIcon(const QIcon &icon);
/**
* @brief setText 设置文本
* @param text 文本内容
* @param wordWrap 是否换行
*/
void setText(const QString &text, bool wordWrap = true);
/**
* @brief text 获取文本内容
* @return
*/
QString text() const;
signals:
/**
* @brief clicked 点击事件信号
*/
void clicked();
protected:
void mousePressEvent(QMouseEvent *ev) override;
private:
QLabel *m_pIconLabel;
QLabel *m_pTextLabel;
QHBoxLayout *m_pHlayout;
};
#endif // ZCLICKABLELABEL_H
2.2 源码文件
#include <QPaintEvent>
#include <QPainter>
#include <QSpacerItem>
#include <QtDebug>
#include "zclickablelabel.h"
static const int iconWidth = 14;
static const int iconHeight = 14;
ZClickableLabel::ZClickableLabel(QWidget *parent)
: QWidget(parent)
, m_pIconLabel(NULL)
, m_pTextLabel(NULL)
, m_pHlayout(NULL)
{
setObjectName("ZClickableLabel");
m_pTextLabel = new QLabel(this);
m_pTextLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft);
m_pHlayout = new QHBoxLayout;
m_pHlayout->addWidget(m_pTextLabel);
setLayout(m_pHlayout);
}
void ZClickableLabel::setIcon(const QIcon &icon)
{
if(!m_pIconLabel)
{
m_pIconLabel = new QLabel(this);
}
m_pIconLabel->setPixmap(icon.pixmap(iconWidth,iconHeight));
m_pIconLabel->setMaximumWidth(iconWidth);
m_pIconLabel->setMaximumHeight(iconHeight);
m_pIconLabel->setAlignment(Qt::AlignTop);
m_pHlayout->insertWidget(0, m_pIconLabel);
}
void ZClickableLabel::setText(const QString &text, bool wordWrap)
{
m_pTextLabel->setWordWrap(wordWrap);
QFontMetrics fm(m_pTextLabel->font());
int labelWidth = m_pTextLabel->rect().width();
if(fm.width(text) > labelWidth)
{
double lines = m_pTextLabel->rect().height() / fm.height();
m_pTextLabel->setText(fm.elidedText(text, Qt::ElideRight, labelWidth * lines, Qt::TextWordWrap));
}
else
{
m_pTextLabel->setText(text);
}
}
QString ZClickableLabel::text() const
{
return m_pTextLabel->text();
}
void ZClickableLabel::mousePressEvent(QMouseEvent *ev)
{
Q_UNUSED(ev)
emit clicked();
}
2.3 设计思路
该控件继承自QWidget,在QWidget内部有两个QLabel组件和一个水平布局控件,其中m_pIconLabel为图标显示控件,m_pTextLabel为文本内容显示控件。通过重载void mousePressEvent(QMouseEvent *ev)
函数,本控件实现了点击事件的获取,并将点击事件通过信号 clicked()
抛给外界使用者。
为了当文本过长显示不下时在末尾显示省略号,在setText
函数中,根据控件尺寸动态计算带省略号的文本长度,代码如下:
QFontMetrics fm(m_pTextLabel->font());
int labelWidth = m_pTextLabel->rect().width();
if(fm.width(text) > labelWidth)
{
double lines = m_pTextLabel->rect().height() / fm.height();
m_pTextLabel->setText(fm.elidedText(text, Qt::ElideRight, labelWidth * lines, Qt::TextWordWrap));
}
else
{
m_pTextLabel->setText(text);
}
如果用户设置了icon,就把m_pIconLabel 添加到控件布局m_pHlayout 上,否则不添加。这一点是在函数setIcon
中实现的。
m_pIconLabel->setPixmap(icon.pixmap(iconWidth,iconHeight));
m_pIconLabel->setMaximumWidth(iconWidth);
m_pIconLabel->setMaximumHeight(iconHeight);
m_pIconLabel->setAlignment(Qt::AlignTop);
m_pHlayout->insertWidget(0, m_pIconLabel);
3、示例
将ZClickableLabel的头文件和源码文件复制到工程目录下,并添加到测试工程中,然后在MainWindow.ui文件中添加测试控件,并将click_lb1和click_lb2两个QWidget提升为ZClickableLabel,如下图所示:
在MainWindow.cpp中实现测试代码:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->click_lb1->setText("白日依山尽,");
ui->click_lb2->setText("黄河入海流!");
ui->click_lb1->setIcon(QIcon(":/resources/icon_redTip.png"));
ui->click_lb2->setIcon(QIcon(":/resources/icon_tip.png"));
connect(ui->click_lb1, SIGNAL(clicked()), this, SLOT(slot_labelClicked()));
connect(ui->click_lb2, SIGNAL(clicked()), this, SLOT(slot_labelClicked()));
}
void MainWindow::slot_labelClicked()
{
ZClickableLabel *pLabel = qobject_cast<ZClickableLabel*>(sender());
if(pLabel)
{
QMessageBox::information(this, "提示", pLabel->text());
}
}
编译运行程序,查看效果
点击自定义控件弹出对话框:
4、总结
这种自定义控件不难,你学会了吗?以上就是本文的所有内容了,欢迎留言讨论,下一篇再见!