LINUX.ORG.RU
 
Gorthauer

Qt TreeView, кастомный делегат и sizeHint


0

1

Собственно делаю кастомный делегат, где имеется текст и описание, описание должно уметь переносы строк. Так вот с деревьями возникает проблема, что они кешируют sizeHint от делегата и соответственно не запрашивают у него по новой sizeHint в случае ресайза. В итоге это приводит к веселым багам. Как проще всего заставить view перегенерить sizeHint'ы для элементов в случае ресайза? По поводу тормозов можно не волноваться: элементом не будет больше 20


[#]  

>Как проще всего заставить view перегенерить sizeHint'ы для элементов в случае ресайза?

Вызывать QTreeView::doItemsLayout() в resizeEvent этого view.

* ()
[#] Ответ на: комментарий от summatus 03.12.2010 19:25:44  
Gorthauer

Шаманить с friend классами? вроде же doItemsLayout is private

*** ()
[#] Ответ на: комментарий от Gorthauer 04.12.2010 2:21:51  
UVV

Зачем, можно ведь просто отнаследоваться.

***** ()
[#] Ответ на: комментарий от Gorthauer 04.12.2010 2:21:51  

Она public virtual. На то что её нет в доках не обращай внимание.

* ()
[#] Ответ на: комментарий от summatus 04.12.2010 9:36:48  

Хотя лучше, вместо doItemsLayout, делай так:

    QEvent e( QEvent::StyleChange );
    qApp->sendEvent( this, &e );

где this - твой view, это тоже самое, в принципе, но более корректно.

* ()
[#] Ответ на: комментарий от summatus 04.12.2010 9:46:14  
Gorthauer

Круто конечно, но хочется как-то из делегата это научиться делать, чтобы не править каждый view под него.

*** ()
[#] Ответ на: комментарий от Gorthauer 04.12.2010 12:14:49  
Gorthauer

Передавать указатель на view тоже не слишком канает ибо у меня делегат один на все view'ы.

*** ()
[#] Ответ на: комментарий от Gorthauer 04.12.2010 12:19:11  

>делегат один на все view'ы.

Какая разница? Ставишь этот делегат, как фильтр событий всех этих view. Создаёшь фильтр:

class Delegate : public QStyledItemDelegate {
protected:
    bool eventFilter( QObject* obj, QEvent* e ) {
        if ( e->type() == QEvent::Resize ) {
            QEvent e( QEvent::StyleChange );
            qApp->sendEvent( obj, &e );
        }

        return QObject::eventFilter( obj, e );
    }
...

Любому объекту, он, в ответ на resize, прикажет обновить стиль. Можно добавить проверку по objectName: тот ли это view, который нужно перерисовать.

И, кстати, ты спрашивал простой вариант. В серьёзный проект такое засовывать не надо, там надо создавать свой BNWTreeView : public QAbstractItemView.

* ()
[#] Ответ на: комментарий от summatus 04.12.2010 13:00:16  
Gorthauer

Ну вот не знаю, можно ли qutIM считать серьезным проектом? К тому же делегата я присобачиваю в том числе и к QComboBox'у, а как у него view поменять не представляю.

*** ()
[#] Ответ на: комментарий от Gorthauer 04.12.2010 13:02:13  

Но, у QComboBox же вид сам перерисовывается при открытии/закрытии, а делегат не влияет на выбранный элемент. Но вообще его можно обновлять например так:

    bool eventFilter( QObject* obj, QEvent* e ) {
        if ( e->type() == QEvent::Resize ) {
            if ( qobject_cast< QTreeView* >( obj ) ) {
                QEvent e( QEvent::StyleChange );
                qApp->sendEvent( obj, &e );
            }
            else if ( QComboBox* cb = qobject_cast< QComboBox* >( obj ) ) {
                QEvent e( QEvent::StyleChange );
                cb->setUpdatesEnabled( false );
                qApp->sendEvent( cb->view(), &e );
                cb->setUpdatesEnabled( true );
            }
        }

        return QObject::eventFilter( obj, e );
    }
* ()
[#] Ответ на: комментарий от summatus 04.12.2010 13:44:01  
Gorthauer

Да вроде бы на него тоже влияет QEvent e( QEvent::StyleChange );

*** ()