Qt基于QWidget打造网速小部件SpeedMeterWidget

目标

  • 基于QWidget自定义网速小部件
  • 支持设置上行和下行方向
  • 支持自定义设置网速显示数值和单位
  • 支持动态设置上行和下行颜色

效果图

控件完整代码

SpeedMeterWidget.h

#pragma once

#include <QWidget>
#include <QPainter>
class QPaintEvent;

/// 
/// @brief: 速度仪表控件, 由箭头+文本组成, 并分别在箭头后紧跟文字,箭头朝向分为上下。同时只能显示其中的一种方向(朝上或者朝下)
/// 
class SpeedMeterWidget  : public QWidget
{
	Q_OBJECT

public:
	enum ARROW_OPTION
	{
		/// 箭头方向-向上
		AO_UP = 1,

		/// 箭头方向-向下
		AO_DOWN = 2,
	};

public:
	explicit SpeedMeterWidget(QWidget *parent = nullptr);
	virtual ~SpeedMeterWidget();

	///// 
	///// @brief:	设置背景色
	///// @param: const QString & str 
	/////  @ret:	void
	/////				
	//void setBackgroundColor(const QString& str);

	/// 
	/// @brief:	设置箭头朝向
	/// @param: const ARROW_OPTION ao 
	///  @ret:	void
	///				
	void setArrowOption(const ARROW_OPTION ao);

	/// 
	/// @brief:	设置箭头填充颜色, 颜色,比如 "#FF00FF" 
	/// @param: const QString & str 
	///  @ret:	void
	///				
	void setArrowFillColor(const QString& str);

	/// 
	/// @brief:	设置显示的文本
	/// @param: const QString & text 
	///  @ret:	void
	///				
	void setSpeedText(const QString& text);

	/// 
	/// @brief:	设置显示的文本的颜色
	/// @param: const QString & str, 颜色,比如 "#FF00FF" 
	///  @ret:	void
	///				
	void setSpeedTextColor(const QString& str);

	/// 
	/// @brief:	设置显示的文本大小
	/// @param: const int size 
	///  @ret:	void
	///				
	void setSpeedTextPointSize(const int size);

private:
	void paintEvent(QPaintEvent* event);

	/// 
	/// @brief:	绘制箭头
	/// @param: QPainter & painter 
	///  @ret:	void
	///				
	void drawArrow(QPainter& painter, const QRectF& contentRect);

	/// 
	/// @brief:	绘制自定义文字
	/// @param: QPainter & painter 
	/// @param: const QRectF & contentRect 
	///  @ret:	void
	///				
	void drawText(QPainter& painter, const QRectF& contentRect);

private:
	struct PainterHelper;

	///// 背景色
	//QString			m_backgroundColor{"#E8E8EC"};

	/// 箭头方向
	ARROW_OPTION	m_arrowOption{AO_DOWN};

	/// 箭头的填充颜色
	QString			m_arrowFillColor{"#2AEBA2"};

	/// 显示的文字内容
	QString			m_speedText{"777.0kb/s"};

	/// 显示的文字的颜色
	QString			m_speedTextColor{ "#5D6B99" };

	/// 文字的大小
	int				m_speedTextPointSize{10};
};

SpeedMeterWidget.cpp

#include "SpeedMeterWidget.h"

struct SpeedMeterWidget::PainterHelper
{
	PainterHelper(QPainter& p) : m_painter(p)
	{
		m_painter.save();
	}
	virtual ~PainterHelper()
	{
		m_painter.restore();
	}

private:
	QPainter& m_painter;
};

SpeedMeterWidget::SpeedMeterWidget(QWidget *parent)
	: QWidget(parent)
{
	setWindowFlags(Qt::FramelessWindowHint);
	setAttribute(Qt::WA_TranslucentBackground);
}

SpeedMeterWidget::~SpeedMeterWidget()
{}
//
///// 
///// @brief:	setBackgroundColor
///// @param: const QString & str - 
/////  @ret:	void
/////				
//void SpeedMeterWidget::setBackgroundColor(const QString& str)
//{
//	m_backgroundColor = str;
//	update();
//}

/// 
/// @brief:	setArrowOption
/// @param: const ARROW_OPTION ao - 
///  @ret:	void
///				
void SpeedMeterWidget::setArrowOption(const ARROW_OPTION ao)
{
	m_arrowOption = ao;
	update();
}

/// 
/// @brief:	setArrowFillColor
/// @param: const QString & str - 
///  @ret:	void
///				
void SpeedMeterWidget::setArrowFillColor(const QString& str)
{
	m_arrowFillColor = str;
	update();
}

/// 
/// @brief:	setSpeedText
/// @param: const QString & text - 
///  @ret:	void
///				
void SpeedMeterWidget::setSpeedText(const QString& text)
{
	m_speedText = text;
	update();
}

/// 
/// @brief:	setSpeedTextColor
/// @param: const QString & str - 
///  @ret:	void
///				
void SpeedMeterWidget::setSpeedTextColor(const QString& str)
{
	m_speedTextColor = str;
	update();
}

/// 
/// @brief:	setSpeedTextPointSize
/// @param: const int size - 
///  @ret:	void
///				
void SpeedMeterWidget::setSpeedTextPointSize(const int size)
{
	m_speedTextPointSize = size;
	update();
}

/// 
/// @brief:	paintEvent
/// @param: QPaintEvent * event - 
///  @ret:	void
///				
void SpeedMeterWidget::paintEvent(QPaintEvent* event)
{
	if (false == isVisible())
	{
		return;
	}

	QPainter painter(this);
	painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

	qreal ww = width() * 1.0;
	qreal hh = height() * 1.0;

	//painter.scale(ww / 200, hh / 200);

	painter.setPen(Qt::NoPen);
	
	/// 绘制背景色
	//painter.setBrush(QColor(m_backgroundColor));
	//painter.drawRect(this->rect());

	const QRectF contentRect = QRectF(0, 1, ww, hh - 2);

	/// 绘制背景色
	drawArrow(painter, contentRect);

	/// 绘制文本
	drawText(painter, contentRect);

}

/// 
/// @brief:	drawArrow
/// @param: QPainter & painter - 
///  @ret:	void
///				
void SpeedMeterWidget::drawArrow(QPainter& painter, const QRectF& contentRect)
{
	PainterHelper ph(painter);

	painter.setPen(QColor(m_arrowFillColor));
	painter.setBrush(QColor(m_arrowFillColor));

	/// 箭头的组成, 三角形 + 矩形。 三角形和矩形的高度各占控件高度的一半

	/// 箭头的宽度占控件整体宽度的1/4
	QRectF arrowRect = contentRect;
	arrowRect.setWidth(contentRect.width() / 4.0);

	/// 移动到箭头的中间
	painter.translate(arrowRect.center());

	qreal ww = arrowRect.width();
	qreal hh = arrowRect.height();



	/// 三角形
	{

		/// 用于确定箭头朝向, 1.0标识箭头朝上
		qreal valueFlag = 1.0;
		if (AO_DOWN == m_arrowOption)
		{
			valueFlag = -1.0;
		}

		QPointF arrTmp[] = 
		{
			QPointF(-ww / 2 , 0),
			QPointF(ww / 2, 0),
			QPointF(0, -hh / 2 * valueFlag)
		};
		
		painter.drawPolygon(arrTmp, 3);
	}

	/// 矩形
	{
		qreal rectW = ww / 3;
		qreal rectH = hh / 2;
		qreal rectY = 0;

		if (AO_DOWN == m_arrowOption)
		{
			rectY = -rectH;
		}

		/// 矩形与三角形相邻的边长=箭头区域宽度的一半
		painter.drawRect(-rectW / 2, rectY, rectW, rectH);
	}
}

/// 
/// @brief:	绘制自定义文字
/// @param: QPainter & painter - 
/// @param: const QRectF & contentRect - 
///  @ret:	void
///				
void SpeedMeterWidget::drawText(QPainter& painter, const QRectF& contentRect)
{
	PainterHelper ph(painter);

	painter.setPen(QPen(QColor(m_speedTextColor)));
	painter.setBrush(Qt::NoBrush);

	QFont fontTmp = painter.font();
	fontTmp.setPointSize(m_speedTextPointSize);
	painter.setFont(fontTmp);

	/// 文字占整个控件的3/4 宽
	QRectF textRect = contentRect;
	qreal tmpW = contentRect.width();
	textRect.setX(contentRect.x() + contentRect.width() / 4.0);
	textRect.setWidth(tmpW * 3.0 /4.0);

	painter.drawText(textRect, Qt::AlignCenter, m_speedText);
}

posted @ 2025-02-14 22:24  mohist  阅读(43)  评论(0)    收藏  举报