crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> Как получить текущий QDockWidget, который отображается в QTabBar'e на MainWindow
SABROG
  опции профиля:
сообщение 26.12.2008, 0:01
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Сегодня озадачился таким вопросом. Как получить текущий QDockWidget, который отображается в QTabBar'e на MainWindow. Т.е. это QDockWidget'ы положенные друг на друга таким образом, что появляются ярлычки как в QTabWidget. Но проблема в том, что это QTabBar и у него нет метода типа QTabWidget::currentWidget(). Более того, по сути эти QTabBar'ы не принадлежат нам и получить на них указатели стандартными средствами QMainWindow мы не можем. Также напрашивается решение - пробежаться по всем QDockWidget'ам и найти те, которые не спрятаны (isVisible). Со слов другого человека этот вариант не работает, т.к. у всех виджетов метод isVisible возвращает true. Также я предложил вариант проверить x,y,width,height. Если у двух виджетов они одинаковы, значит они лежат друг на друге, а следовательно в "стеке" (QMainWindow не использует ни один из вариантов стека виджетов или лэйаутов). Но оказалось, что у видимых QDockWidget'ов координаты положительные, в то время как у скрытых за ними виджетами они отрицательные. Т.е. этот способ можно использовать, но выглядит он не очень надежным. В итоге этот вопрос привел меня к следующему решению.

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

    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()).



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

Сообщение отредактировал SABROG - 26.12.2008, 0:20
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
3 страниц V   1 2 3 >  
Начать новую тему
Ответов (1 - 9)
Litkevich Yuriy
  опции профиля:
сообщение 26.12.2008, 0:18
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(SABROG @ 26.12.2008, 3:01) *
хочу предупредить, что этот вариант может не работать на других версиях Qt
а на какой проверял и ОСька какая?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 26.12.2008, 0:22
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Windows XP Professional SP3 (2002 build)
MinGW 3.4.5
Qt 4.4.0-beta1 (такой и нет уже наверное)

Сообщение отредактировал SABROG - 26.12.2008, 0:26
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.12.2008, 0:40
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


может я что-то не понял, но узнать видимый или нет я могу так:
void MainWindow::createDockWindows()
{
...
QDockWidget *dock = new QDockWidget(tr("Customers"), this);
...
// Добавил соединение
connect(dock, SIGNAL(visibilityChanged(bool) ), this, SLOT(slot_visibilityChanged(bool)));
...
dock = new QDockWidget(tr("Paragraphs"), this);
...
// Добавил соединение
connect(dock, SIGNAL(visibilityChanged(bool) ), this, SLOT(slot_visibilityChanged(bool)));
...
}


// Добавил слот
void MainWindow::slot_visibilityChanged ( bool visible )
{
    QDockWidget *dock = qobject_cast<QDockWidget *>(sender());
    qDebug() << "Dock" << dock->windowTitle() << "isVisible?" << visible;
}

это доработка примера %QTDIR%\examples\mainwindows\dockwidgets


вывод в консоль при старте:
Dock "Customers" isVisible? true
Dock "Paragraphs" isVisible? true

и в том же духе при перетаскивании и всяком разном расположении
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 26.12.2008, 9:14
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Тоже вариант, правда неудобный. Придется создавать лист виджетов с их состояниями, чтобы можно было определить какие из-них в данный момент отображаются. Удалять и добавлять в лист закрытые и новые созданные виджеты. Да и переключением закладок програмным методом уже не воспользоваться.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kwisp
  опции профиля:
сообщение 26.12.2008, 10:16
Сообщение #6


астарожна ынтжинэр
*****

Группа: Участник
Сообщений: 1404
Регистрация: 26.11.2008
Из: ТаганрогРодинаЧехова
Пользователь №: 435

Спасибо сказали: 113 раз(а)




Репутация:   23  


в Qt 4.4.3. есть
int QTabWidget::currentIndex()const;
void QTabWidget::currentChanged(int);[signal]

не поможет?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.12.2008, 10:54
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


SABROG, вобщем, тему стоит пожевать и найти решение. Я думаю надо делать либо класс "организатор", либо наследника более умного от QDockWidget.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 26.12.2008, 12:12
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(kwisp @ 26.12.2008, 10:16) *
не поможет?

Совершенно. QMainWindow использует QTabBar'ы, не QTabWidget'ы. А в QTabBar'е есть только currentIndex.
Но опять же стандартными методами через QMainWindow невозможно получить список указателей на QTabBar'ы, если таковые существуют. А их может и не быть, если пользователь не манипулировал с доками.

Цитата(Litkevich Yuriy @ 26.12.2008, 10:54) *
SABROG, вобщем, тему стоит пожевать и найти решение. Я думаю надо делать либо класс "организатор", либо наследника более умного от QDockWidget.

Если делать умного наследника от QDockWidget'а, то что это должно дать ? Проверку типа isTopWidget() ?
Класс организатор тоже решение. Хоть и правильное решение с точки зрения программирования, но достаточно непростое и скорее смахивает на затычку.

По-хорошему надо написать и класс-менеджер и добавить в таск-лист троллям, что хотелось бы иметь подобную возможность. Т.е. добавить методы для QMainWindow и доп.класс типа QDockTabBar на базе QTabBar:
QList <QDockTabBar *> QMainWindow::dockTabBars() const

Для класса QDockTabBar метод:
QDockWidget * QDockTabBar::currentWidget() const
void QDockTabBar::setCurrentWidget(QDockWidget *dw)

Может еще какие-то.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.12.2008, 12:37
Сообщение #9


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


SABROG, давай еще раз формулировку задачи.
Положим есть такие ситуации:
1) доквиджеты расположены самостоятельно, т.е. не скрывая другдруга
2) только два доквиджета из нескольких сложены в виде вкладок
3) существует несколько групп доквиджетов сложенных в виде вкладок (т.е. как на рисунке в первом посте)

при этом только один из доквиджетов имеет фокус

что нужно определить/сделать?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 26.12.2008, 13:15
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Предположим ситуацию. У пользователя есть доквиджеты в которых размещаются таблицы базы данных.
От сервера приходит сообщение, что данные в таблицах изменились и их надо обновить.
Операция обновления может быть достаточно долгим процессом, особенно если данных много, а канал маленький.
Более того, операция обновления может быть бесполезной, если пользователь работает только с несколькими
активными доквиджетами. Стало быть надо определить какие виджеты в данный момент может видеть пользователь,
чтобы обновлять только их.

Или можно аналогичный пример только уже с графикой. Есть несколько виджетов - окон,
в которых происходит отрисовка сцены, предположим каждое окно - вид камеры.
Цель - обновлять только видимые камеры.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V   1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.11.2024, 0:06