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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Эмуляция доков сплиттерами  (Прочитано 4474 раз)
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« : Июня 09, 2011, 20:49 »

У меня есть задача - на табе разместить интерфейс, похожий на доки - то есть 5 областей (4 вокруг и 1 в центре). Нагромоздил я кучу сплиттеров и возник косяк - если область ничего не содержит (при этом сама является сплиттером), то у ее парент сплиттера рисуется хэндл, несмотря на то, что размер области 0. Как бороться?
Сплиттер считает вложенный сплиттер полноценным виджетом и хз как заставить его хайдить хэндл в случае, если вложенный сплиттер пуст. Проблема что при попытке хайдить вложенные сплиттеры им перестают приходить эвенты от реальных виджетов (типа ShowToParent приходит самому верхнему ВИДИМОМУ виджету).
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Июня 10, 2011, 06:53 »

Может для лучшего понимания проблемы покажешь скриншот?
И чем не устроил QMainWindow с доками?
Записан

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

Сообщений: 3260


Просмотр профиля
« Ответ #2 : Июня 10, 2011, 09:26 »

Черные полоски вокруг - это хэндлы сплиттеров (по идее они 1 пиксель толщиной, но для наглядности сделал 7). Собсно над верхней полоской, справа от правой и т.п. могут как быть, так и не быть виджеты. Расположение сплиттеров (на топ левеле - вертикальный, в нем 3 горизонтальных. В центральном горизонтальном еще 3 вертикальных сплиттера)
Код:
---
|||
---
Из-за того, что верхний/нижний сплиттеры не спрятаны, хотя и пусты, главный сплиттер рисует для них хэндлы. Аналогично для центрального.
Доки не устроили тем, что мне надо доки в табе, а в табе надо еще и стакед лэйаут. А тролли захардкодили док лэайут в мейнвиндоу. Это можно эмулировать используя флаг при компиляции Qt EXPERIMENTAL_USER_DECORATIONS, чтобы разместить таббар ВНЕ доков, но наличие этой фичи всё еще под вопросом, кроме того приходится эмулировать иерархию таб->стакед->доки. Когда-нибудь, когда у меня будет много времени, я перепишу кьютовские доки в отдельный виджет.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #3 : Июня 10, 2011, 11:08 »

Цитата: Авварон
Доки не устроили тем, что мне надо доки в табе, а в табе надо еще и стакед лэйаут. А тролли захардкодили док лэайут в мейнвиндоу. Это можно эмулировать используя флаг при компиляции Qt EXPERIMENTAL_USER_DECORATIONS, чтобы разместить таббар ВНЕ доков, но наличие этой фичи всё еще под вопросом, кроме того приходится эмулировать иерархию таб->стакед->доки.
Не вижу проблемы использования QMainWindow и табов. Вешаешь QTabBar, под ним QMainWindow. На последний накидываешь QDockWidget-s.
Вот примерно так:
Код
C++ (Qt)
#include <QApplication>
#include <QMainWindow>
#include <QDockWidget>
#include <QTabBar>
#include <QVBoxLayout>
#include <QVariant>
 
#include <QTextEdit>
#include <QPushButton>
 
static QDockWidget* addDock( QWidget* w );
 
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow( QWidget* parent = 0 )
: QWidget( parent )
{
QVBoxLayout* l = new QVBoxLayout( this );
l->setContentsMargins( 0, 0, 0, 0 );
l->setSpacing( 0 );
 
tb_ = new QTabBar;
l->addWidget( tb_ );
connect( tb_, SIGNAL( currentChanged( int ) ), SLOT( switchTab( int ) ) );
 
mw_ = new QMainWindow;
l->addWidget( mw_ );
mw_->setWindowFlags( Qt::Widget );
}
 
void addWidget( Qt::DockWidgetArea area, QWidget* w )
{
if( area == Qt::NoDockWidgetArea )
{
mw_->setCentralWidget( w );
return;
}
 
QDockWidget* dw = new QDockWidget( w->windowTitle() );
 
#if 1 // if no title needed
QWidget* tb = new QWidget;
tb->setFixedSize( 0, 0 );
dw->setTitleBarWidget( tb );
#endif
dw->setFeatures( QDockWidget::NoDockWidgetFeatures );
dw->setWidget( w );
 
connect( w, SIGNAL( destroyed(QObject*) ), SLOT( removeTab(QObject*) ) );
dw->connect( w, SIGNAL( destroyed() ), SLOT( deleteLater() ) );
 
mw_->addDockWidget( area, dw );
 
int i = tb_->addTab( w->windowTitle() );
tb_->setTabData( i, qVariantFromValue( w ) );
}
 
protected slots:
void switchTab( int i )
{
if( QWidget* w = tb_->tabData( i ).value< QWidget* >() )
{
w->show();
w->setFocus();
}
}
void removeTab( QObject* o )
{
for( int i = 0; i < tb_->count(); i++ )
{
QWidget* w = tb_->tabData( i ).value< QWidget* >();
if( w == o )
{
tb_->removeTab( i );
break;
}
}
}
 
private:
QMainWindow* mw_;
QTabBar* tb_;
};
 
int main( int argc, char** argv )
{
QApplication app( argc, argv );
MainWindow w;
 
QTextEdit te;
w.addWidget( Qt::NoDockWidgetArea, &te );
 
const char *titles[] = { "Left", "Right", "Top", "Bottom" };
 
for( int i = 0; i < 4; i++ )
{
QPushButton* pb = new QPushButton;
pb->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
pb->setWindowTitle( titles[i] );
pb->setText( "Press to hide..." );
#if 0
pb->connect( pb, SIGNAL( clicked() ), SLOT( deleteLater() ) );
#else
pb->connect( pb, SIGNAL( clicked(bool) ), SLOT( setVisible(bool) ) );
#endif
w.addWidget( Qt::DockWidgetArea( 1 << i ), pb );
}
 
w.show();
return app.exec();
}
 
#include "t8_moc.cpp"
 

PS: исправил удаление.
« Последнее редактирование: Июня 10, 2011, 11:19 от GreatSnake » Записан

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

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Июня 10, 2011, 11:21 »

Мог не писать код, я в курсе про этот способ. Он также черезжопный, есть артефакты рисования у QMainWindow если его класть как виджет. Ну и плюс оверхед в виде тулбаров/статусбаров/менюбаров, их лэйаутов и тп.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #5 : Июня 10, 2011, 11:31 »

Мог не писать код, я в курсе про этот способ.
Ты описал надуманную проблему про QMainWindow/QTabBar/QStackWidget - я пытался объяснить обратное)

Цитировать
Он также черезжопный, есть артефакты рисования у QMainWindow если его класть как виджет.
На X11/Win не видел. Может на маке и есть.

Цитировать
Ну и плюс оверхед в виде тулбаров/статусбаров/менюбаров, их лэйаутов и тп.
Нашел на чём экономить) Тем более они в таком случае не создаются.
Записан

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

Сообщений: 2921



Просмотр профиля
« Ответ #6 : Июня 10, 2011, 11:41 »

Цитата: Авварон
Проблема что при попытке хайдить вложенные сплиттеры им перестают приходить эвенты от реальных виджетов (типа ShowToParent приходит самому верхнему ВИДИМОМУ виджету).
Кстати, а не пробовал у соответствующего QSplitterHandle установить width/height в 0?
Записан

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

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Июня 10, 2011, 11:46 »

У меня проблема в том, чтобы узнать - есть там что-то или нет:) То есть я не смог подобрать эвент, при котором бы стоило делать проверку на то, что чайлды сплиттера визибл.
Сейчас проблему решил по-тупому - мануально сделал метод hideArea(int) к-й прячет область (Улыбающийся). Это еще и плюшку дает что можно юзеру хайдить не отдельный "док" а всю панель целиком.
Второй вариант ще более тупой, изначально прятать сплиттеры, а показывать при добавлении в них виджета. Но это не спасет от той же проблемы, если виджет "закроют" и сплиттер будет визуально пустой.
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #8 : Июня 10, 2011, 11:53 »

Перегрузи
Код
C++ (Qt)
void QSplitter::childEvent ( QChildEvent * c ) [virtual protected]
и показывай/прячь соответствующий QSplitterHandle, если добавили/удалили чайлд.
Записан

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

Сообщений: 3260


Просмотр профиля
« Ответ #9 : Июня 10, 2011, 12:14 »

Да, в QObject-то я не заглянул:) Лан, спасибо, но наверно уже не буду экспериментировать.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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