QT实现蓝色提示气泡绘制、显隐时机、移动、方向切换等功能

功能描述

很多软件中会有类似下面这种的蓝色提示气泡,目的是为了引导或提示用户如何操作。
气泡上附有提示信息和一个可以点击的按钮。
在这里插入图片描述
在这里插入图片描述
下面绘制一个提示气泡,该气泡是提示用户第一步需要先点击导航栏上的“浏览器”图标。
跟随导航栏移动
实现“躲避屏幕边缘”机制,当导航栏位置到屏幕左侧的距离大于气泡长度,气泡显示在导航栏左侧,反之显示在右侧。
在这里插入图片描述
在这里插入图片描述
气泡显示时机

  1. 启动软件,不点击气泡上的按钮及提示用户操作的按钮
  2. 重新安装软件

气泡关闭时机

  1. 点击气泡上“不再提示”的按钮
  2. 点击提示用户操作的按钮

代码实现

.h文件

//三角形的高度
#define DEF_TRIANGLE_HEIGHT 8
//透明宽度
#define TRANSPARENT_LENGTH 10

enum class ENDIRECT {
	DIRECT_LEFT = 1,
	DIRECT_TOP,
	DIRECT_RIGHT,
	DIRECT_BOTTOM
};
class BubbleTipsWidget : public QWidget
{
	Q_OBJECT
public:
	explicit BubbleTipsWidget(QWidget *parent = nullptr);

	void setBackColor(int r, int g, int b, int a = 255);
	void setDirect(ENDIRECT direct);
	void setContentFont(QFont font = {});
	void setContent(const QString &content, QColor color = {});
	bool isClickTips();

private slots:
	void slotClickTips();

protected:
	void paintEvent(QPaintEvent *event);

private:
	QColor m_backColor;
	ENDIRECT m_direct;
	QLabel *m_pLabel;
	QWidget *m_pParent;
	QPushButton *m_pTipsButton;
	QLockFile *m_pLockFile;
};

.cpp文件(绘制气泡)

#pragma region 提示气泡
/**
* @brief        气泡按钮样式
* @return       void
*/
static void setBubbleButtonStyle(QPushButton *pTipsButton, QHBoxLayout *layout, QSize oButtonSize)
{
	pTipsButton->setFixedSize(oButtonSize);
	pTipsButton->setText(QStringLiteral("不再提示"));

	//设置按钮样式、按下时的状态
	pTipsButton->setStyleSheet("QPushButton{background-color:rgb(91, 181, 250);border-radius:2px;}"
		"QPushButton{color:rgb(255, 255, 255);}"
		"QPushButton:pressed{background-color:rgb(80, 170, 240);}");

	QAction *oAct = new QAction();
	QFont oButtonFont = oAct->font();
	oButtonFont.setFamily("Microsoft YaHei");//设置字体为微软雅黑
	oButtonFont.setPixelSize(14);
	pTipsButton->setFont(oButtonFont);

	layout->addWidget(pTipsButton);
}

BubbleTipsWidget::BubbleTipsWidget(QWidget *parent)
	: QWidget(parent)
{
	m_pParent = parent;
	setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);//窗口无边框效果
	setAttribute(Qt::WA_TranslucentBackground);//窗口透明显示

	//窗体尺寸
	int nWidth = 190;
	int nHeight = 40;
	resize(nWidth, nHeight);
	setMinimumSize(nWidth, nHeight);

	QHBoxLayout *pMainLayout = new QHBoxLayout;
	m_pLabel = new QLabel();
	pMainLayout->addWidget(m_pLabel);

	//“不在提示”按钮
	m_pTipsButton = new QPushButton();
	QSize oButtonSize(65, 20);//按钮尺寸
	setBubbleButtonStyle(m_pTipsButton, pMainLayout, oButtonSize);

	setLayout(pMainLayout);

	//获得导航栏位置,定位气泡
	QPoint oParentPoint = m_pParent->pos();
	int oParentPointX = oParentPoint.x() - this->width();
	int oParentPointY = oParentPoint.y() + TRANSPARENT_LENGTH;
	this->move(oParentPointX, oParentPointY);

	connect(m_pTipsButton, SIGNAL(clicked()), this, SLOT(slotClickTips()));
}

/**
* @brief        气泡背景色
* @return       void
*/
void BubbleTipsWidget::setBackColor(int r, int g, int b, int a)
{
	m_backColor = QColor(r, g, b, a);
}

/**
* @brief        气泡三角方向
* @return       void
*/
void BubbleTipsWidget::setDirect(ENDIRECT direct)
{
	m_direct = direct;
}

/**
* @brief        气泡提示信息字体
* @return       void
*/
void BubbleTipsWidget::setContentFont(QFont font)
{
	this->setFont(font);
}

/**
* @brief        气泡提示信息颜色
* @return       void
*/
void BubbleTipsWidget::setContent(const QString &content, QColor color)
{
	m_pLabel->setText(content);
	m_pLabel->setStyleSheet(QString("color: rgb(%1, %2, %3)")
		.arg(color.red())
		.arg(color.green())
		.arg(color.blue()));
}

/**
* @brief        通过是否生成lock.txt文件,判断用户是否点击过气泡上“不再提示”按钮或提示用户操作的按钮,用于显隐
* @brief        lock.txt文件会跟随软件的拆卸而删除
* @return       bool
*/
bool BubbleTipsWidget::isClickTips()
{
	//获取程序当前运行目录
	QString strFilePath = QCoreApplication::applicationDirPath();
	QFileInfo oFile(strFilePath + "/lock.txt");
	if (oFile.isFile())
	{
		return true;
	}

	return false;
}

/**
* @brief        点击过气泡上“不再提示”按钮,会生成一个lock.txt文件
* @return       void
*/
void BubbleTipsWidget::slotClickTips()
{
	//添加文件锁
	QString strFilePath = QCoreApplication::applicationDirPath() + "/lock.txt";
	QFile oFile(strFilePath);
	if (!oFile.open(QFile::WriteOnly | QFile::Text))
	{
		return;
	}

	this->close();
}

/**
* @brief        重绘气泡
* @return       void
*/
void BubbleTipsWidget::paintEvent(QPaintEvent *event)
{
	int nBubbleWidth = width();
	int nBubbleHeight = height();

	QPainter painter(this);
	painter.setRenderHints(QPainter::Antialiasing);
	painter.setPen(Qt::NoPen);
	painter.setBrush(m_backColor);

	//相对于当前布局的起点坐标
	painter.drawRoundedRect(DEF_TRIANGLE_HEIGHT, 0,
		nBubbleWidth - DEF_TRIANGLE_HEIGHT * 2,
		nBubbleHeight, 2, 2);

	QPointF points[3];

	switch (m_direct)
	{
	case ENDIRECT::DIRECT_LEFT:
	{
		points[0] = QPointF(0, nBubbleHeight * 0.5);
		points[1] = QPointF(DEF_TRIANGLE_HEIGHT, nBubbleHeight * 0.3);
		points[2] = QPointF(DEF_TRIANGLE_HEIGHT, nBubbleHeight * 0.7);
		break;
	}

	case ENDIRECT::DIRECT_RIGHT:
	{
		points[0] = QPointF(nBubbleWidth, nBubbleHeight * 0.5);
		points[1] = QPointF(nBubbleWidth - DEF_TRIANGLE_HEIGHT, nBubbleHeight * 0.3);
		points[2] = QPointF(nBubbleWidth - DEF_TRIANGLE_HEIGHT, nBubbleHeight * 0.7);
		break;
	}
	default:
		break;
	}

	painter.drawPolygon(points, 3);
}
#pragma endregion

.cpp文件(功能逻辑实现)
ToolbarViewForm为导航栏窗体类

ToolbarViewForm::ToolbarViewForm(QWidget *parent) :
	QDialog(parent)
{
	bubbleTips();
	connect(m_pBrowserPushButton, SIGNAL(clicked()), this, SLOT(slotClickBrowserPushButton()));
}

/**
* @brief        气泡提示框
* @return       void
*/
void ToolbarViewForm::bubbleTips()
{
	m_pBubbleWgt = new BubbleTipsWidget(this);	//this为将导航栏窗体作为父窗体传入,主要用于获取导航栏的实时位置
	if (m_pBubbleWgt->isClickTips())
	{
		return;
	}

	QFont oFont;
	oFont.setFamily("Microsoft YaHei");
	oFont.setPixelSize(14);
	m_pBubbleWgt->setContentFont(oFont);
	m_pBubbleWgt->setBackColor(0, 145, 255, 240);
	m_pBubbleWgt->setDirect(ENDIRECT::DIRECT_RIGHT);
	m_pBubbleWgt->setContent(QStringLiteral("请先打开浏览器"), QColor(Qt::white));

	m_pBubbleWgt->show();
}

/**
* @brief        点击浏览器按钮响应的槽函数,点击按钮生成lock.txt文件,并关闭气泡
* @return       void
*/
void ToolbarViewForm::slotClickBrowserPushButton()
{
	//添加文件锁
	QString strFilePath = QCoreApplication::applicationDirPath() + "/lock.txt";
	QFile oFile(strFilePath);
	if (!oFile.open(QFile::WriteOnly | QFile::Text))
	{
		return;
	}

	m_pBubbleWgt->close();
}

mousePressEvent,mouseMoveEvent为两个鼠标事件,实现导航栏随意拖动。

void ToolbarViewForm::mousePressEvent(QMouseEvent *event)
{
	this->m_windowPos = this->pos();       // 获得部件当前位置
	this->m_mousePos = event->globalPos(); // 获得鼠标位置
	this->m_dPos = m_mousePos - m_windowPos;   // 移动后部件所在的位置
}

void ToolbarViewForm::mouseMoveEvent(QMouseEvent *event)
{
	this->move(event->globalPos() - this->m_dPos);

	//气泡移动
	moveBubbleWgt();
}

/**
* @brief        气泡跟随导航栏移动,并在满足条件时改变气泡方向
* @return       void
*/
void ToolbarViewForm::moveBubbleWgt()
{
	int nToolbarWgtWidth = this->width();
	if (m_pBubbleWgt)
	{
		if (this->x() - m_pBubbleWgt->width() > 0)
		{
			m_pBubbleWgt->setDirect(ENDIRECT::DIRECT_RIGHT);
			m_pBubbleWgt->move(this->x() - m_pBubbleWgt->width(), this->y() + TRANSPARENT_LENGTH);
		}
		else
		{
			m_pBubbleWgt->setDirect(ENDIRECT::DIRECT_LEFT);
			m_pBubbleWgt->move(this->x() + nToolbarWgtWidth, this->y() + TRANSPARENT_LENGTH);
		}
		m_pBubbleWgt->update();
	}
}
  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值