Qt - виджет верхнего уровня с прозрачностью событий клавиатуры и мыши?

Я хочу, чтобы главное окно приложения игнорировало события мыши и клавиатуры, передавая их приложениям под ним в Z-порядке оконного менеджера.

Я вижу, как заставить дочерние виджеты игнорировать события клавиатуры или мыши, но как насчет главного окна?

Я пытаюсь создать виджет рабочего стола, который всегда находится прямо над фоном и полностью невидим для событий клавиатуры и мыши. (Пройти через)

Qt::X11BypassWindowManagerHint позволяет мне проходить через клавиатуру (хотя, к сожалению, специфично для X11, но пока нормально), так как насчет событий мыши?

Есть ли независимый от ОС способ быть прозрачным для событий клавиатуры?

ИЗМЕНИТЬ:

Ключевое слово здесь — прозрачность.

Я не хочу съедать события мыши и клавиатуры, я хочу, чтобы оконный менеджер знал, что они мне вообще не нужны. Эти события должны быть направлены на любое приложение, находящееся под моим контролем в zorder.

Например, я хочу иметь возможность щелкать значки на рабочем столе, закрытые моим виджетом, и взаимодействовать с ними так, как если бы виджета там не было.


person darron    schedule 12.06.2009    source источник
comment
понятия не имею, почему кто-то проголосовал за этот ... совершенно законный вопрос. к сожалению, у меня нет ответа, но я почти уверен, что он есть, потому что, если я правильно помню, в KDE есть такие виджеты на рабочем столе, и он основан на Qt.   -  person Idan K    schedule 16.06.2009
comment
Вы когда-нибудь находили решение для Linux?   -  person nilshi    schedule 08.04.2014


Ответы (6)


В Windows вы можете установить WS_EX_TRANSPARENT

Для этого в Qt используйте следующий код:

Включите заголовок,

#if _WIN32
    #include <windows.h>
#endif

и поместите следующий код в конструктор.

#if _WIN32
    HWND hwnd = (HWND) winId();
    LONG styles = GetWindowLong(hwnd, GWL_EXSTYLE);
    SetWindowLong(hwnd, GWL_EXSTYLE, styles | WS_EX_TRANSPARENT);
#endif
person JProgrammer    schedule 08.02.2011

Я нашел следующее решение (проверено на Linux, также работает на Windows согласно @TheSHEEEP):

setWindowFlags(windowFlags() | Qt::WindowTransparentForInput);

Он был добавлен в более позднем выпуске qt (я не нашел, когда) см. http://doc.qt.io/qt-5/qt.html

person mx1up    schedule 03.08.2016
comment
Я только что столкнулся с неясным побочным эффектом WindowTransparentForInput: если вы также пытаетесь установить флаг WA_TranslucentBackground для окна, оно перестает работать, и вместо этого цвет фона окна становится сплошным. Получается, что в Qt прозрачность для пользовательского ввода нарушает визуальную прозрачность. Никто бы никогда не столкнулся с этим, если бы они не пытались реализовать непрямоугольное окно. - person MusiGenesis; 20.08.2018

Может быть, то, что вы хотите, это

widget->setAttribute(Qt::WA_TransparentForMouseEvents)

? Это то, что использует QRubberBand, чтобы родительский элемент мог обрабатывать события мыши. Что касается событий клавиатуры, QWidget не получает никаких событий клавиатуры, если только он не установил для себя focusPolicy().

setFocusPolicy( Qt::NoFocus );

поэтому следует позаботиться о событиях клавиатуры.

person Marc Mutz - mmutz    schedule 10.07.2009
comment
Хорошо, это делает именно то, что я сказал, я уже знаю, как это сделать. Мне не нужен виджет, который позволяет своему родителю обрабатывать события мыши... Я хочу, чтобы все ПРИЛОЖЕНИЕ игнорировало их. Я хочу, чтобы что-то сообщало оконной среде (X, WinXP и т. д.), что щелчок по моему приложению должен просто перейти к другому приложению, находящемуся под ним в Z-порядке. Тот набор текста на клавиатуре должен делать то же самое. Эти решения просто передают события от дочерних виджетов к родительскому. Я хочу, чтобы события отправлялись из родительского виджета обратно в оконный менеджер или, скорее всего, вообще никогда не отправлялись в приложение. - person darron; 10.07.2009
comment
однако этот ответ полезен для тех, кто действительно хочет сделать то, о чем вы говорите. (передать вещи клиенту). Я попробовал это на случай, если инфраструктура Qt действительно распознает, что вы пытаетесь игнорировать события на родительском уровне, и попытается отправить их обратно в оконный менеджер (или установить какой-то флаг в оконном менеджере, чтобы обойти )... но, как и ожидалось, это не сработало. Мое приложение съело события. - person darron; 10.07.2009
comment
Верно, извини. С тех пор я также пробовал setMask(), который делает то, что вы хотите, но также обрезает видимость. Я почти уверен, что нет способа сделать то, что вы хотите, не прибегая к хакам, специфичным для ОС. Нашли ли вы искомую функциональность в любом другом приложении? - person Marc Mutz - mmutz; 13.07.2009

Возможно, я что-то упустил, но пробовали ли вы создать подкласс класса QMainWindow и переопределить QWidget Метод ::event() всегда возвращает false? Если вам нужно обрабатывать какие-то события, вы также можете добавить эту информацию сюда.

Этот метод должен позволить вам проверять события, поступающие в приложение, и игнорировать их, если это необходимо, без необходимости их использования с помощью фильтра событий.

Если это не сработает, вы можете попытаться перенаправить события на рабочий стол, вызвав QCoreApplication: :notify() и передать событие виджету рабочего стола, полученному путем вызова QApplication ::рабочий стол(). Я понятия не имею, сработает ли это, но мне показалось, что стоит попробовать.

person Joe Corkery    schedule 19.06.2009

Я думаю, что переопределение должно работать:

bool YourMainWindow::event( QEvent *event )
{
   event ->accept();
   return true;
}

это часть того, что документация класса QWidget говорит о функции-члене event():

Эта функция возвращает значение true, если событие было распознано, иначе — значение false. Если распознанное событие было принято (см. QEvent::accepted), любая дальнейшая обработка, например передача события родительскому виджету, прекращается.

person Maleev    schedule 16.06.2009

Используйте фильтры событий Qt: они позволят вашему приложению использовать любые указанные вами события (т.е. события клавиатуры и мыши), но по-прежнему обрабатывают другие события, такие как события рисования.

bool FilterObject::eventFilter(QObject* object, QEvent* event)
{
    QKeyEvent* pKeyEvent = qobject_cast<QKeyEvent*>(event);
    QMouseEvent* pMouseEvent = qobject_cast<QMouseEvent*>(event);

    if (pKeyEvent || pMouseEvent)
    {
        // eat all keyboard and mouse events
        return true;
    }

    return FilterObjectParent::eventFilter(object, event);
}
person Krsna    schedule 18.06.2009