Это можно сделать, установив фильтр событий в родительском окне внутри дочернего окна.
Вот пример проект, который я сделал, чтобы продемонстрировать это:
untitled3.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = untitled3
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp \
form.cpp
HEADERS += mainwindow.h \
form.h
FORMS += mainwindow.ui \
form.ui
form.h:
#ifndef FORM_H
#define FORM_H
#include <QDialog>
namespace Ui {
class Form;
}
class Form : public QDialog
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
Ui::Form *ui;
};
#endif // FORM_H
form.cpp:
#include "form.h"
#include "ui_form.h"
Form::Form(QWidget *parent) :
QDialog(parent),
ui(new Ui::Form)
{
ui->setupUi(this);
parentWidget()->installEventFilter(this);
}
Form::~Form()
{
delete ui;
}
bool Form::eventFilter(QObject *obj, QEvent *event)
{
return QObject::eventFilter(obj, event);
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class Form;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
Form *f;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "form.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
f = new Form(this);
connect(ui->pushButton, SIGNAL(clicked()), f, SLOT(show()));
}
MainWindow::~MainWindow()
{
delete ui;
}
form.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QDialog" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>190</x>
<y>40</y>
<width>46</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>zz</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Form</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Form</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>200</x>
<y>40</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Push</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
В результате дочерний виджет теряет фокус, но всегда остается на верхней части родительского виджета.Дайте мне знать, если это то, что вы ищете.
AFAIK это не реально, если окно модально, поскольку это обрабатывается диспетчером OS-window, а не QT. Если дочернее окно является модальным, все события направляются к нему из ОС. Вероятно, вы могли поймать все события в дочернем элементе, проверить координаты мыши и затем перенаправить на родителя, но я не уверен, может ли главное окно обрабатывать любые слоты в таком состоянии. – Bowdzone
Я считаю, что вы должны использовать 'winEventFilter' (' nativeEventFilter' в 'Qt5'), чтобы поймать все события приложения. – Ezee
@Bowdzone, спасибо вам за хорошую идею! Я попытаюсь проверить, получает ли модальное окно какие-либо сообщения после щелчка мышью по родительскому окну. – Ilya