Событие изменения размера пользователя Qt заканчивается (останавливается) - PullRequest
4 голосов
/ 13 октября 2011

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

Я просто пытался переопределить QMouseReleaseEvent, чтобы перехватить его, но он не работает, когда пользователь нажимает на границе виджета, чтобы изменить его размер.Это означает, что в нашей ситуации это не работает.

Затем я попытался создать свой собственный QSizeGrip и вставить его внизу моего виджета, но переопределенное событие QMouseReleaseEvent снова не сработало в нем.Событие не генерируется ни разу, когда пользователь отпустил мышь.Я не знаю почему.

Кто-нибудь может мне помочь с этой проблемой?

Заранее спасибо.

Ответы [ 5 ]

5 голосов
/ 23 августа 2017

Метод тайм-аута - неплохая идея, но если пользователь изменяет размеры, а затем делает паузу дольше, чем интервал таймера, вы в конечном итоге не получаете истинное событие «пользователь сделал изменение размера окна».Увеличение интервала делает эту ситуацию менее вероятной, но, делая это, вы получаете большую задержку между временем, когда пользователь завершил изменение размера, и временем, когда ваша функция вызывается.В своем поиске решения я обнаружил, что немало людей решают его с помощью метода таймера, так что, по-видимому, он достаточно надежен для некоторых случаев использования, но я думаю, что он немного хакерский.после его реализации я решил добавить сюда некоторый код, который может быть полезен кому-то, пытающемуся сделать что-то подобное.Вы можете легко адаптировать его, чтобы поймать событие «пользователь завершил перемещение окна», установив флаг m_bUserIsMoving и переопределив «void MainWindow :: moveEvent (QMoveEvent * pEvent)».Я использую его для сохранения файла конфигурации всякий раз, когда пользователь заканчивает изменение размера или перемещение окна, чтобы последняя позиция всегда сохранялась, даже если приложение было убрано нечистым образом.

// constructor
MainWindow::MainWindow(QWidget* pParent, Qt::WindowFlags flags) : QMainWindow(pParent, flags)
{
    m_bUserIsResizing = false;
    qApp->installEventFilter(this);
}

// this will be called when any event in the application occurs
bool MainWindow::eventFilter(QObject* pObj, QEvent* pEvent)
{
    // We need to check for both types of mouse release, because it can vary on which type happens when resizing.
    if ((pEvent->type() == QEvent::MouseButtonRelease) || (pEvent->type() == QEvent::NonClientAreaMouseButtonRelease)) {
        QMouseEvent* pMouseEvent = dynamic_cast<QMouseEvent*>(pEvent);
        if ((pMouseEvent->button() == Qt::MouseButton::LeftButton) && m_bUserIsResizing) {
            printf("Gotcha!\n");
            m_bUserIsResizing = false; // reset user resizing flag
        }
    }
    return QObject::eventFilter(pObj, pEvent); // pass it on without eating it
}

// override from QWidget that triggers whenever the user resizes the window
void MainWindow::resizeEvent(QResizeEvent* pEvent) { m_bUserIsResizing = true; }

Этонемного сложнее, чем таймер, но надежнее.

3 голосов
/ 25 октября 2013

Я сделал это следующим образом:

  1. унаследовал мой класс от QWidget
  2. определить приватную переменную int timerId = 0
  3. перегрузка QWidget :: resizeEvent и QObject :: timerEvent

void MapLoader::resizeEvent(QResizeEvent *){
    if (timerId){
        killTimer(timerId);
        timerId = 0;
    }
    timerId = startTimer(5000/*delay beetween ends of resize and your action*/);
}

void MapLoader::timerEvent(QTimerEvent *te){
    /*your actions here*/
    killTimer(te->timerId());
    timerId = 0;
}
1 голос
/ 14 сентября 2012

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

"Установка фильтра событийв QCoreApplication :: instance (). Такой фильтр событий способен обрабатывать все события для всех виджетов, поэтому он так же силен, как повторная реализация notify (), более того, возможно иметь более одного глобального фильтра событий приложения.фильтры даже видят события мыши для отключенных виджетов. Обратите внимание, что фильтры событий приложения вызываются только для объектов, которые находятся в главном потоке. "

1 голос
/ 14 октября 2011

События мыши при декорировании окон управляются базовой оконной системой, поэтому вы не можете поймать их так, как пытались.Однажды у меня была та же проблема, решение, которое я выбрал, состояло в том, чтобы (повторно) запускать одиночный QTimer при каждом событии изменения размера, и обрабатывать обновление только после истечения интервала таймера.Не очень сексуально, но я не нашел другого обходного пути ..

0 голосов
/ 15 мая 2018

Мое приложение Qt использует окна изображений и выполняет сложные многоуровневые перестройки, что может занять некоторое время даже на очень быстрой машине.Поэтому отсутствие перерисовки окна при каждом изменении размера оконной рамки было для меня важно, поэтому ответ на изменение размера оконной рамки не был бы медленным.

Поэтому я решил это следующим образом:

В моем окне изображения я включил отслеживание мыши:

setMouseTracking(true);

Затем в классе окна у меня есть логическое значение, puntme;устанавливается, когда перехватывается событие resize:

bool puntme;

Затем в событии mousemove:

void imgWindow :: mouseMoveEvent (QMouseEvent * event) {

if (puntme)
{
    puntme = false;
    needRebuild = true;
    update();
}

...

По сути, это происходит, как только пользователь наводит указатель мыши на окно - что вполне естественно для него, если он просто изменяет его размер, - тогда окно перерисовывается с новым размером.Это не происходит во время изменения размера, потому что Qt не пересылает ходы перемещения.

Вместо этого, во время изменения размера, я просто масштабирую уже существующее растровое изображение, которое дает грубоеаппроксимация изменения масштаба с необходимостью обработки фактического нового более или менее доступного разрешения.

В худшем случае пользователь изменяет размеры, удаляет от окна и оставляет грубо масштабированное растровое изображениена месте, пока не вернетесь к нему, и в этот момент он должным образом обновится до фактического нового отображаемого растрового изображения == условия масштаба / размера.

Не существует идеального пути - здесь действительно нужно предоставить Qt(пользователь прекратил изменение размера окна ", но вместо этого это работает хорошо для меня.

...