Qt实现环形拖动旋转框

目的

本来设计如图一个环形属性旋转框, 其难点是在于如何在一个圆形的窗口中 如何鼠标拖动指示器实现旋转并依据角度变化, 依据设计范围准确显示当前值。

可能有些会想到利用顺时针, 逆时针, 这虽然是一个好的想法idea, 那么问题来了? 你怎么判断顺时针,逆时针, 这个想法设计我网上搜了下, 感觉问题相对来说就弄复杂了。

一种方法就是可以参考环形进度条原理, 去设计。 我只需要找一个相对某个初始化参考位置, 另一个位置变化, 然后求出转动角度(0-360),结合你给定的数值范围, 360° ,可以求出当前位置的数值。稍微难一点在于如何求出两者之间夹角, 以及弧度与角度转换。
如何求夹角
c++ 弧度值与角度值的转换
数学函数库

double Rad_to_deg  = 45.0 / atan(1.0);
弧度值到角度值的转换  用   角度 =  弧度值* Rad_to_deg 
角度值到弧度值的转换  用  弧度值 = 角度 /  Rad_to_deg

我采用的是三点求夹角, 通过向量夹角余弦公式法

比如已知三点M(1,1),A(2,2),B(2,1)求角度∠AMB
1.先求向量MA,MB
向量公式 MA=(A.x-M.x)i+(B.x-M.x)j
所以:
MA=(2-1,2-1)=(1,1)
MB=(2-1,1-1)=(1,0)
则两向量的数量积为:
MA*MB=1×1+1×0=1
2.求向量的模
向量的模=sqrt(x*x+y*y)
|MA|=√(1×1)+(1×1)=√2
|MB|=√(1*1)+(0*0)=√1
将以上结果带入向量夹角余弦公式得:
cos∠AMB=MA*MB/|MA|*|MB|=√2/2
则∠AMB=45度

核心思路 :以圆心为原点, 正y轴向上一定长度某个点为一个点, 另一个点为窗口鼠标移动或者点击某个点, 然后求其三点之间夹角。

Qt实现环形拖动旋转框
代码: 返回的值是0-360.

double DashBoardWidget::getAngle(const QPointF &point)
{
   QPointF v1(m_yOriginPos.x()  - m_originPos.x(), m_yOriginPos.y()  - m_originPos.y());
   QPointF v2(point.x() - m_originPos.x(), point.y() - m_originPos.y());
   double N(v2.x() * v1.x() + v2.y() * v1.y());
   double M1 = sqrt(v1.x() * v1.x() + v1.y() * v1.y());
   double M2 = sqrt(v2.x() * v2.x() + v2.y() * v2.y());
   double cosValue = N / (M1 * M2);
   double radtoDeg = 45.0 / atan(1.0);
   bool positiveAngle = (point.x() >= m_originPos.x()) ? true : false;
   double cos = radtoDeg * acos(cosValue);
   double realAngle = cos;
   if(!positiveAngle){
       realAngle = 360.0 - realAngle;
   }
   qDebug() << __FUNCTION__ << "cosValue!" << cos << realAngle;
//   double angel = acos(cosValue);
   return realAngle;
}

如下是网上搜到较多的仪表盘之类的博客, 可看看, 拓展思路
博客大佬一
QPainter中坐标系变换问题
基本图形绘制
Qt实现环形拖动旋转框
大佬博客二

上一篇:如何在 Linux 安装 MySQL 数据库


下一篇:Java学习——HashMap