Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Разворачивающиеся панели

Автор: 0xF 17.3.2008, 14:44

Как замутить вот такие панели на Qt(Object Type, Name and Color etc.)?



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

Как замутить? Может есть готовое решение?

Автор: Litkevich Yuriy 17.3.2008, 15:02

помоему, QToolBox не подойдет, надо на основе дерева делать или QGroupBox
например так:


виджеты в нутри QGroupBox'ов располагаются внутри каких нибудь контейнеров, эти контейнеры когда надо отображать когда не надо прятать.

Автор: 0xF 17.3.2008, 15:36

Та вот плохо, что не подойдет... Допустим сделаю я контрол на основе контейнеров и груп боксов... можно ли это потом как-нить встроить в QtDesigner? А то меня как-то не греет перспектива конструировать все это в коде... :(

Автор: Litkevich Yuriy 17.3.2008, 15:45

есть два рианта:
1 создать модуль для дизайнера, на основе твоего класса (http://crossplatform.ru/documentation/qtdoc4.3/designer-creating-custom-widgets.php)
2 установить в дизайнере использование иного класса (http://crossplatform.ru/documentation/qtdoc4.3/designer-using-custom-widgets.php)

Автор: 0xF 17.3.2008, 19:26

Ага, спс :) А как вобще этот контрол называется? Тот шо в 3ds max на скрине

Автор: Litkevich Yuriy 17.3.2008, 19:29

не знаю, может у них самописаный

Автор: 0xF 17.3.2008, 19:48

А где-нить в сети можно скачать виджеты для Qt? Может уже есть что-то подобное...

Автор: trdm 17.3.2008, 19:55

http://www.crossplatform.ru/?q=taxonomy/term/65
http://www.qt-apps.org/

Автор: Litkevich Yuriy 17.3.2008, 19:57

http://www.qt-apps.org/
http://www.qt-prop.org
на них такого нет

есть еще такие
http://labs.trolltech.com
http://www.qtcentre.org/
на http://sourceforge.net ищи

Автор: 0xF 17.3.2008, 20:11

Вот, кое-что нашел, индус накодил :) http://www.vcreatelogic.com/oss/qpulistview/index.html

Автор: Litkevich Yuriy 17.3.2008, 20:19

да очень похоже на твой скриншот, одна беда портировать прийдется под Qt4 или разобратся как работает и сделать свой

Автор: 0xF 17.3.2008, 21:57

Решил сделать по-своему. В QVBoxLayout толкаю парами QPushButton и QGroupBox. Разворачивается и сворачивается(просто по нажатию на кнопку прячу соответсвующий QGroupBox). Вышел косяк: при соврачивании какой-то одной группы, остальные автоматом растягиваются для занятия всей площади QVBoxLayout:
До:


После(открытые группы растянулись):

Ещё бы можно было как-то пережить, если бы не вот такая фигня при отсутствии открытых групп:


Нашел у QVboxLayout метод addSpacing, при закрытии группы добавляю отступ равный высоте QGroupBox, при открытии вычитаю... но тут тоже косяк, если много раз открыть-закрыть какую-то группу, то отсуп накапливается и выходит вот такая фигня(красным обозначен накопленный левый отсутп):


Может забить на QVBoxLayout? Но тогда надо будет каждый раз вручную тасовать все QGroupBox & QPushButton...

Any ideas? :)

Автор: Litkevich Yuriy 17.3.2008, 22:03

ну ясен перец на то он и Layout, попробуя задавать sizePolicy для QGroupBox как fixed (по вертикали), после того как на толкаешь в них (QGroupBox) нужных виджетов и толко потом прятать/показывать.
Снизу добавь, спэйсер, когда будут исчезать QGroupBox'ы он будет всю систему подпирать с низу как пружинка

---
на заметку:
тот факт, что у тебя отступ накапливается, говорит о том, что спейсеров у тебя все больше и больше :) (т.е. они не удаляются)

Автор: 0xF 17.3.2008, 22:31

Блин, ну и гемор с этим лейаутом...
Ладно, пока забил на корректировку размеров... может и на лейаут забью: сам буду тасовать :)

Фигня какая-то с размерами... надо бы подкорректировать размеры моего виджета под размеры предка. Пример:

QDockWidget *foldDock = new QDockWidget( "Foldout", this );

QFoldout *foldOut = new QFoldout( foldDock ); // ** Мой виджет

foldDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
foldDock->setWidget( foldOut );

addDockWidget( Qt::RightDockWidgetArea, foldDock );

foldOut->resize( foldDock->size() );

Даже после foldOut->resize ничо не изменилось... width = 100, height = 30 :( Почему?? Ведь само окошко (foldDock) куда больше чем 100х30(см. скрины выше)

Автор: Litkevich Yuriy 17.3.2008, 22:38

попробую угадать с закрытыми глазами:
foldOut в Layout'е лежит
у Layout'а способность регулировать толко от этого и завит что он меняет размер виджета, а иначеб он несмог работать

Автор: Litkevich Yuriy 17.3.2008, 22:41

QFoldout это твой класс, от QWidget?

тогда тебе надо сделать рекомендуху для Layout'а в своем классе:

// Рекомендация размера, для Layout'ов
QSize QFoldout::sizeHint() const
{
    return size();
}

Автор: 0xF 17.3.2008, 22:52

Да, QFoldout - мой класс от QWidget, QVBoxLayout я пока убрал и кидаю кнопки прям в него(QFoldout):

void QFoldout::AddGroup( const std::string caption )
{
    QPushButton *button = new QPushButton( caption.c_str(), this );
    QGroupBox *group    = new QGroupBox( this );

    connect( button, SIGNAL( clicked(bool) ), this, SLOT( OnCategoryButtonClicked(bool) ) );

    button->setCheckable( true );
    button->setChecked( true );
}


И вот такой конструктор:
QFoldout::QFoldout( QWidget *parent ) : QWidget( parent ) {
    if( parent ) resize( parent->size() );
}


В итоге никакие ресайзы не помагают: размер 100х30... Вобще ресайз не работает... ни для моего QFoldout, ни для ихнего QDockWidget :(

Автор: 0xF 17.3.2008, 22:58

О, после добавки QFoldout::sizeHint можно хотя бы вручную ресайзить...

Автор: Litkevich Yuriy 17.3.2008, 23:02

пример от Макса Шлее:
main.cpp:

CODE

#include <QtGui>
#include "CustomWidget.h"

// ----------------------------------------------------------------------
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWidget wgt;

CustomWidget* pcw = new CustomWidget;
QScrollBar* phsb = new QScrollBar(Qt::Horizontal);

phsb->setRange(0, 100);

QObject::connect(phsb, SIGNAL(valueChanged(int)),
pcw, SLOT(slotSetProgress(int))
);

//Layout setup
QVBoxLayout* pvbxLayout = new QVBoxLayout;
pvbxLayout->addWidget(pcw);
pvbxLayout->addWidget(phsb);
wgt.setLayout(pvbxLayout);

wgt.show();

return app.exec();
}

CustomWidget.h:
CODE

#ifndef _CustomWidget_h_
#define _CustomWidget_h_

#include <QFrame>

// ======================================================================
class CustomWidget : public QFrame {
Q_OBJECT
protected:
int m_nProgress;

virtual void paintEvent(QPaintEvent*);

public:
CustomWidget(QWidget* pwgt = 0);

virtual QSize sizeHint() const;

signals:
void progressChanged(int);

public slots:
void slotSetProgress(int n);
};
#endif //_CustomWidget_h_

CustomWidget.cpp:
CODE

#include <QtGui>
#include "CustomWidget.h"

// ----------------------------------------------------------------------
CustomWidget::CustomWidget(QWidget* pwgt/*= 0*/) : QFrame(pwgt)
, m_nProgress(0)
{
setLineWidth(3);
setFrameStyle(Box | Sunken);

setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
}

// ----------------------------------------------------------------------
/*virtual*/ void CustomWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QLinearGradient gradient(0, 0, width(), height());
float f = m_nProgress / 100.0f;

gradient.setColorAt(0, Qt::black);
gradient.setColorAt(f, Qt::green);

painter.fillRect(rect(), Qt::black);
painter.setBrush(gradient);
painter.drawRect(0, 0, (int)(width() * f), height());

painter.setPen(QPen(Qt::green));
QString str = QString().setNum(m_nProgress) + "%";
painter.drawText(rect(), Qt::AlignCenter, str);

drawFrame(&painter);
}

// ----------------------------------------------------------------------
void CustomWidget::slotSetProgress(int n)
{
m_nProgress = n > 100 ? 100 : n < 0 ? 0 : n;
repaint();
emit progressChanged(m_nProgress);
}

// ----------------------------------------------------------------------
/*virtual*/ QSize CustomWidget::sizeHint() const
{
return QSize(200, 30);
}


он жестко задал размер

Автор: 0xF 18.3.2008, 0:17

.

Автор: 0xF 20.3.2008, 16:57

Так, новая запарка возникла :)
Вот код, добавляющий страницу в мой контрол:

void QFoldout::AddPage( const std::string& caption, QGroupBox *group )
{
    QPushButton *button = new QPushButton( caption.c_str(), this );

    connect( button, SIGNAL( clicked(bool) ), this, SLOT( OnCategoryButtonClicked(bool) ) );

    button->setCheckable( true );
    button->setChecked( true );
    button->setVisible( true );
    group->setVisible( true );
    group->setParent( this );

    categoryMap[ button ] = group;
    buttonMap[ caption ] = button;

    Layout();
}


И ф-ция Layout для расстановки страниц в нужном порядке:
void QFoldout::Layout( void )
{
    tCategoryMapIter end = categoryMap.end();

    int w = width();
    int yOffset = 0;

    const int k_ButtonHeight = 22;
    const int k_ButtonOffset = 0;

    for( tCategoryMapIter i = categoryMap.begin(); i != end; i++ ) {
        QPushButton *button = i->first;
        QGroupBox   *group    = i->second;

        button->setGeometry( k_ButtonOffset, yOffset, w - k_ButtonOffset * 2, k_ButtonHeight );
        group->setGeometry( 0, yOffset + k_ButtonHeight, w, group->height() );

        if( button->isVisible() ) yOffset += k_ButtonHeight; // ** Вот тут собственно запарка, isVisible возвращает false
        if( group->isVisible() ) yOffset += group->height(); // ** для QPushButton и для QGroupBox :(
    }

    resize( QSize( w, yOffset ) );
}


Прошелся дебагером по коду: сразу же после вставки страницы вызывается ф-ция Layout(см. код), но метод isVisible почему-то возвращает false, хотя я вызвал в коде вставки страницы button->setVisible( true ) и group->setVisible( true )

Почему isVisible возвращает false? О_о

Автор: 0xF 20.3.2008, 21:09

Думал, может у меня в коде какая-нить ошибка, написал:

QPushButton *button = new QPushButton( "Caption", this );

button->setVisible( true );
bool v = button->isVisible(); // ** Вот тут v = false

WTF?!! :wacko: Чо за фигня? :blink:

Автор: Litkevich Yuriy 20.3.2008, 21:25

а кнопку видно?

Автор: 0xF 20.3.2008, 21:25

Так, решил проблему переопределением QWidget::showEvent: вставил туда ф-цию QFoldout::Layout

Автор: 0xF 20.3.2008, 21:26

Цитата
а кнопку видно?

Нет, она не появлялась... т.е. просто пустой виджет без кнопок и групп

Автор: Litkevich Yuriy 20.3.2008, 21:29

обычно даже и не надо делать setVisible, уже видно должно быть, он случаем задом неперет не работает? :)

Автор: 0xF 20.3.2008, 22:00

А хз. Не думаю :) Почитал щас доки, написано, что если кто-то из предков контрола не виден, то setVisible никакого эффекта не имеет... может по этому

Автор: Litkevich Yuriy 20.3.2008, 22:58

запросто, т.к. родитель - контейнер.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)