Qt 空调遥控按钮

最近优化软件外观,做了一个很像空调遥控按钮的东西。分享一下

1.效果

2. 代码

#pragma once
#include <qwidget.h>
#include <qdebug.h>
#include <qpainter.h>
#include <QEnterEvent>
#include <QPaintEvent>
#include <QMouseEvent>
#include <QResizeEvent>


namespace mortal
{
	const float PI = 3.1415926;
	enum class Direction
	{
		without = 0b0000,
		up      = 0b0001,
		left    = 0b0010,
		down    = 0b0011,
		right   = 0b0100
	};
	class ControlButton : public QWidget
	{
		Q_OBJECT
	signals:
		void SignalHaveDown(Direction button);
	private:
		Direction now_button_down_;
		Direction now_mouse_in_;
		QColor in_circle_color_ , background_color_ , mouse_in_color_;
		float in_circle_shadow_radius_;
		QRadialGradient down_color_;
		QVector<QString> button_text_;
		QColor text_normal_color_, text_down_color_;
		QFont text_font_;
		float low_side_;
		float in_radius_, out_radius_;
		QPoint center_point_;
		bool press_last;

		QPoint GetRotatePoint(float radius, float angle)
		{
			return QPoint(radius * cos(angle * PI / 180), radius * sin(angle * PI / 180));
		}
		void DrawBackgroundCircle(QPainter &painter, float radius)
		{
			painter.save();
			QPen pen;
			pen.setColor(background_color_);
			painter.setPen(pen);
			QBrush brush(background_color_);
			painter.setBrush(brush);
			painter.drawEllipse(QPoint(0, 0), static_cast<int>(radius), static_cast<int>(radius));
			painter.restore();
		}
		void DrawInCircle(QPainter &painter, float radius)
		{
			painter.save();
			QPen pen;
			pen.setColor(in_circle_color_);
			painter.setPen(pen);
			QBrush brush(in_circle_color_);
			painter.setBrush(brush);
			painter.drawEllipse(QPoint(0, 0), static_cast<int>(radius), static_cast<int>(radius));
			painter.restore();
		}
		void DrawInCircleShadow(QPainter &painter, float radius)
		{
			painter.save();
			QRadialGradient shadow_color(QPoint(0, 0), radius , QPoint(0,0));
			shadow_color.setColorAt(0, Qt::black);
			shadow_color.setColorAt(1, background_color_);

			QPen pen;
			pen.setColor(background_color_);
			painter.setPen(pen);
			QBrush brush(shadow_color);
			painter.setBrush(brush);
			painter.drawEllipse(QPoint(0, 0), static_cast<int>(radius), static_cast<int>(radius));
			painter.restore();
		}
		QRect GetArcRect(int radius)
		{
			QRect rect(QPoint(-radius , -radius) , QSize(2*radius,2*radius));
			return rect;
		}
		void DrawButton(QPainter& painter ,const QRect &rect,int radius , Direction should_draw)
		{
			painter.save();
			if (should_draw != now_button_down_)
			{
				QPen pen;
				if (should_draw == now_mouse_in_)
				{
					pen.setColor(mouse_in_color_);
				}
				else
				{
					pen.setColor(in_circle_color_);
				}
				pen.setWidth(0.5 * radius);
				pen.setCapStyle(Qt::PenCapStyle::FlatCap);
				painter.setPen(pen);
				int begine_angle = 45 + (static_cast<int>(should_draw) - 1)*90;
				int arc_long = 90;

				painter.drawArc(rect, begine_angle * 16, arc_long * 16);
			}
			else
			{
				QBrush brush(down_color_);
				painter.setBrush(brush);

				int begine_angle = 45 + (static_cast<int>(should_draw) - 1) * 90;
				int pie_long = 90;
				int true_radius = radius ;
				QRect down_rect(QPoint(- true_radius , - true_radius),QSize(true_radius*2 , true_radius*2));
				painter.drawPie(down_rect, begine_angle * 16, pie_long * 16);
			}

			painter.restore();
		}
		void DrawLine(QPainter& painter, float out_radius, float in_radius, float width)
		{
			painter.save();
			int begin_angle = 45;
			QPen pen;
			pen.setColor(background_color_);
			pen.setWidth(width);
			pen.setCapStyle(Qt::PenCapStyle::FlatCap);
			painter.setPen(pen);
			for (int i = 0; i < 4; i++)
			{
				painter.drawLine(GetRotatePoint(in_radius, begin_angle), GetRotatePoint(out_radius, begin_angle));
				begin_angle += 90;
			}
			painter.drawEllipse(QPoint(0, 0), int(out_radius), int(out_radius));
			painter.restore();
		}
		void DrawTriangle(QPainter &painter, Direction should_draw)
		{
			painter.save();
			QPoint one , two , three;
			float should_rotate = 90 * static_cast<int>(should_draw);
			float rotate_angle = 3;
			
			one = GetRotatePoint(470, - should_rotate);
			two = GetRotatePoint(446, - (should_rotate + rotate_angle));
			three = GetRotatePoint(446,-(should_rotate - rotate_angle));

			
			QBrush brush(down_color_);

			QPolygon local_poly;
			local_poly << one << two << three;
			QPainterPath linshi;
			linshi.addPolygon(local_poly);
			painter.fillPath(linshi, brush);
			
			painter.restore();

		}
		void DrawButtonText(QPainter& painter, Direction should_draw)
		{
			painter.save();
			QPen pen;
			if (should_draw == now_button_down_)
			{
				pen.setColor(text_down_color_);
			}
			else
			{
				pen.setColor(text_normal_color_);
			}
			painter.setPen(pen);
			painter.setFont(text_font_);
			float should_rotate = -90 * static_cast<int>(should_draw);
			QRect rect(GetRotatePoint(0.75 * 450, should_rotate), QSize(200, 100));
			rect.adjust(-100, -50, -100, -50);

			painter.drawText(rect, Qt::AlignCenter, button_text_[static_cast<int>(should_draw) - 1]);
			painter.restore();
		}
	protected:
		void paintEvent(QPaintEvent *event)override
		{

			QPainter painter(this);
			painter.translate(this->rect().width() / 2, this->rect().height() / 2);
			painter.scale(low_side_ / 1000, low_side_ / 1000);
			painter.setRenderHint(QPainter::Antialiasing);

			int radius = 450;
			float in_circle_radius = 0.25;

			QRect rect = GetArcRect(0.75 * radius);
			for (int i = 1; i <= 4; i++)
			{
				this->DrawButton(painter, rect, radius, static_cast<Direction>(i));
			}
			this->DrawBackgroundCircle(painter, 0.5 * radius);
			this->DrawInCircleShadow(painter, (in_circle_shadow_radius_ + in_circle_radius) * radius);
			this->DrawInCircle(painter, radius * in_circle_radius);
			this->DrawLine(painter, radius, 0.5 * radius, 10);
			if (now_button_down_ != Direction::without)
			{
				this->DrawTriangle(painter, now_button_down_);
			}
			for (int i = 1; i <= 4; i++)
			{
				this->DrawButtonText(painter, static_cast<Direction>(i));
			}


		}
		void enterEvent(QEvent* event)override 
		{
			this->setMouseTracking(true);
		}
		void leaveEvent(QEvent* event)override
		{
			this->setMouseTracking(false);
		}
		void resizeEvent(QResizeEvent* event)override
		{
			low_side_ = (this->width() < this->height() ? this->width() : this->height());
			in_radius_ = pow(low_side_ /4 ,2) ;
			out_radius_ = pow(low_side_/2 * 0.9,2);
			center_point_ = QPoint(this->width() / 2, this->height() / 2);
			;//TODO
		}
		void mousePressEvent(QMouseEvent* event)override
		{
			if (now_mouse_in_ != Direction::without)
			{
				if (press_last == false)
				{
					now_button_down_ = now_mouse_in_;
				}
				else
				{
					if (now_button_down_ == now_mouse_in_)
					{
						now_button_down_ = Direction::without;
					}
					else
					{
						now_button_down_ = now_mouse_in_;
					}
				}
				this->repaint();
			}
		}
		void mouseReleaseEvent(QMouseEvent* event)override
		{
			if (now_mouse_in_ == now_button_down_)
			{
				if (press_last == false)
				{
					emit SignalHaveDown(now_button_down_);
					now_button_down_ = Direction::without;
				}
				else
				{
					emit SignalHaveDown(now_button_down_);
				}
			}
			else
			{
				now_button_down_ = Direction::without;
			}
			this->repaint();
		}
		void mouseMoveEvent(QMouseEvent* event)override
		{
			QPoint mouse_pos =  event->pos();
			float distance;
			QPoint linshi = mouse_pos - center_point_;
			distance = pow(linshi.x(), 2) + pow(linshi.y(), 2);
			int flags = 0;
			if (distance < out_radius_ && distance > in_radius_)
			{
				float cos_angle = QPoint::dotProduct(linshi, QPoint(1, 0)) /sqrt((pow(linshi.x(),2)+pow(linshi.y() ,2)));
				float angle = (acos(cos_angle) * 180.0 /PI);
				if (linshi.y() > 0)
				{
					angle = 360 - angle;
				}
				
				
				if (angle > 315 || angle < 45)
				{
					flags = 4; 
				}
				else if (angle < 315 && angle > 225)
				{
					flags = 3;
				}
				else if (angle < 225 && angle > 135)
				{
					flags = 2;
				}
				else if (angle < 135 && angle > 45)
				{
					flags = 1;
				}
				
			}

			if (now_mouse_in_ != static_cast<Direction>(flags))
			{
				now_mouse_in_ = static_cast<Direction>(flags);
				this->repaint();
			}
			;//TODO
		}
	public:
		ControlButton()
			: button_text_{"上","左","下","右"}
		{
			
			now_button_down_ = Direction::without;
			now_mouse_in_ = Direction::without;

			background_color_ = QColor("#CEDAE8");

			in_circle_color_ = Qt::white;
			in_circle_shadow_radius_ = 0.075;

			mouse_in_color_ = QColor("#E8EDF3");
			down_color_ = QRadialGradient(0, 0, 500, 0, 0);
			down_color_.setColorAt(0.5, QColor("#4392CB"));
			down_color_.setColorAt(1, QColor("#00f2fe"));

			text_normal_color_ = Qt::black;
			text_down_color_ = Qt::white;
			text_font_ = QFont("Hei", 50);

			press_last = false;
		}
		~ControlButton() {}
		void SetFLoatColor(const QColor& color = QColor("#E8EDF3")) { mouse_in_color_ = color; }
		void SetBackgroundColor(const QColor& color = QColor("#CEDAE8")) { background_color_ = color; }
		void SetNormalColor(const QColor& color = Qt::white) { in_circle_color_ = color; }
		void SetInCircleShadowRadius(float radius = 0.075) { in_circle_shadow_radius_ = radius; }
		void SetDownColor(QColor begin_color = QColor("#4392CB"), QColor end_color = QColor("#00f2fe"))
		{
			down_color_.setColorAt(0.5, begin_color);
			down_color_.setColorAt(1, end_color);

		}
		void SetTextString(const QVector<QString>& text)
		{
			button_text_.clear();
			for (auto i : text)
			{
				button_text_.append(i);
			}
		}
		void SetTextColor(QColor normal = Qt::black, QColor down = Qt::white)
		{
			text_normal_color_ = normal;
			text_down_color_   = down;
		}
		void SetTextFont(QFont font = QFont("Hei", 50))
		{
			text_font_ = font;
		}
		void SetPressKeep(bool keep = false) { press_last = keep; }
	};
};

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值