如何识别 child 小部件内的 QMouseEvent?
How to recognize QMouseEvent inside child widgets?
编辑和一些自我批评
我尝试了两种给定的解决方案,它们都解决了我的问题,因此我感谢你们!我将透明解决方案标记为已接受,因为我认为当我只有一个 child 小部件时这是最简单的实现,但我希望与其他初学者分享一些见解:
我首先使用了 QLabel
,它显然默认启用了 Qt::WA_TransparentForMouseEvents
,因此显然有效,但我也希望文本能够 select,使用 [=15] =] 代替。可笑的是,这是不可能的,因为如果您尝试 select 文本(通过单击),您将关闭 window!我最终保持了透明度,而忽略了 select-text-feature.
我猜我的以下问题以前曾在某个地方得到过回答,但经过一个小时的搜索后,我现在 post 我自己提出了这个问题。如果有人能指出一个已经回答的问题来解决我的问题,我将不胜感激。
无论如何,我正在使用 C++ 和 Qt 创建一个弹出窗口 window。我创建了以下 PopupDialog
class,它可以很好地满足所有用途。但是,我删除了它的框架(包括包含关闭按钮和 window 标题的栏)以使其看起来简约,现在我希望它在用户 presses/releases 鼠标按钮位于内部任何位置时关闭弹出窗口 window(对话框)。
下面的代码有效,但是我必须准确地在 QDialog-window 处单击并释放鼠标。如果鼠标悬停在 QDialog
内的 child 小部件上,则当我单击时它不会关闭,例如a QPlainTextEdit
,正在显示文本。
因此,我需要 QDialog
的解决方案来识别其 child 小部件 中的 QMouseEvents
。请不要犹豫,问是否有不清楚的地方。我没有包含我的 mainwindow.h/.cpp 文件或 popupdialog.ui
文件,因为我认为这里 post 有点太多了,但是 .ui
非常简单:只是 QDialog
window 持有一个 QBoxLayout
,包含一个小部件,一个 QPlainTextEdit
。如果有帮助,我可能会 post 根据要求提供这些内容。
// popupdialog.h
#ifndef POPUPDIALOG_H
#define POPUPDIALOG_H
#include <QDialog>
#include <QString>
namespace Ui {class PopupDialog;}
class PopupDialog : public QDialog
{
Q_OBJECT
public:
explicit PopupDialog(QWidget *parent = 0, QString msgTxt="");
~PopupDialog();
private:
Ui::PopupDialog *ui;
QString messageText;
void mouseReleaseEvent(QMouseEvent*);
};
#endif //POPUPDIALOG_H
...
// popupdialog.cpp
#include "popupdialog.h"
#include "ui_popupdialog.h"
PopupDialog::PopupDialog(QWidget *parent, QString msgTxt) :
QDialog(parent),
ui(new Ui::PopupDialog),
messageText(msgTxt)
{
ui->setupUi(this);
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setModal(true);
ui->message_text_display->setText(messageText);
// The message_text_display is an instance of the class,
// "PlainTextEdit". Using "QLabel" partly solves my
// problem, but does not allow text selection.
}
PopupDialog::~PopupDialog()
{
delete ui;
}
void PopupDialog::mouseReleaseEvent(QMouseEvent *e)
{
this->close();
}
在头文件中
class PopupDialog : public QDialog
{
Q_OBJECT
public:
explicit PopupDialog(QWidget *parent = 0, QString msgTxt="");
~PopupDialog();
//////////////////////////////////
protected:
bool eventFilter(QObject *obj, QEvent *event);
//////////////////////////////////////
private:
Ui::PopupDialog *ui;
QString messageText;
void mouseReleaseEvent(QMouseEvent*);
};
在 cpp 中
PopupDialog::PopupDialog(QWidget *parent, QString msgTxt) :
QDialog(parent),
ui(new Ui::PopupDialog),
messageText(msgTxt)
{
ui->setupUi(this);
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setModal(true);
ui->message_text_display->setText(messageText);
// The message_text_display is an instance of the class,
// "PlainTextEdit". Using "QLabel" partly solves my
// problem, but does not allow text selection.
///////////////////////////////////////
foreach (QObject *child, children())
{
child->installEventFilter(this);
}
///////////////////////////////////////
}
///////////////////////////////////////
bool PopupDialog::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonRelease)
{
this->close();
}
}
正如您已经注意到的,鼠标事件是从子窗口小部件处理的,如果不被接受,则会传播到父窗口。您可以阅读更多相关信息 here
要在子窗口小部件内完成点击后关闭弹出窗口 window,您可以做两件事。您可以尝试查看 installEventFilter 并在每个子部件上设置它以调用 close()
.
另一种选择要求您拥有一种 centralWidget(就像 MainWindow
通常拥有的那样)- 只是为了对所有子部件进行分组。这样您就可以调用 setAttribute() 来设置 Qt::WA_TransparentForMouseEvents
属性 以简单地跳过处理小部件及其所有子项上的鼠标事件。
groupWidget->setAttribute(Qt::WA_TransparentForMouseEvents);
根据 Qt
文档:
When enabled, this attribute disables the delivery of mouse events to
the widget and its children. Mouse events are delivered to other
widgets as if the widget and its children were not present in the
widget hierarchy; mouse clicks and other events effectively "pass
through" them. This attribute is disabled by default.
这基本上意味着事件将向上传递到链中可以处理事件的第一个小部件。在您的情况下,它将是 PopupDialog
和已经覆盖的 mouseReleaseEvent
插槽。
编辑和一些自我批评 我尝试了两种给定的解决方案,它们都解决了我的问题,因此我感谢你们!我将透明解决方案标记为已接受,因为我认为当我只有一个 child 小部件时这是最简单的实现,但我希望与其他初学者分享一些见解:
我首先使用了 QLabel
,它显然默认启用了 Qt::WA_TransparentForMouseEvents
,因此显然有效,但我也希望文本能够 select,使用 [=15] =] 代替。可笑的是,这是不可能的,因为如果您尝试 select 文本(通过单击),您将关闭 window!我最终保持了透明度,而忽略了 select-text-feature.
我猜我的以下问题以前曾在某个地方得到过回答,但经过一个小时的搜索后,我现在 post 我自己提出了这个问题。如果有人能指出一个已经回答的问题来解决我的问题,我将不胜感激。
无论如何,我正在使用 C++ 和 Qt 创建一个弹出窗口 window。我创建了以下 PopupDialog
class,它可以很好地满足所有用途。但是,我删除了它的框架(包括包含关闭按钮和 window 标题的栏)以使其看起来简约,现在我希望它在用户 presses/releases 鼠标按钮位于内部任何位置时关闭弹出窗口 window(对话框)。
下面的代码有效,但是我必须准确地在 QDialog-window 处单击并释放鼠标。如果鼠标悬停在 QDialog
内的 child 小部件上,则当我单击时它不会关闭,例如a QPlainTextEdit
,正在显示文本。
因此,我需要 QDialog
的解决方案来识别其 child 小部件 中的 QMouseEvents
。请不要犹豫,问是否有不清楚的地方。我没有包含我的 mainwindow.h/.cpp 文件或 popupdialog.ui
文件,因为我认为这里 post 有点太多了,但是 .ui
非常简单:只是 QDialog
window 持有一个 QBoxLayout
,包含一个小部件,一个 QPlainTextEdit
。如果有帮助,我可能会 post 根据要求提供这些内容。
// popupdialog.h
#ifndef POPUPDIALOG_H
#define POPUPDIALOG_H
#include <QDialog>
#include <QString>
namespace Ui {class PopupDialog;}
class PopupDialog : public QDialog
{
Q_OBJECT
public:
explicit PopupDialog(QWidget *parent = 0, QString msgTxt="");
~PopupDialog();
private:
Ui::PopupDialog *ui;
QString messageText;
void mouseReleaseEvent(QMouseEvent*);
};
#endif //POPUPDIALOG_H
...
// popupdialog.cpp
#include "popupdialog.h"
#include "ui_popupdialog.h"
PopupDialog::PopupDialog(QWidget *parent, QString msgTxt) :
QDialog(parent),
ui(new Ui::PopupDialog),
messageText(msgTxt)
{
ui->setupUi(this);
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setModal(true);
ui->message_text_display->setText(messageText);
// The message_text_display is an instance of the class,
// "PlainTextEdit". Using "QLabel" partly solves my
// problem, but does not allow text selection.
}
PopupDialog::~PopupDialog()
{
delete ui;
}
void PopupDialog::mouseReleaseEvent(QMouseEvent *e)
{
this->close();
}
在头文件中
class PopupDialog : public QDialog
{
Q_OBJECT
public:
explicit PopupDialog(QWidget *parent = 0, QString msgTxt="");
~PopupDialog();
//////////////////////////////////
protected:
bool eventFilter(QObject *obj, QEvent *event);
//////////////////////////////////////
private:
Ui::PopupDialog *ui;
QString messageText;
void mouseReleaseEvent(QMouseEvent*);
};
在 cpp 中
PopupDialog::PopupDialog(QWidget *parent, QString msgTxt) :
QDialog(parent),
ui(new Ui::PopupDialog),
messageText(msgTxt)
{
ui->setupUi(this);
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setModal(true);
ui->message_text_display->setText(messageText);
// The message_text_display is an instance of the class,
// "PlainTextEdit". Using "QLabel" partly solves my
// problem, but does not allow text selection.
///////////////////////////////////////
foreach (QObject *child, children())
{
child->installEventFilter(this);
}
///////////////////////////////////////
}
///////////////////////////////////////
bool PopupDialog::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonRelease)
{
this->close();
}
}
正如您已经注意到的,鼠标事件是从子窗口小部件处理的,如果不被接受,则会传播到父窗口。您可以阅读更多相关信息 here
要在子窗口小部件内完成点击后关闭弹出窗口 window,您可以做两件事。您可以尝试查看 installEventFilter 并在每个子部件上设置它以调用 close()
.
另一种选择要求您拥有一种 centralWidget(就像 MainWindow
通常拥有的那样)- 只是为了对所有子部件进行分组。这样您就可以调用 setAttribute() 来设置 Qt::WA_TransparentForMouseEvents
属性 以简单地跳过处理小部件及其所有子项上的鼠标事件。
groupWidget->setAttribute(Qt::WA_TransparentForMouseEvents);
根据 Qt
文档:
When enabled, this attribute disables the delivery of mouse events to the widget and its children. Mouse events are delivered to other widgets as if the widget and its children were not present in the widget hierarchy; mouse clicks and other events effectively "pass through" them. This attribute is disabled by default.
这基本上意味着事件将向上传递到链中可以处理事件的第一个小部件。在您的情况下,它将是 PopupDialog
和已经覆盖的 mouseReleaseEvent
插槽。