• 10346阅读
  • 3回复

enterEvent 在无边框窗口中无反应[已确定为Qt BUG] [复制链接]

上一主题 下一主题
离线napier
 

只看楼主 倒序阅读 楼主  发表于: 2009-09-25
以前提过类似的问题,但未解决,现在详细描述一下。

首先这是一个漂浮在桌面下边缘附近、可以拖动的无边框窗口,显示的是一个“LOOK”的卡通形象。LOOK 的眼睛平时是半闭的,隔一段时间会眨眼。当鼠标移动到窗口上时,LOOK 半闭的眼睛会睁大。

这个功能是用 enterEvent 实现的。
  1. void Look::enterEvent(QEvent*e)
  2. {
  3.     //
  4.     qDebug() << "enterEvent";
  5.     if (lblSquint->isVisible())    // eyelids visible
  6.         attention();               // open eyes
  7.     //QWidget::enterEvent(e);
  8. }


一般情况下这个功能正常运行,但是有时 enterEvent 会失效,例如:
右键单击,出现 context menu

不点击退出,而是把鼠标移动到另一个位置,左键单击,把菜单 cancel 掉

  

之后,enterEvent 就没有反应了,无论怎么移动鼠标,也不会发生 enterEvent。


如果去掉代码里面的 Qt::FramelessWindowHint 就不会发生这个问题,但是卡通形象的效果就没有了。


下面是部分源代码,全部的源文件在压缩包里面。
  1. #include "look.h"
  2. #include <QtGui/QAction>
  3. #include <QtGui/QApplication>
  4. #include <QtGui/QPixmap>
  5. #include <QtGui/QLabel>
  6. #include <QtGui/QMouseEvent>
  7. #include <QtGui/QDesktopWidget>
  8. #include <QtCore/QTimer>
  9. #include <QDebug>
  10. //Look::Look(QWidget *parent)
  11.     //: QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint)
  12. Look::Look()
  13. {
  14.     setWindowFlags(
  15.             Qt::WindowSystemMenuHint
  16.           | Qt::FramelessWindowHint
  17.           | Qt::WindowStaysOnTopHint
  18.           );
  19.     setAttribute(Qt::WA_TranslucentBackground);
  20.     // load character pic
  21.     imgLook.load(":/image/look.png");
  22.     imgSquint.load(":/image/half.png");
  23.     imgClose.load(":/image/close.png");
  24.     lblLook = new QLabel(this);
  25.     lblLook->setGeometry(imgLook.rect());
  26.     lblLook->setPixmap(imgLook);
  27.     // dock: bottom of availableGeometry (work area?)
  28.     pos_y = QApplication::desktop()->availableGeometry().bottom() - imgLook.height();
  29.     setGeometry(0, pos_y, imgLook.width(), imgLook.height());
  30.     lblClose = new QLabel(this);
  31.     lblClose->setGeometry(62, 38, 69, 56);
  32.     lblClose->setPixmap(imgClose);
  33.     lblClose->hide();
  34.     lblSquint = new QLabel(this);
  35.     lblSquint->setGeometry(62, 38, 69, 30);
  36.     lblSquint->setPixmap(imgSquint);
  37.     lblSquint->show();
  38.     // Wink
  39.     timerWink = new QTimer(this);
  40.     connect(timerWink, SIGNAL(timeout()), this, SLOT(wink()));
  41.     timerWink->start(10000);
  42.     // context Menu
  43.     QAction *quitAction = new QAction(tr("E&xit"), this);
  44.     quitAction->setShortcut(tr("Ctrl+Q"));
  45.     connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
  46.     addAction(quitAction);
  47.     setContextMenuPolicy(Qt::ActionsContextMenu);
  48.     // When screen resolution change
  49.     connect(QApplication::desktop(), SIGNAL(resized(int)),
  50.             this, SLOT(screenResize(int)));
  51.     connect(QApplication::desktop(), SIGNAL(workAreaResized(int)),
  52.             this, SLOT(screenResize(int)));
  53. }
  54. void Look::enterEvent(QEvent*e)
  55. {
  56.     //
  57.     qDebug() << "enterEvent";
  58.     if (lblSquint->isVisible())
  59.         attention();
  60.     //QWidget::enterEvent(e);
  61. }
  62. void Look::wink()
  63. {
  64.     //
  65.     if (lblClose->isHidden())
  66.         lblClose->show();
  67.     QTimer::singleShot(80, this, SLOT(openeyes()));
  68. }
  69. void Look::openeyes()
  70. {
  71.     if (lblClose->isVisible())
  72.         lblClose->hide();
  73. }
  74. void Look::screenResize(int screen)
  75. {
  76.     int temp = QApplication::desktop()->availableGeometry().bottom()
  77.                - imgLook.height();
  78.     // if y is not appropriate
  79.     if (y() != temp) {
  80.         pos_y = temp;
  81.         move(x(), pos_y);
  82.     }
  83. }
  84. void Look::mousePressEvent(QMouseEvent*event)
  85. {
  86.     if (event->button() == Qt::LeftButton) {
  87.         pos_x = event->globalX() - x();
  88.         event->accept();
  89.     }
  90.     else
  91.         event->ignore();
  92. }
  93. void Look::mouseMoveEvent(QMouseEvent*event)
  94. {
  95.     if (event->buttons() & Qt::LeftButton) {
  96.         move(event->globalX() - pos_x, pos_y);
  97.         event->accept();
  98.     }
  99. }
  100. void Look::attention()
  101. {
  102.     lblSquint->hide();
  103.     QTimer::singleShot(6000, this, SLOT(standby()));
  104. }
  105. void Look::standby()
  106. {
  107.     lblSquint->show();
  108. }
[ 此帖被napier在2009-10-12 11:28重新编辑 ]
附件: LOOK.zip (17 K) 下载次数:49
离线napier

只看该作者 1楼 发表于: 2009-10-11
本来已经分析到消息队列了,却发现这是一个官方还未解决的 BUG...
http://qt.nokia.com/developer/task-tracker/index_html?method=entry&id=210564
时间居然一推再推... ft
离线thomas8852
只看该作者 2楼 发表于: 2011-03-03
非常 感谢, 找了很久 类似的 效果的例子 , 学习学习。
离线alexltr

只看该作者 3楼 发表于: 2011-03-03
it's a good example for me. thanks.
我不从事IT,只是喜欢Qt。
我不是程序员,只是与程序有缘。
我写程序,只是为了让工作变得简单有序!

                      ----  一个一直在入门的编程学习者
快速回复
限100 字节
 
上一个 下一个