我的小部件窗口是主窗口上始终显示的小部件的子窗口,它是一个 "Qt::ToolTip",因此我认为可能会有一些问题。有什么方法可以解决这个问题吗?
我的目标是:我有一个自定义工具栏小部件,其中的按钮可能有“下拉”小部件。这些下拉小部件没有标准的窗口框架。我不想让它们“窃取”主窗口的标题焦点,并且希望它们在用户在屏幕区域之外的任何地方单击后立即消失。我在寻找一个不需要妥协 Qt 的策略来完成这个任务,但遇到了严重困难。
我有什么遗漏的吗?(我敢打赌我有)。
我使用了:
setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
这在OSX和Windows上似乎运行良好。 我的窗口正确显示,不会从我的主窗口标题中夺取焦点,并且在我单击其外部时正确调用焦点丢失事件。
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();
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等事件,您需要在它们上面安装eventFilter,或者在主控件中重新实现QWidget::event(QEvent * event)函数,并在那里查找这些事件。
eventFilter
示例将无限递归。 - Flintvoid 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();
}
对于 Qt 版本低于 4.8 的情况,OP 的回答非常好,但正如他们在回答中提到的那样,它不适用于高于该版本的版本。当鼠标在小部件外单击时,Qt::Popup 小部件不会消失,并且它将吞噬所有通常会关闭它的输入。
经过进一步调查,这只是非对话框小部件的问题。使用 Qt::Popup 的 QDialog 在用户单击其外部时将正确关闭,但任何其他 QWidget,例如 QFrame,都不会。因此,为了解决 Qt 4.8 中的这种行为变化,所需的全部就是将小部件包装在 QDialog 中。
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);
StrongFocus
策略的focusOutEvent
效果更好,后者会产生非常不一致的结果。 - Ad NQt::Popup
确实会窃取焦点。 - Tenders McChiken