QToolTip类为任何小部件提供工具提示(气球帮助)。提示是一小段文字,提醒用户小部件的功能。它是在一个独特的黑黄色组合中直接在给定位置下方绘制的。提示可以是任何富文本格式的字符串。
在这里需要用到的函数主要是void QToolTip::showText ( const QPoint & pos, const QString & text, QWidget * w, const QRect & rect ) [static] ,在Event中实现。
pos为全局坐标点位,显示文本text,w用于指定需要显示提示信息的窗口小部件,rect若为非空矩形,则鼠标移出该矩形便隐藏显示。
用到QHelpEvent,该类提供了一个事件,用于请求有关窗口小部件中特定点的有用信息。在应用程序中拦截此事件用以提供工具提示。
在项目此部件中,需要实现的效果是:当用户鼠标触碰到玫瑰图中的扇形数据显示区域时,浮窗显示此扇形所处角度区间,显示包含角度及其个数,对于相同的角度需要统计个数。
实现思路:除去使用showText函数辅助实现功能,此时主要问题在于如何判断当鼠标处于扇形之内时,显示相对应的数据信息。一个思路是,判断当前鼠标的坐标是否在圆形坐标系内,若在时,求该点与圆心的差值,这个差值可等同于该点在以圆心为原点的坐标系中的情况。(因为得到的鼠标坐标是相对于整个窗口的,而需要确定的扇形角度信息是在相对于圆心为原点的坐标系中的)在这里使用了qAtan2(y,x)反正切函数,此函数返回传入点的弧度。通过这个函数传入经过相应变换处理的坐标,就可以确定鼠标坐标相对于圆心的角度。在对这个角度与玫瑰图的角度数据数组进行比较,即可实现。、
相关代码如下:
bool GRoseView::event(QEvent* event)
{
if(event->type() == QEvent::ToolTip)
{
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
double px = helpEvent->x();
double py = helpEvent->y();
QString s = angleMessageTip(px,py);
QToolTip::showText(helpEvent->globalPos(),s);
}
return QWidget::event(event);
}
QString GRoseView::angleMessageTip(double x,double y)
{
double dx = x - mCenter.x();
double dy = y - mCenter.y();
if(qSqrt(dx*dx + dy*dy) > mMaxRadius) return QString::null;
double pointAngle = getPointAngle(x,y);
int angleL = 0;
int angleH = mdeltAngle;
QString s = QString::null;
qSort(mDatas);
while(angleH <= 360)
{
int number = 0;
if(pointAngle >=angleL && pointAngle <angleH)
{
s = ("Angle range :" + QString::number(angleL) + QString::fromLocal8Bit("") + "-"
+ QString::number(angleH) + QString::fromLocal8Bit("") +"\n");
for(int i = 0;i < mDatas.count(); i++)
{
if(mDatas[i] >= angleL && mDatas[i] < angleH)
{
if(i != mDatas.count()-1)
{
if(mDatas[i] == mDatas[i+1])
{
number++;
}
else
{
s += QString::number(mDatas[i]) + QString::fromLocal8Bit("") + " "+QString::number(number+1)+"\n";
number = 0;
}
}
else
{
number = 0;
s += QString::number(mDatas[i]) + QString::fromLocal8Bit("") + " "+QString::number(number+1)+"\n";
}
}
}
break;
}
else
{
angleL = angleH;
angleH += mdeltAngle;
}
}
return s;
}
double GRoseView::getPointAngle(double x,double y)
{
double x1,y1;
double pointRadian,pointAngle;
y1 = x - mCenter.x();
x1 = mCenter.y() - y;
if(x >= mCenter.x()) //[0,pi]
{
pointRadian = qAtan2(y1,x1);
}
else //[pi,2*pi]
{
pointRadian = qAtan2(y1,x1) + 2*PI ;
}
pointAngle = 180*pointRadian/PI;
return pointAngle;
}