Сегодня озадачился таким вопросом. Как получить текущий 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()));
}
}
Windows XP Professional SP3 (2002 build)
MinGW 3.4.5
Qt 4.4.0-beta1 (такой и нет уже наверное)
может я что-то не понял, но узнать видимый или нет я могу так:
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;
}
Dock "Customers" isVisible? true
Dock "Paragraphs" isVisible? true
Тоже вариант, правда неудобный. Придется создавать лист виджетов с их состояниями, чтобы можно было определить какие из-них в данный момент отображаются. Удалять и добавлять в лист закрытые и новые созданные виджеты. Да и переключением закладок програмным методом уже не воспользоваться.
в Qt 4.4.3. есть
int QTabWidget::currentIndex()const;
void QTabWidget::currentChanged(int);[signal]
не поможет?
SABROG, вобщем, тему стоит пожевать и найти решение. Я думаю надо делать либо класс "организатор", либо наследника более умного от QDockWidget.
SABROG, давай еще раз формулировку задачи.
Положим есть такие ситуации:
1) доквиджеты расположены самостоятельно, т.е. не скрывая другдруга
2) только два доквиджета из нескольких сложены в виде вкладок
3) существует несколько групп доквиджетов сложенных в виде вкладок (т.е. как на рисунке в первом посте)
при этом только один из доквиджетов имеет фокус
что нужно определить/сделать?
Предположим ситуацию. У пользователя есть доквиджеты в которых размещаются таблицы базы данных.
От сервера приходит сообщение, что данные в таблицах изменились и их надо обновить.
Операция обновления может быть достаточно долгим процессом, особенно если данных много, а канал маленький.
Более того, операция обновления может быть бесполезной, если пользователь работает только с несколькими
активными доквиджетами. Стало быть надо определить какие виджеты в данный момент может видеть пользователь,
чтобы обновлять только их.
Или можно аналогичный пример только уже с графикой. Есть несколько виджетов - окон,
в которых происходит отрисовка сцены, предположим каждое окно - вид камеры.
Цель - обновлять только видимые камеры.
в итоге: список видимых (или тех, что сверху) в данный момент доквиджетов.
да, уместнее было бы чтобы это была функция QMainWindow, например: QList<QWidget*> QMainWindow::topDocWidgetsList()
Я предлагаю не ограничиваться только этой задачей. Т.к. переключение табов, добавление, удаление виджета из/в таб/а програмным методом было бы тоже интересно. Правда я не пробывал, возможно ли сейчас сложить в табы выбранные доквиджеты програмным методом ? Это надо move() делать на заданные координаты или флаги какие устанавливать ?
В общем решил развить тему сигнала visibilityChanged. На этот раз метод должен работать везде, т.к. привязки к нестандартным вещам нет
В конструкторе соединями сигналы каждого QDockWidget'а к одному слоту. Можно соединять вручную поименно каждый виджет, как удобнее. Просто с учетом на будущее я решил пробежаться по всем детишкам, мало ли добавится еще пара окон.
DockWidgets::DockWidgets(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QList <QDockWidget *> lst = findChildren<QDockWidget *>();
foreach(QDockWidget *widget, lst)
{
connect(widget, SIGNAL(visibilityChanged(bool)), SLOT(slotVisibilityChanged(bool)));
}
}
void DockWidgets::slotVisibilityChanged(bool visible)
{
QObject *sndr = sender();
if (sndr)
{
sndr->setProperty("dockIsVisible", visible);
qDebug()
<< "CName:" << sndr->metaObject()->className()
<< "WTitle: " << sndr->property("windowTitle").toString()
<< "isVisible(): " << sndr->property("visible").toString()
<< "vChange: " << sndr->property("dockIsVisible").toString();
}
}
CName: QDockWidget WTitle: "2" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "1" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "3" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "4" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "5" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "6" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "7" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "8" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "9" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "10" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "3" isVisible(): "false" vChange: "false"
CName: QDockWidget WTitle: "3" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "3" isVisible(): "false" vChange: "false"
CName: QDockWidget WTitle: "3" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "3" isVisible(): "true" vChange: "false"
CName: QDockWidget WTitle: "3" isVisible(): "true" vChange: "true"
CName: QDockWidget WTitle: "2" isVisible(): "true" vChange: "false"
SABROG, чёто с форматированием, как-то все плохо
из изменений в 4.5.0:
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)