QT Перерисовать/перерисовать/обновить/сделать что-то

Я новичок в QT. Я понимаю, что вы можете заставить обновить дисплей, но я вытащил все мои волосы, пытаясь понять, как это сделать. Вот что я конкретно пытаюсь сделать.

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

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

Как я могу принудительно обновить pixmap QLabel. Я все пробовал. Ниже приведен код, который я пробовал в моем обработчике событий onClick. (upButton - это имя QLabel, которое является pixmap)

update();
repaint();
ui->upButton->setUpdatesEnabled(TRUE);
update();
repaint();
QPaintEvent paintevent(ui->upButton->childrenRegion());
QPaintEvent * test = &paintevent;
paintEvent(test);
this->changeEvent(test);
ui->upButton->update();
ui->upButton->repaint();
ui->upButton->repaint(ui->upButton->childrenRegion());
repaint();
QApplication::sendPostedEvents();
this->parentWidget()->update();
usleep(100000);

Как вы можете видеть, я просто снимаю в темноте в этот момент. Я попытался посмотреть пример кода и сделать все домашнее задание, но я потерян. Оцените любую помощь, совет и/или образец кода.

Ответ 1

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

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

Кроме того, "событие", которое должно выполняться для продолжения программы, является событием USB. Поскольку я использую устройство класса HID, невозможно установить событие без цикла ожидания. Классы USB HID не позволяют устанавливать прерывания, заявляет ОС устройство.

Мне удалось заставить это работать. Я прошел через отладчик и заметил, что дисплей будет обновляться до функции сна. Выполняя программу самостоятельно, я получал случайные результаты, когда дисплей обновлялся в 1% случаев. Я избавился от функции сна и добавил в него другой код, чтобы подражать задержке, и все было в порядке.

Просто для всех знаний это возможно, это не запрещено, и это легко сделать со следующим:

qApp->processEvents();

qApp - глобальная внешняя переменная в заголовке QApplication.

Поскольку это событие USB делает мой поток сложным, я наткнулся на класс QWaitCondition. Я собирался начать процесс, ожидающий события USB. Я бы подождал, пока процесс освободит условие ожидания для моей подпрограммы.

Но если кто-то думает, что это плохая идея, пожалуйста, выскажитесь. Я действительно ценю ваши отзывы PiedPiper и Hostile Fork.

Спасибо.

Ответ 2

Вы не должны ждать ввода в обработчике событий. Вам нужно переосмыслить логику вашей программы, чтобы использовать события так, как они были предназначены. Все вызовы update() и repaint() в вашем коде не нужны, если вы возвращаетесь к циклу событий.

Ответ 3

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

Если это так, выполните событие update() и вызовите qApp- > processEvents(). Этот метод обрабатывает события, которые ждут в очереди событий, а затем возвращается, поэтому это может быть то, что вы после.

PS: update() может вообще не понадобиться, я не уверен.

Ответ 4

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

Например

this->repaint();
this->parentWidget()->repaint();
this->parentWidget()->parentWidget()->repaint();

Это намного проще, чем выталкивать любую обработку в другой поток или создавать дополнительные обработчики событий.