Russian Qt Forum
Апрель 24, 2024, 19:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Popup window and button  (Прочитано 8551 раз)
Azazello
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« : Октябрь 27, 2018, 12:01 »

Есть всплывающее окно  - setWindowFlags(Qt::Popup) (окно скрывается, когда теряет фокус  - другими словами кляцнули на другом месте, оно скрылось).
Есть кнопочка, которая вызывает это окно. При активном окне кнопочка утоплена. Окно закрылось, кнопочка обратно выпрямилась.

Понятно, что пользователь захочет нажать на эту кнопочку (ожидаемое поведение) чтобы скрыть это окно. НО!, как только он захочет её нажать, окно потеряет фокус и само скроется ( и окно переведет кнопочку в состояние выкл.). И произойдет опять вызов окна (т.к. кнопка уже выпрямилась).

Решено так:
Код:
 void ChoiceWidget::hideEvent(QHideEvent *event)
{
    QWidget::hideEvent(event);
   //disable recurse unset button
    if (mAction != nullptr) {
        QAction *action = mAction; //for capture lambda
        action->blockSignals(true);
        QTimer::singleShot(200,[action]() {
            action->setChecked(false);
            action->blockSignals(false);
        });
    }
}

Т.е. блокируем кнопку на пару милисекунд.
Может есть более нормальное решение?
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Октябрь 29, 2018, 07:25 »

А если так:
Код
C++ (Qt)
void ChoiceWidget::buttonClick(bool state)
{
 if (state){
   // показываем всплывашку
 }
}
 
// соединять соответственно так:
connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClick(bool)));
Записан

Юра.
Azazello
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #2 : Октябрь 29, 2018, 10:21 »

А если так:
Код
C++ (Qt)
void ChoiceWidget::buttonClick(bool state)
{
 if (state){
   // показываем всплывашку
 }
}
 
// соединять соответственно так:
connect(button, SIGNAL(clicked(bool)), this, SLOT(buttonClick(bool)));

Так и сделано. Но дело в том, что state изменит окно, когда закроется и кнопочка выпрямится. Т.е. событие закрытия окна (которое изменяет состояние кнопки) происходит раньше, чем клик на кнопку. Таким образом мы опять вызовем окно.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #3 : Октябрь 29, 2018, 11:14 »

Судя по описанию задачи получается, что окно должно скрываться при потери фокуса, но не должно скрываться при переходе/нажатии на кнопку(она сама закроет окно). Может в эту сторону и нужно копать. Т.е. не закрывать окно безусловно при потери фокуса, а проверять куда/при каких обстоятельствах он изменяется.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Октябрь 29, 2018, 11:28 »

Так и сделано. Но дело в том, что state изменит окно, когда закроется и кнопочка выпрямится. Т.е. событие закрытия окна (которое изменяет состояние кнопки) происходит раньше, чем клик на кнопку. Таким образом мы опять вызовем окно.
Если окно скрывается как угодно (как и положено для popup) - то зачем делать это еще действием? Пусть кнопка только открывает и становится disabled. А окно закрылось - опять enabled

Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #5 : Октябрь 29, 2018, 12:14 »

Ещё можно попробовать вызывать методы (hide, setChecked, и т.п.) не напрямую, а через QMetaObject::invokeMethod(..., Qt::QueuedConnection), чтобы они в конец очереди сообщений ставились.
Записан

Пока сам не сделаешь...
Azazello
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #6 : Октябрь 29, 2018, 13:57 »

Если окно скрывается как угодно (как и положено для popup) - то зачем делать это еще действием? Пусть кнопка только открывает и становится disabled. А окно закрылось - опять enabled


Да, цирк в том, что нажатие на кнопку реально не происходит, но пользователь то об этом не знает.

Ну действительно, пользователь, который будет работать с тулузой, со временем перестанет обращать внимание на кнопочки, т.к. будет знать, что окно пропадет само  и не стоит тратить на него энергию.
Но разницу между вашим вариантом и своим я не вижу. Если кнопка станет disable, то сделать его enable должно само окно и мы приходим к тому же самому.
Ну и конечно же, это введет в ступор пользователя - как закрыть окно? (на секунду конечно, он автоматом начнет на все поряд тыкать)

Ещё можно попробовать вызывать методы (hide, setChecked, и т.п.) не напрямую, а через QMetaObject::invokeMethod(..., Qt::QueuedConnection), чтобы они в конец очереди сообщений ставились.

Но это ничего не гарантирует

Судя по описанию задачи получается, что окно должно скрываться при потери фокуса, но не должно скрываться при переходе/нажатии на кнопку(она сама закроет окно). Может в эту сторону и нужно копать. Т.е. не закрывать окно безусловно при потери фокуса, а проверять куда/при каких обстоятельствах он изменяется.

Не совсем понял. Условно (считайте), что я пишу Qt Creator - это инструмент, у которого все под рукой, и который не должен отвлекать. Окна, которые закрываются при потере фокуса - самое то, чтобы не отвлекать. И да, хоть он вместо окон использует меню, смысл тот же самый. Да, можно было бы использовать только онКлик..... Но как то некрасиво для самого себя. Не видел я такого поведения. Тем более, можно ж умом тронуться для неокрепших пользователей. Он тыкает, чтобы закрыть, на кнопку, а окно пропадает и сразу появляется.
« Последнее редактирование: Октябрь 29, 2018, 14:21 от Azazello » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #7 : Октябрь 29, 2018, 14:19 »

А чем QToolButton не угодило с setPopupMode( QToolButton::MenuButtonPopup )? Вроде как, нужное поведение реализует.
Если не то, тогда можно внутри Qt посмотреть, как реализовано.
Записан
Azazello
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #8 : Октябрь 29, 2018, 14:27 »

А чем QToolButton не угодило с setPopupMode( QToolButton::MenuButtonPopup )? Вроде как, нужное поведение реализует.
Если не то, тогда можно внутри Qt посмотреть, как реализовано.

Это и есть QToolButton с фейковым (пустым) меню - для того, чтобы стрелочку рисовало на кнопочке - мол появится что-то.
И второе: в меню весь функционал который мне нужен не влезет.
Можно также сравнить с ComboBox. Но отличие этих всех контролов от того, что мне нужно - их меню или списки встроены в тип. QToolButton знает о меню. Моя же кнопочка ничего ни о ком не знает и знать НЕ СОБИРАЕТСЯ.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #9 : Октябрь 29, 2018, 14:56 »

Но это ничего не гарантирует

Моя же кнопочка ничего ни о ком не знает и знать НЕ СОБИРАЕТСЯ.

Тогда хорошо бы минимальный проект выкладывать, чтобы можно было посмотреть: кто о ком знает, как с кем соединяется и как сигналы проходят.

Можно попробовать перед action->setChecked(false) задействовать QAction::setData() с каким-нибудь флагом/состоянием/данными.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Октябрь 29, 2018, 15:16 »

Но разницу между вашим вариантом и своим я не вижу. Если кнопка станет disable, то сделать его enable должно само окно и мы приходим к тому же самому.
Последовательность событий: нажатие мыши -> закрытие popup окна -> нажатие кнопки. Если сигнал закрытия соединить с enabled кнопки (QueuedConnection), то на момент нажатия кнопка еще disabled и повторного открытия не произойдет. 

Ну и конечно же, это введет в ступор пользователя - как закрыть окно? (на секунду конечно, он автоматом начнет на все поряд тыкать)
Не стоит считать юзера таким уж тупым - с др менюшками и попапками он прекрасно разбирается без всяких доп указаний
Записан
Azazello
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #11 : Октябрь 29, 2018, 15:47 »

Последовательность событий: нажатие мыши -> закрытие popup окна -> нажатие кнопки. Если сигнал закрытия соединить с enabled кнопки (QueuedConnection), то на момент нажатия кнопка еще disabled и повторного открытия не произойдет. 

Попробую. Потом отпишусь

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

Он прекрасно разбирается, потому что все программы одинаково себя правильно ведут. Да понятное дело, что разберутся. Но это же разражает. Кому охота иметь программу, которая раздражает.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Октябрь 29, 2018, 15:55 »

Да понятное дело, что разберутся. Но это же разражает. Кому охота иметь программу, которая раздражает.
Кнопка типа "закрой роpup (идиот)" раздражает куда больше  Улыбающийся
Записан
Azazello
Самовар
**
Offline Offline

Сообщений: 103


Просмотр профиля
« Ответ #13 : Октябрь 29, 2018, 16:20 »

Да понятное дело, что разберутся. Но это же разражает. Кому охота иметь программу, которая раздражает.
Кнопка типа "закрой роpup (идиот)" раздражает куда больше  Улыбающийся

У вас есть хоть один пример, где этот функционал отсутствует?

Я же не добавляю новую кнопку, не махаю флагом перед пользователем, даже не спрашиваю пользователя, хочет ли он выйти из программы (просто из нее нельзя выйти:)). Наоборот, делаю интерфейс найболее ненавязчивый. Скажем так, если всплывает меню - уже все привыкли, что оно само пропадет. Если окно, то нет. Но для контекстного меню то и кнопка не нужна, поэтому проблема отсутствует. Но, даже если забить на юзабилити, все равно что то нужно делать с поведением. Кнопка есть и её не может не быть. Если не заморачиватся с интерфейсом, то конечно, проще сделать его модальным (окно) с кнопочкой закрытия. Но мы не ищем лёгких путей.......Пример программы The BAT. Пруд пруди почтовых клиентов, однако популярность бата, по моему мнению, обусловленно именно юзабилити. И функционал здесь нипричем

Последовательность событий: нажатие мыши -> закрытие popup окна -> нажатие кнопки. Если сигнал закрытия соединить с enabled кнопки (QueuedConnection), то на момент нажатия кнопка еще disabled и повторного открытия не произойдет.  

Итак, сделал вариант с disable + Qt::QueuedConnection.Работает. Скажем так, в принципе пойдёт. Не совсем так уж чтобы красиво. Ну представте, вы нажимаете меню File, вываливается само меню, а File стал заблокированым...... Спасибо (это не сарказм).

Хех. Не. Не работает. Подсознание не позволяло нажать на кнопочку disabled чтобы протестировать. Если я нажимаю на нее (disabled), окно пропадает, она становится enable и срабатывает событие, окно опять появляется
« Последнее редактирование: Октябрь 29, 2018, 17:20 от Azazello » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Октябрь 29, 2018, 17:29 »

У вас есть хоть один пример, где этот функционал отсутствует?
Так для юзверя ф-ционал тот же самый, пусть давит на бубочку, окно и закроется. Не нравится  что кнопка стала disabled? Этого можно и не показывать (переставить палитру). Ну или разориться на флажок
Код
C++ (Qt)
void MyButton::SlotPressed( void )
{
 if (!m_flagOpened) {
   ShowPopupWindow();
   m_flagOpened = true;
 }
}
Смысл в том что флажок сбрасывается через QueuedConnection, поэтому когда окно уже закрылось - он еще взведен до окончания текущего события
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.109 секунд. Запросов: 22.