вторник, 3 июня 2014 г.

Комплексные виджеты в Qt

В довольно древней книге-туториалу по VB.NET описывалось то, как можно создать свой комплексный виджет, состоящий из нескольких подвиджетов на основе встроенного в систему UserControl.

В туториалах по Qt есть свой туториал по созданию своих сложных виджетов на основе QWidget. Но он довольно сложный, так как рассчитан на интеграцию в Qt Designer. В итоге разработка своего виджета может показаться сложным и неблагодарным занятием. 

Но есть более простой путь. Он заключается в наследовании класса QWidget и переопределении методов void resizeEvent( QResizeEvent * e ), а также void moveEvent( QMoveEvent * e );

При этом достаточно объявить новые виджеты, как поля в новом классе и назначить им родительским виджетом, виджет родительский для данного. В итоге - виджеты будут отображаться и  даже реагировать на действия пользователя.

Мини-пример такого виджета на C++ показан ниже.


#include <QWidget>
#include <QTreeWidget>
#include <QTableWidget>


class MyWidget: public QWidget
{
    Q_OBJECT
public: 
        MyWidget(QWidget * parent = NULL);        
        ~MyWidget();
protected:
        virtual void resizeEvent(QResizeEvent * e);
        virtual void moveEvent(QMoveEvent * e);
        void resizeWidgets(const QRect & r);

        QTreeWidget  * m_tree_view;
        QTableWidget * m_element_view;
};

MyWidget::MyWidget(QWidget * parent) 
: QWidget(parent)
{
        m_tree_view = new QTreeWidget(parent);
        m_element_view = new QTableWidget(parent);

        resizeWidgets(this->geometry());
}

MyWidget::~MyWidget()
{
        delete m_tree_view;
        delete m_element_view;
}

void MyWidget::resizeEvent( QResizeEvent * e )
{
        QRect oldrect = this->geometry();
        QRect r(oldrect.x(), oldrect.y(), e->size().width(), e->size().height());
        resizeWidgets(r);
}

void MyWidget::moveEvent( QMoveEvent * e )
{
        QRect oldrect = this->geometry();       
        QRect r(e->pos().x(), e->pos().y(), oldrect.width(), oldrect.height());
        resizeWidgets(r);       
}

void MyWidget::resizeWidgets(const QRect & r)
{
        double halfsizenopad = r.width() / 2.0;
        m_tree_view->setGeometry(r.x(), r.y(), halfsizenopad, r.height());
        double element_view_x = r.x() + r.width() / 2.0;
        m_element_view->setGeometry(element_view_x, r.y(), 
                                    halfsizenopad , r.height());
}

Код более серьезного виджета на С++, использующего этот же подход можно посмотреть по ссылкам: [1] [2].

UPD: Можно обойтись и без реализации resizeEvent и moveEvent, если использовать один из наследников QLayout, а виджеты добавлять в него. Спасибо degeron!

Комментариев нет:

Отправить комментарий