2014-11-07 2 views
2

В моем проекте Qt есть два окна: родительский и дочерний. Окно для детей является модальным, поэтому все клики по родительскому окну игнорируются системой. Мне нужно реагировать на щелчки мыши на внутренней части окна-родителя (я понимаю, что это странное требование, но я не могу убедить клиента не спрашивать его).Как поймать клики на заблокированном окне?

Итак, что у нас есть: родительское окно отключено (поскольку дочернее окно открыто и модально). И мне нужно щелкнуть мышью по этому заблокированному (отключенному) окну.

Я вижу два способа сделать это:

  1. Имитировать модальность дочернего окна. Это мое текущее временное решение: я прокомментировал строку setWindowModality(Qt::WindowModal); в коде дочернего окна (то есть дочернее окно теперь не модально), поэтому я могу поймать щелчки мыши в родительском окне. И я установил eventFilter() для родительского окна, чтобы игнорировать большинство действий. Это решение работает, но оно выглядит неправильно и грубо.

  2. Найти способ поймать события мыши в отключенном окне. К сожалению, я не могу его поймать eventFilter() (потому что вход родительского окна заблокирован). Вы видите другие подходы?

Или вы видите другие способы сделать это?

+1

AFAIK это не реально, если окно модально, поскольку это обрабатывается диспетчером OS-window, а не QT. Если дочернее окно является модальным, все события направляются к нему из ОС. Вероятно, вы могли поймать все события в дочернем элементе, проверить координаты мыши и затем перенаправить на родителя, но я не уверен, может ли главное окно обрабатывать любые слоты в таком состоянии. – Bowdzone

+0

Я считаю, что вы должны использовать 'winEventFilter' (' nativeEventFilter' в 'Qt5'), чтобы поймать все события приложения. – Ezee

+0

@Bowdzone, спасибо вам за хорошую идею! Я попытаюсь проверить, получает ли модальное окно какие-либо сообщения после щелчка мышью по родительскому окну. – Ilya

ответ

2

Это можно сделать, установив фильтр событий в родительском окне внутри дочернего окна.

Вот пример проект, который я сделал, чтобы продемонстрировать это:

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(); 
} 

В результате дочерний виджет теряет фокус, но всегда остается на верхней части родительского виджета.Дайте мне знать, если это то, что вы ищете.

+0

Спасибо за этот пример! Он работает на моей стороне. Но, как я понимаю, это мое текущее решение (т. Е. Я не устанавливаю флаг модальности в дочернем окне, поэтому я могу улавливать все события родителя, а также моделирую модальность, игнорируя большинство событий). Пожалуйста, поправьте меня, если я ошибаюсь! – Ilya

+0

@ Илья Я думал, что вы устанавливаете дочернее окно модальное и * после *, что вы пытались поймать события. Думаю, я пропустил эту часть. Но почему вы не можете использовать этот подход? – Iuliu

+0

@luliu, да, я бы предпочел установить дочернее окно модальным и после этого сможет поймать события мыши родителя. Теперь я имитирую модальность, чтобы сделать это. Я могу использовать этот подход, но он выглядит грязным. Поэтому я ищу правильное решение для этого случая. – Ilya

 Смежные вопросы

  • Нет связанных вопросов^_^