如果鼠标在其外部单击,则关闭窗口小部件窗口

时间:2011-09-14 19:12:15

标签: qt

这是一种鸡和蛋的问题。当鼠标点击外面时,我想关闭我的小部件窗口。据我了解,我的小部件没有鼠标事件,因为在它之外发生了点击。有一个SetFocus插槽,但其对应或焦点丢失在哪里?我没有为我的班级调用“focusOutEvent”。

我的窗口小部件窗口是一个窗口小部件的子窗口,它总是显示在我的主窗口上,它是一个“Qt :: ToolTip”,因此我假设可能会出现一些问题。任何方式?

我的目标:我有一个自定义工具栏小部件,其上的按钮可能有“下拉”小部件。这些下拉小部件没有标准的窗口框架。我不希望他们从主窗口“窃取”字幕焦点,我希望他们一旦用户点击他们所在地区以外的屏幕上的ANYWHERE就会消失。我很难找到一个在Qt上没有妥协的策略来完成这项工作。

我错过了什么吗? (打赌我)。

5 个答案:

答案 0 :(得分:15)

我用过:

setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);

这似乎在OSX和Windows上运行良好。我的窗口显示正确,从主窗口的标题中窃取焦点,并且只要我点击它外面就会正确调用焦点丢失事件。

答案 1 :(得分:7)

如果您的小部件可能具有焦点,并且“窃取”某些其他小部件的标题焦点,那么它会更容易。这样的事情可以奏效:

class ToolBarWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ToolBarWidget(QWidget * parent = 0)
    {
        setFocusPolicy(Qt::ClickFocus);
    }

protected:
    void focusOutEvent(QFocusEvent * event)
    {
        close();
    }
}

当你创建任何小工具时,你会这样做:

ToolBarWidget * pWidget = new ToolBarWidget(this);
pWidget->show();
pWidget->setFocus();

完成!好吧,我想不安静。首先,您不希望ToolBarWidget首先获得任何焦点。其次,您希望用户能够在任何地方单击并隐藏ToolBarWidget。 因此,您可以跟踪您创建的每个ToolBarWidget。例如,在'QList ttWidgets'成员变量中。然后,每当你创建一个新的ToolBarWidget时,你都会这样做:

ToolBarWidget * pWidget = new ToolBarWidget(this);
pWidget->installEventFilter(this);
pWidget->show();

在主窗口小部件类中,实现eventFilter()函数。类似的东西:

bool MainWidget::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::FocusOut ||
        event->type() == QEvent::KeyPress ||
        event->type() == QEvent::MouseButtonPress)
    {
        while (!ttWidgets.isEmpty()) {
            ToolBarWidget * p = ttWidgets->takeFirst();
            p->close();
            p->deleteLater();
        }
    }
    return MainWidget::eventFilter(obj, event);
}

这将有效。因为这样,即使您的ToolTabWidgets没有获得焦点,主窗口小部件中的其他窗口小部件也会有焦点。一旦改变(无论用户是否从窗口中,或在其中的另一个控件上,或者在这种情况下,按下按键或鼠标按钮,控件将到达该eventFilter()函数并关闭所有选项卡小部件。

顺便说一下,为了从其他小部件中捕获MouseButtonPress,KeyPress等,你需要在它们上面安装EventEvent,或者只是在你的主小部件中重新实现QWidget :: event(QEvent * event)函数,在那里寻找那些活动。

答案 2 :(得分:1)

你可以像这样使用QDesktopWidget.h

来做到这一点
void MainWindow::on_actionAbout_triggered()
{
    AboutDialog aboutDialog;
    //Set location of player in center of display
    aboutDialog.move(QApplication::desktop()->screen()->rect().center() -aboutDialog.rect().center());
    // Adding popup flags so that dialog closes when it losses focus
    aboutDialog.setWindowFlags(Qt::Popup);
    //finally opening dialog
    aboutDialog.exec();

}

答案 3 :(得分:0)

这是我的工作,目的是不使主要应用程序失去重点:

.h

bool eventFilter(QObject *obj, QEvent *event) override;

.cpp

bool Notification::eventFilter(QObject *obj, QEvent *event)
{
    if(event->type() == QEvent::MouseButtonPress)
        deleteLater();

    return QObject::eventFilter(obj, event);
}
...
// somewhere else (i.e. constructor, main window,...)
qApp->installEventFilter(this);

答案 4 :(得分:0)

OP 自己的答案对于 4.8 以下的 Qt 版本非常有用,但正如他们在答案中提到的那样,它不适用于高于 4.8 的版本。 Qt::Popup 小部件在小部件外部点击鼠标时不会消失,它会接收所有通常会关闭它的输入。

经过进一步调查,这只是非对话框小部件的问题。当用户在其外部单击时,使用 Qt::Popup 的 QDialog 将正确关闭,但任何其他 QWidget,如 QFrame,则不会。因此,为了解决 Qt 4.8 中的这种行为变化,所需要做的就是将小部件包装在 QDialog 中。