Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Sasha от Декабрь 03, 2013, 17:00



Название: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: Sasha от Декабрь 03, 2013, 17:00
Здравствуйте,

1) Создаю в дизайнере главное окно
2) Кладу в него QStackedWidget
3) Кладу в первую вкладку QStackedWidget-а LineEdit
4) Запускаю "предварительный просмотр" (Ctrl+R)

И фокуса в LineEdit-е НЕТ. Почему? И как заставить его появлятся при запуске?
Если нажать пару раз "tab" или кликнуть по LineEdit-у мышкой, то фокус появляется в нём, и после этого корректно восстанавливается в нём же, если переключиться на другую вкладку (при её наличии) и обратно.

И ещё я не могу понять как работает setFocus для виджета у которого есть дочерние виджеты. Производится ли попытка установить фокус в одном из них? Если нет, то как, имея указатель на родительский виджет, установить фокус в том дочернем виджете, который имел этот фокус последним?


Название: Re: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: ammaximus от Декабрь 03, 2013, 20:09
Если ты делаешь предпросмотр формы (Alt+Shift+R), то фокус будет появляться не сразу, т.к. там не реализуется полная логика, оно и не нужно. Если ты запустишь приложение, в котором эта форма, то фокус обязательно установится на этот элемент (если он один или отмечен как первый).

При старте фокус устанавливается на элемент виджета 1 (порядок можно поменять в дизайнере нажав F4). Если за время работы фокус поменялся на элемент Х, то этот элемент запоминается, при возвращении фокуса родителя на него и устанавливается.

Попробуй создай форму, в ней несколько лайнэдитов, щелкай за пределы приложения, а потом обратно. setFocus - работает также.

Короче, то что ты хочешь работает из коробки.


Название: Re: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: Sasha от Декабрь 03, 2013, 21:42
Да, действительно, скомпилировал, запустил и фокус появился в LineEdit-е, просто у меня проблемма с этим фокусом в большом проекте и я решил сделать тест и первое, где проявилась потеря фокуса - это прям в дизайнере, о чём и написал, а создавать проект не стал.

НО!!!
Я всё-равно добился пропадания фокуса при старте программы, правда немного с другим интерфейсом:
1) Создаю в дизайнере главное окно
2) Кладу в него QTabWidget
3) первую вкладку оставляю пустой
4) Кладу во вторую вкладку LineEdit
5) Делаю активной 1-ю вкладку
6) Устанавливаю для QTabWidget политику фокуса в NoFocus (иначе LineEdit не получает фокус при старте даже располагаясь на 1-ой вкладке, что, кстати, тоже, по-моему, не верно тем более, что кнопка вкладки не подсвечивается пунктиром, хотя именно на ней фокус)
7) Запускаю (вижу первую пустую вкладку)
8) Кликаю мышкой по второй вкладке
9) Появляется LineEdit, НО без фокуса.

Что здесь не так?


Название: Re: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: Bepec от Декабрь 03, 2013, 23:09
Это называется горе от ума :)

Совершенно корректное и нормальное поведение виджетов. Активным является центральный виджет вкладки. И, как ни странно, это логично :)


Название: Re: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: gil9red от Декабрь 04, 2013, 00:11
Если так хочется, указываете программно какому виджету нужно иметь фокус и все :)


Название: Re: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: Sasha от Декабрь 04, 2013, 15:02
Это называется горе от ума :)

Совершенно корректное и нормальное поведение виджетов. Активным является центральный виджет вкладки. И, как ни странно, это логично :)
Может быть...
Даже не знаю как вопросы задать, будет слишком длинно. Если кратко, то попробуйте сами сделать как я написал выше и поиграйтесь с фокусом. Всё ли Вас будет устраивать. Я исхожу из того, что, перемещаясь по вкладкам, пользователь хочет видеть фокус в каком либо виджете ВНУТРИ вкладки.

Мне кажутся не логичными следующие вещи:
ситуация1:
У TabWidget-а политика фокуса - NoFocus
В этом случае, если при старте активна вкладка на которой НИЧЕГО НЕТ, то:
1) Никакими клавиатурными комбинациями (Ctrl+Tab, Tab, стрелки) невозможно переключить вкладку, только мышью
2) После переключения мышью на вкладку с edit-ом, фокус всёравно неизвестно где. Ни в edit-е, ни на закладках, т.к. курсор не мигает и Ctrl+Tab по-прежнему не работает и стрелочки тоже, однако Tab уже срабатывает и переключает фокус в edit, после чего начинает работать и Ctrl+Tab
Т.е. вывод один - нельзя чтобы ПРИ СТАРТЕ была открыта ПУСТАЯ вкладка.
ситуация2:
У TabWidget-а политика фокуса по умолчанию - TabFocus
В этом случае, на мой взгляд вообще всё плохо:
1) Если при старте активна ПУСТАЯ вкладка, то Tab, Ctrl+Tab и даже стрелочки работают, но
1.1) почему если стрелочки переключают вкладки, то на самих кнопках-вкладках НЕ ОТОБРАЖАЕТСЯ ПУНКТИР, говорящий о фокусе? Допустим, потому, что фокус всё-же на центральном (пустом) виджете (кстати, то, что после нажатия клавиши "Tab" пунктир появляется, косвенно подтверждает это). Но почему тогда:
2) Если при старте активна НЕ пустая вкладка, например с edit-ом, то фокуса нет на edit-е, а Ctrl+Tab и стрелочки переключают вкладки и опять же БЕЗ ПОДСВЕТКИ пунктиром. Стоит нажать Tab и edit получает фокус, что теперь косвенно говорит о том, что фокус всё-же был именно на кнопках-вкладках.
И как вообще в ситуации2 действовать при старте ДАЖЕ при НЕ ПУСТОЙ вкладки, ведь по-моему логично, чтобы фокус при старте был сразу на первом редактируемом поле вкладки. Я вижу следующие выходы:
1) Делать NoFocus для TabWidget-а и иметь проблемму1 и, кроме того, не иметь возможности перейти Tab-ом на кнопки-закладок
2) Вручную перемещать фокус, но для этого нужно знать или как-то искать первый виджет, могущий получать фокус для каждой вкладки.
3) В дизайнере установить позицию табуляции TabWidget-а после всех первых элементов всех закладок, но это если и TabWidget и закладки рисуются в дизайнере одним объектом, а если каждая вкладка рисуется отдельно (и оформлена отдельным классом) и потом они все объединяются програмно в TabWidget или StackedWidget. Это я к тому, что taborder по умолчанию выстанвляется не совсем логично (или я просто не знаю как это умолчание изменить, например каким-нибудь флажком) и чтоб выправить, в общем случае нужен не особенно очевидный код. Я вроде-бы его написал, но не факт что он полностью верен (прокси фокус я даже не пытался учитывать). К тому-же, даже, если всё в одном объекте и настроен taborder, то старт с пустой вкладкой возвращает к ситуации1.


Название: Re: Нет фокуса на элементе внутри QStackedWidget при запуске
Отправлено: Sasha от Декабрь 04, 2013, 15:26
Если так хочется, указываете программно какому виджету нужно иметь фокус и все :)
Это вроде-бы очевидно, но не всегда в сложных случаях просто делается. Нужно, либо для каждой вкладки отлавливать событие show и там устанавливать фокус на первый элемент (а если пользователь уже был на этой вкладке и сместил фокус на другой элемент, затем сменил вкладки и вернулся? значит ещё и запоминать фокусный элемент скажем по событию hide? и так для каждой вкладки?), либо писать код поиска фокусного элемента.
Кстати приведу такой код, может кому-то пригодится или кто-то его подправит:
Код
C++ (Qt)
void MainWindow::setFocusWidget( QWidget *pw_ )
{
   QWidget *pw = pw_;
   QWidget *pwf = QApplication::focusWidget();
   if( pw==pwf || pw->isAncestorOf( pwf ) )
       return;
 
   // считаем, что если политика фокуса не имеет типа Qt::TabFocus, то такой виджет не подходит
   while( pw!=NULL && (pw->focusPolicy() & Qt::TabFocus) != Qt::TabFocus )
       pw = pw->focusWidget();
 
   if( pw==NULL )
     {
       pw = pw_;
       // считаем, что если политика фокуса не имеет типа Qt::TabFocus, то такой виджет не подходит
       while( pw->isVisible()==false || (pw->focusPolicy() & Qt::TabFocus) != Qt::TabFocus )
           pw = pw->nextInFocusChain();
     }
 
   // это нужно, если ф-я используется НЕ в момент получения события show, а как слот на сигнал currentChanged из StackedWidget-а
   QTimer::singleShot( 1, pw, SLOT(setFocus()) );
}
 
Этой ф-ии можно передать указатель на виджет, который сам не может иметь фокус, но имеет дочерние элементы, которые уже могут иметь фокус.
Сам я вначале стал использовать этот код, но потом:
1) отказался от пустой стартовой вкладки
2) сменил политику фокуса внутренних TabWidget-ов на NoFocus
3) сменил политику фокуса на NoFocus ещё нескольких элементов, находящихся на одном уровне с главным StackedWidget-ом иначе они при старте перетягивали фокус на себя.
Это позволило отказаться от этой ф-ии и пока этого хватает