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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: tabbed docked area  (Прочитано 9656 раз)
EhTemka
Гость
« : Декабрь 22, 2008, 11:49 »

Всем привет.

Qt 4.2.3

Такие вопросы.

Есть некие доквиджеты, которые составлены в табулятор. Как-нибуть можно узнать, какой из доков в данный момент активен, а какие нет.
Дело в том, что неактивные доквиджеты в табуляторе не являются почему-то скрытыми. Т.е. у них isVisible() = true.
И как я не пробовал (в т.ч. с помошью eventFilter)  отловить момент переключения доквиджетов в этом табуляторе, ни чего не получалось.

И вообще, можно узнать в табуляторе ли доквиджет, или нет?
Записан
SABROG
Гость
« Ответ #1 : Декабрь 22, 2008, 14:36 »

QMainWindow использует QTabBar, который в принципе никак не привязан к виджетам кроме как через сигналы. Т.е. поступил сигнал currentChaned - вызывался метод QWidget::raise() для centralWidget() - (bring to top, поместить на вершину), по сути окна просто тупо лежат друг на друге (не используются ни QStackedWidget ни QStackedLayout). Т.ч. надо проверить возвращает ли centralWidget() текущее активное окно, а также попробывать всякие isActiveWindow, activateWindow...
Записан
EhTemka
Гость
« Ответ #2 : Декабрь 22, 2008, 15:26 »

Вообщем, я так понял, что ни как  Грустный
Доки не становятся активными. Вообще при переключении доков в табуляторе происходит только два события 
QEvent::Move
и
QEvent::Paint

Эх...
Записан
SABROG
Гость
« Ответ #3 : Декабрь 22, 2008, 17:23 »

А если сигнал обрабатывать этот ?

Цитировать
void QDockWidget::visibilityChanged ( bool visible )   [signal]
This signal is emitted when the dock widget becomes visible (or invisible). This happens when the widget is hidden or shown, as well as when it is docked in a tabbed dock area and its tab becomes selected or unselected.

В самом QDockWidget на QEvent::Hide и QEvent::Show должны сигналы выпускаться.
Еще вот такая штука интересная есть:

Код
C++ (Qt)
   QMainWindow *win = qobject_cast<QMainWindow*>(parentWidget());
   QMainWindowLayout *layout = 0;
   if (win != 0)
       layout = qobject_cast<QMainWindowLayout*>(win->layout());
...
   case QEvent::ZOrderChange: {
       bool onTop = false;
       if (win != 0) {
           const QObjectList &siblings = win->children();
           onTop = siblings.count() > 0 && siblings.last() == (QObject*)this;
       }
       if (!isFloating() && layout != 0 && onTop)
           layout->raise(this);
       break;
   }
 
« Последнее редактирование: Декабрь 22, 2008, 17:28 от SABROG » Записан
EhTemka
Гость
« Ответ #4 : Декабрь 22, 2008, 19:01 »

Цитировать
В самом QDockWidget на QEvent::Hide и QEvent::Show должны сигналы выпускаться.
В том то и дело, что не происходит ни Hide, ни Show.

ПО поводу остального посмотрю.
Записан
SABROG
Гость
« Ответ #5 : Декабрь 22, 2008, 21:19 »

Цитировать
В самом QDockWidget на QEvent::Hide и QEvent::Show должны сигналы выпускаться.
В том то и дело, что не происходит ни Hide, ни Show.

Ну дык ты же сказал, что в "табуляторе", я так понял ты говоришь о событиях QTabBar'a. А я предлагаю проверить события QDockWidget'a отдельно взятого.
Записан
EhTemka
Гость
« Ответ #6 : Декабрь 23, 2008, 10:11 »

Я имел ввиду QDockWidget'ы составленные в табулятор. Пользователь распологает QDockWidget'ы как ему заблагорассудится. В том числе он может какие нибуть из них составить в табулятор. В доках у меня происходят запросы к базе данных каждые несколько секунд. Я хотел оптимизировать программу за счет того, чтобы не обновлять(производить запросы) в доке, который не виден в данный момент.
 
Проверял события QDockWidget'a отдельно взятого, так как к QTabBar'у доступа нет.

По поводу QEvent::ZOrderChange. А где его отлавливать?
Записан
SABROG
Гость
« Ответ #7 : Декабрь 23, 2008, 13:50 »

Используй const QObjectList & QObject::children () const, список будет ровно в том порядке в котором находятся сестринские окна в стеке. Первый элемент - видимый и выше всех.
Записан
vaprele07
Гость
« Ответ #8 : Декабрь 24, 2008, 06:43 »

QEvent::Hide и QEvent::Show приходят контролируемому виджету
QWidget * QDockWidget::widget () const, вот только в момент перетаскивания доквиджета они тоже приходят, почему хз.
Записан
EhTemka
Гость
« Ответ #9 : Декабрь 24, 2008, 21:47 »

QEvent::Hide и QEvent::Show приходят контролируемому виджету
QWidget * QDockWidget::widget () const, вот только в момент перетаскивания доквиджета они тоже приходят, почему хз.

Какая версия Qt? У меня на QDockWidget::widget () приходит только QEvent::Paint при переключении. Qt 4.2.3

Используй const QObjectList & QObject::children () const, список будет ровно в том порядке в котором находятся сестринские окна в стеке. Первый элемент - видимый и выше всех.

Этот вариант будет работать если я точно знаю, что все доки составлены в табулятор. Тогда, конечно, можно быть уверенным, что
Первый элемент - видимый, остальные - нет. Может быть такая ситуация, что 3 виджета в табуляторе, а два сами по себе. И это ни как не определишь. В течении сессии я не знаю точно как расположены QDockWidget (т.е. в табуляторе ли они, или еще как). Если какие-то QDockWidgetы составленны в табулятор, то мне хотелось бы знать об этом, и знать, какой из доков сверху, а какие снизу.

Всем спасибо за участие. Но видимо проблему можно решить (наверно?) с переходом на более новую версию Qt
Записан
SABROG
Гость
« Ответ #10 : Декабрь 25, 2008, 09:16 »

У виджетов есть координаты и размеры, если x,y,width, height совпадают, значит они в табуляторе. Ну или висят просто друг над другом как простые окна, т.е. уже за пределами mainwindow, на этот случай есть флаг isFloating().
« Последнее редактирование: Декабрь 25, 2008, 09:18 от SABROG » Записан
EhTemka
Гость
« Ответ #11 : Декабрь 25, 2008, 11:00 »

SABROG, спасибо.

Хоть ты оказался и не прав на счет равенства координат, но ты (и штудирование кода кутешной библиотеки) направили меня на "путь истинный".

Вообщем дело в следующем. Размеры у доков составленных в таб ессно одинаковы, и если брать QDockWidget::rect()-ы они будут одинаковы. Но вот если взять QDockWidget::geometry(), или проще x() или у(), то получится, что у доков, которые в табуляторе и неактивны(то есть снизу) - значения x,y отрицательны. Я не особо понимаю почему так (возможно так само куте понимает, что не надо рисовать этот виджет, или дает таким образом понять оконному менегеру), но факт.

Если QDockWidget - ы составленны в табулятор, то у активного дока(который сверху) коодинаты положительные, у остальных - отрицательные.  

Хоть решение и карявенькое, зато простое -всего одна проверка.

Код
C++ (Qt)
if(dockWidget->y() < 0)
{
...
}
Записан
SABROG
Гость
« Ответ #12 : Декабрь 25, 2008, 23:49 »

Я пошаманил немного и нашел нестандартное решение. Сразу хочу предупредить, что этот вариант может не работать на других версиях Qt, т.к. в них может быть уже по другому реализован класс QMainWindow/QDockWidget.

Код
C++ (Qt)
   QList <QTabBar *>lst = this->findChildren<QTabBar *>(); // рекурсивно ищем деток типа QTabBar* в QMainWindow
   quint8 i = 0; // 255 TabBar'ов должно хватить ;)
   foreach(QTabBar *tab, lst)
   {
/*
QTabBar'ы могут создаваться, но не уничтожатся, поэтому они могут быть невидимы.
Еще есть вариант, когда в TabBar'e всего 2 DockWidget'а, при этом один плавает (floating),
пользователь видет, что TabBar исчез, однако реально исчезает только ярлычек.
QTabBar скрывается, когда плавающее окно пришвартовывается куда-нибудь и в QTabBare
остается всего 1 элемент. В общем проверка с count'ом опциональна, чтобы детектить
где QTabBar'ы имеют ярлычки.
*/

       if (tab->isVisible() /*&& tab->count() > 1*/)
       {
           i++; // ведем подсчет видимых QTabBar'ов, если надо
/*
Далее идет непереводимая игра слов :)
Разработчики Qt в каждый ярлычек помещают указатель на QDockWidget, которому ярлычек принадлежит.
Процедура перевода указателя QWidget'a в QVariant с пользовательским типом и обратно.
Страшный тип quintptr - кроссплатформенный вариант указателя, где надо его размер 32 бита, где не надо 64.
*/

           quintptr wId = qvariant_cast<quintptr>(tab->tabData(tab->currentIndex()));
           QDockWidget *widget = reinterpret_cast<QDockWidget *>(wId);
           QMessageBox::information(0,"Info", QString("class:%1, title:%2").arg(widget->metaObject()->className()).arg(widget->windowTitle()));
       }
   }
 

Логика кода следующая. Ищем все видимые QTabBar'ы и получаем указатель на QDockWidget, который в данный момент показывается пользователю (тоже самое что и QTabWidget::currentWidget()).
Записан
EhTemka
Гость
« Ответ #13 : Декабрь 26, 2008, 16:31 »

reinterpret_cast как-то немного пугает Улыбающийся Но идею понял.
Пока не буду это реализовывать (вариант с отрицательными координатами пока устраивает), но спасибо за разъяснение,   
как это всё работает.

Имхо, лучшим вариантом было бы, если троли таки сделали нормальный интерфейс для работы с QDockWidget-ми
Записан
SABROG
Гость
« Ответ #14 : Декабрь 26, 2008, 17:30 »

Можно еще такой вариант провернуть. Коннектим сигнал visibilityChanged() каждого виджета к одному слоту в своем классе. Через sender() определяем отправителя, добавляем динамическое свойство QObject'a для QDockWidget'a, которое отображает текущее состояние: видимый/невидимый. Меняем в зависимости от пришедшего с сигналом флага. В общем замена методу isVisible(), раз уж он не работает почему-то.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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