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

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

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Дырка QMessageBox  (Прочитано 19284 раз)
Bepec
Гость
« Ответ #15 : Ноябрь 27, 2015, 15:13 »

Покопаюсь чуток.
« Последнее редактирование: Ноябрь 27, 2015, 16:12 от Bepec » Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #16 : Ноябрь 27, 2015, 15:55 »

Покопаюсь чуток.

На всякий случай - если без box->setWindowModality( Qt::WindowModal ); то бокс появляется также посередине родительского окна, но блокируется весь интерфейс приложения. Собственно, это всё описано в документации.
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Ноябрь 27, 2015, 15:58 »

Если нужна блокировка окна (а не приложения), то проще так
Код
C++ (Qt)
QMessageBox box(parent);
...
box.open();
 
Записан
Bepec
Гость
« Ответ #18 : Ноябрь 27, 2015, 16:12 »

Покопался. Всё правильно работает и мой сумбур верен. Расписываю.

1) Модальность - свойство окна. Не виджета, а именно окна.  При установлении родителем окна, диалог считает себя и родителя одним окном, что вполне логично, окно одно.

2) Блокировка событий. Блокировка событий использует внутри QDialog processEvents с недокументированным флагом QEventLoop::DialogExec, что вызывает  свободный проход событий для ОКНА диалога. (напоминаю пункт 1 - окно то у нас одно)

3) насчёт пропадания диалога. Диалог отрисовывается на вашем окне, но изза ситуации что окно "не родное", а предка, там происходит наложение размеров рабочего стола (1920x1080) на положение окна (86*30) и размер окна (800*600), что в конечном итоге приводит в моём случае на перенос отрисовки по координатам окна с 0*0 на ~600*400. При передвижении окна чуть ближе к центру, отрисовка пропадает - уходит за границу видимой области.  

Так что вот утверждения.
 Окно диалога есть, модальность окна не сохраняется(т.к. окно родител), луп работает, но обеспечивает работоспособность окна диалога Улыбающийся


PS да, дополнительно проверил, qDebug() << window()->objectName(); в классе диалога выдаёт родителя при использовании setParent Улыбающийся
« Последнее редактирование: Ноябрь 27, 2015, 16:22 от Bepec » Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #19 : Ноябрь 27, 2015, 16:31 »

3) насчёт пропадания диалога. Диалог отрисовывается на вашем окне, но изза ситуации что окно "не родное", а предка, там происходит наложение размеров рабочего стола (1920x1080) на положение окна (86*30) и размер окна (800*600), что в конечном итоге приводит в моём случае на перенос отрисовки по координатам окна с 0*0 на ~600*400. При передвижении окна чуть ближе к центру, отрисовка пропадает - уходит за границу видимой области.  

Сие есть баг. После установки родителя, уже нельзя центрировать окно по размерам десктопа.

И баг проявляется при разной последовательности действий. Если родитель задается при вызове конструктора бокса - всё работает, как ожидается. И бокс посередине родителя, и родитель под ним блокируется.

То есть, при

Код:
QMessageBox box( (QWidget*) parent );

всё нормально. Но

Код:
QMessageBox box( (QWidget*) 0 );
box.setParent( parent );

уже другой результат. Хотя логически это одно и то же.

« Последнее редактирование: Ноябрь 27, 2015, 16:33 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Bepec
Гость
« Ответ #20 : Ноябрь 27, 2015, 16:35 »

Не досмотрел где там точно баг,  не за этим в исходники лазил. Улыбающийся
Но согласен, смещение координат бага бага.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #21 : Ноябрь 27, 2015, 16:41 »

Не досмотрел где там точно баг,  не за этим в исходники лазил. Улыбающийся
Но согласен, смещение координат бага бага.

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

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Ноябрь 27, 2015, 17:37 »

А как сделать наоборот - диалог блокирует все окна кроме заданного(ых)?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #23 : Ноябрь 27, 2015, 17:43 »

А как сделать наоборот - диалог блокирует все окна кроме заданного(ых)?

Цепочкой родительские отношения блокируемым окнам установить. А не блокируемое не включать в цепочку. Правда после закрытия диалога отношения надо убирать. Специальный класс "группа окон" придётся сделать.
Записан

2^7-1 == 127, задумайтесь...
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #24 : Ноябрь 27, 2015, 17:47 »

А как сделать наоборот - диалог блокирует все окна кроме заданного(ых)?
Код
C++ (Qt)
for( auto w : qApp->topLevelWindows() )
   if( !non_blocking_windows.contains( w ) )
       w->setModality( Qt::WindowModal );
 
Записан

Qt 5.11/4.8.7 (X11/Win)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #25 : Ноябрь 28, 2015, 07:31 »

Код
C++ (Qt)
for( auto w : qApp->topLevelWindows() )
   if( !non_blocking_windows.contains( w ) )
       w->setModality( Qt::WindowModal );
 
Вот сделал пример (Qt 5.4)
Код
C++ (Qt)
#include <QtWidgets>
 
QWidget * CreateWin( int index, bool modal )
{
QWidget * win = new QWidget;
win->setGeometry(index * 100, index * 100, 320, 240);
win->setWindowTitle("Win " + QString::number(index));
new QLineEdit("Text " + QString::number(index), win);
if (modal)
win->setWindowModality(Qt::WindowModal);
win->show();
return win;
}
 
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
 
QWidget * win4 = CreateWin(4, true);
QWidget * win3 = CreateWin(3, true);
QWidget * win2 = CreateWin(2, false);
QWidget * win1 = CreateWin(1, false);
 
// QMessageBox box;
// box.exec();
 
return app.exec();
}
 
Ожидается что 2 окна будут блокированы, а между 2-мя др можно переключаться. Но на Вындоуз вообще никакой модальности, а на OSX есть но для одного окна, т.е. никаких переключений. На обоих платформах QMessageBox блокирует всех  

ЧЯДНТ?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #26 : Ноябрь 28, 2015, 18:17 »

ЧЯДНТ?

Кто кого тут блокировать будет? У создаваемого QWidget * win = new QWidget; родителем является десктоп. А чтобы win->setWindowModality(Qt::WindowModal); работало, родителем у win должно быть другое окно. Тогда win будет его блокировать.
Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Ноябрь 29, 2015, 08:56 »

Кто кого тут блокировать будет? У создаваемого QWidget * win = new QWidget; родителем является десктоп. А чтобы win->setWindowModality(Qt::WindowModal); работало, родителем у win должно быть другое окно. Тогда win будет его блокировать.
Ну вот и показали бы кодом, а то словеса. Хорошо, делаю как я Вас понял
Код
C++ (Qt)
#include <QtWidgets>
 
QWidget * InitWin( QWidget * win, int index )
{
win->setGeometry(index * 100, index * 100, 320, 240);
win->setWindowTitle("Win " + QString::number(index));
new QLineEdit("Text " + QString::number(index), win);
return win;
}
 
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
 
QWidget * win1 = InitWin(new QWidget, 1);
QWidget * win2 = InitWin(new QWidget, 2);
QWidget * win3 = InitWin(new QWidget(win1, Qt::Window), 3);
QWidget * win4 = InitWin(new QWidget(win1, Qt::Window), 4);
 
win3->setWindowModality(Qt::WindowModal);
win4->setWindowModality(Qt::WindowModal);
 
win1->show();
win2->show();
win3->show();
win4->show();
 
// QMessageBox box;
// box.exec();
 
return app.exec();
}
 
На Вындоуз это работает "не вполне". Т.е. да, я могу переключаться между окнами 2 и 4. а окна 1 и 3 блокированы. Но вот почему активное окно 2 может быть свободно перекрыто неактивными - хз.

А на OSX нужный ф-ционал вообще не достигается - окна 3 и 4 "вставляются" в окно 1 (Sheet окна). См аттач
Видимо WindowModal здесь не решение
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


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

QWidget - это НЕ окно. Модальность работает для окон, а не для кувиджетов. RTFM, там это описано. Тролли несколько запутали тем, что модальность задаётся у кувиджетов, потому что класса QWindow отдельного нет.

Цитировать
почему активное окно 2 может быть свободно перекрыто неактивными

Что тут означает "свободно перекрыто"? у окна win2 нет потомков, оно само по себе, перекрыто оно может быть кем угодно, но при этом оно не блокировано

Вообще с parent/children есть запутанность. В последнем примере окну win1 придаются два потомка win3 и win4. В документации нет ни слова о том, что у окна могут быть несколько окон-потомков, на которые распространяется правило модальности. Вообще-то модальным в иерархии, может быть по определению только одно окно. Это его сущность. Поэтому попытка сделать два модальных окна для одного родителя не должна работать. Поэтому окно win3 блокируется, хотя вроде бы не должно, так как win4 не является его потомком. Насколько я понимаю, для реализации модальности используются механизмы host OS. Очевидно поэтому и в OSX работает по-другому, так как ОС не понимает чего от неё хотят. Можно сделать два модальных окна, но у каждого должен быть свой родитель.

У меня сейчас модальность идентично работает в Windows и KDE Kubuntu 14 в версиях 32 и 64 бита.

Цитировать
показали бы кодом, а то словеса
это не словеса, а описание бизнес-логики, оно первично, если оно правильно понято, то написать код - дело техники
« Последнее редактирование: Ноябрь 29, 2015, 22:53 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #29 : Ноябрь 30, 2015, 10:45 »

... потому что класса QWindow отдельного нет.
Давным-давно есть  Улыбающийся

Вот ситуевина. Есть плагины с UI в виде модальных окон с кнопками Ok, Cancel. Это в принципе устраивает, НО нужна возможность отрендерить preview не нажимая кнопку Ok, т.е. не выходя из UI плагтна. Ладно, добавляем горячую клавишу, по ней preview рендерится и показывается в новом окне (или в старом если preview уже вызывалось). Но это новое окно нельзя даже передвинуть - не дает окно модальное плагина

И что, рассказывать юзеру что он должен сто раз жать Ok и снова открывать плагин - потому что, дескать, вообще-то модальность... Так юзера это мало волнует, ему нужно удобство
Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


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