Qt中关于menu菜单的定位以及相关注意事项

      上篇文章讲了如何定制menu。但是对于这个menu,我们是要有个动作来触发它的显示的,并且要将其显示在一个合适的位置。对于这两个问题我在做项目过程发现还是有一些值得注意的地方的。

 

       我要实现的功能是:对于一个button,我希望在长按3s之后,menu会显示在该button的正下方。

       对于这个功能其实就是创建一个QMenu对象,而后在创建一个定时器,在press这个button时候启动,过3s让其show出来。而release时候则将该定时器stop。  原本这样做下来的确实现了最初的想法,但是却产生了两个新的问题:

 

       问题①: 当release该Button时发现button并没有弹起,需要你再去click一下才能弹起。

       问题②:显示出来的menu定位不准。

 

       解答如下:

       1:对于QMenu菜单而言:其默认是一个顶层窗口!当它显示出来的时候:其必然获得foucs焦点。所以此后button已经没有焦点了,当然接受不到release事件,从而无法弹起。

       2:默认的QMenu菜单,不管其父对象设置成哪个widget,其坐标系都是以整个屏幕为准的(屏幕的左上角为坐标原点),而不是常规的以其父窗口或者该app应用程序为准的,这点切记!

 

       对于问题1,这个牵扯到焦点的问题,我们必然是要在menu显示时让其获得焦点,亦即:button必然获得不了焦点,从而弹不起来。这个矛盾解决不了,所以需要改变原先的设计,后来改成:当button被release弹起之后才显示这个menu,这样就OK了。

 

      对于问题2,这个关键是坐标系转换了。只要我们先将这个button针对屏幕的全局坐标获得,而后再依据大小来计算menu的位置就可以了。而获得button针对屏幕的全局坐标可以使用mapToGlobal()这个函数。 

 

       该函数在assistant上的解释为:

Translates the widget coordinate pos to global screen coordinates. For example, mapToGlobal(QPoint(0,0)) would give the global coordinates of the top-left pixel of the widget

 

       亦即:该函数负责获得一个widget针对屏幕坐标系的坐标。

 

(当然了,还可以用另外一种方法:首先把menu的屏幕全局位置用mapFromGlobal()转换成局部坐标,然后再来计算。)

 

 

 

    总结:

      全局和局部坐标系的转换函数mapToGlobal()mapFromGlobal()还是很有用的,尤其是在处理menu这种只有屏幕全局坐标的wiget时。

    牵扯到focus变换时,一定要注意。(在这一点上还遇到了一个问题,后边再写文章来说明这个问题。)

 

===============================================================================

    当然,有人会说你可以直接使用QPushButton::setMenu()来给button设置一个菜单。 

    这个方法其实也可以,但关键是你的设计适合不适合。我们project用到的button是有两个功能的:当符合某个条件时,click它用于处理某个事件。当不满足这个条件时:则用来显示menu。   那这种情况下则不适合用setMenu()这个函数了,因为一旦定义了这个函数:无论什么情况下:只要click该button,menu都会显示的,这不是我们需要的结果.

你可能感兴趣的:(qt,button,menu)