Russian Qt Forum

Qt => Вопросы новичков => Тема начата: koldun90 от Февраль 18, 2015, 20:07



Название: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 18, 2015, 20:07
Здравствуйте есть qfilesystemmodel представленный в Qlistview
проблема в следующем мне нужно как бы выровнять папки
(http://s018.radikal.ru/i514/1502/e3/3945e1546212.png) (http://www.radikal.ru)
мой виджет скомпонован по сетке те он может расширяться...

но мне нужно чтобы как бы все папки были по сетке чтоли... Те каждая под каждой....
как примерно тут
(http://s40.radikal.ru/i087/1502/4a/488f3acb57ad.png) (http://www.radikal.ru)


вопрос как это сделать?


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 18, 2015, 20:23
попробуй возвращать фиксированную ширину для Qt::SizeHintRole из data() модели. если не поможет, то наверное без кастомного делегата никак.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 18, 2015, 23:15
я делаю так вот
Код:
if (role==Qt::SizeHintRole)
{
   return QSize(60,60);
}
(http://s017.radikal.ru/i405/1502/23/217c10629b24.png) (http://www.radikal.ru)
получается такая картина все вроде бы устраивает...
НО как бы мне еще нужно чтобы имена файлов и папок(если они длинные) переносились на другую сторону(на вторую сторону чтоб они прям полностью отображались...
как в примере приведенном в начале темы на второй картинке.... там допустим отображается название папки полностью (SYSTEM VOLUME INFORMATION) переносится на след строку если сжимаю.... ну я думаю вы поняли)


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 18, 2015, 23:55
делегат свой писать, по-другому никак. посмотри исходниках как дефолтный делегат отрисовывает айтемы qfilesystemmodel.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 19, 2015, 05:59
дефолтный делегат это это?
Код:
void QItemDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const   [virtual]
вообщем что нужно переопределять?
и у меня нет исходников....
объясните подробнее.....


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 19, 2015, 14:48
ну так скачай их, раз нету.

открой документацию QStyledItemDelegate и почитай, ну и примеры посмотри.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 19, 2015, 15:55
я в английском не очень силен могли бы вы подсказать  в сторону какого метода в классе QStyledItemDelegate нужно "копать"?


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 19, 2015, 17:01
открой русский перевод и почитай раздел наследования от QStyledItemDelegate. как минимум тебе нужно будет писать свою отрисовку в paint().


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 19, 2015, 20:52
открой русский перевод и почитай раздел наследования от QStyledItemDelegate. как минимум тебе нужно будет писать свою отрисовку в paint().
странно русского перевода не нашел этого класса) http://doc.crossplatform.ru/
если вы знаете можно ссылку...


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 19, 2015, 20:56
вот нашел исходник вроде бы
https://qt.gitorious.org/qt/webkit/source/435bbd4be73768f617e4a4083a345d1d8d62daa3:src/gui/itemviews/qstyleditemdelegate.cpp


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 19, 2015, 21:03
Код:
void QStyledItemDelegate::paint(QPainter *painter,
        const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_ASSERT(index.isValid());
 
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);
 
    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}
и что тут отвечает за надпись айтема ( в моем случае имени файла+ или папки)?


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 20, 2015, 00:32
открой русский перевод и почитай раздел наследования от QStyledItemDelegate. как минимум тебе нужно будет писать свою отрисовку в paint().
странно русского перевода не нашел этого класса) http://doc.crossplatform.ru/
если вы знаете можно ссылку...

не повезло :)
Код:
void QStyledItemDelegate::paint(QPainter *painter,
        const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_ASSERT(index.isValid());
 
    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);
 
    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);
}
и что тут отвечает за надпись айтема ( в моем случае имени файла+ или папки)?
значит надо копать глубже, в QStyle::drawControl


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 20, 2015, 18:48
извините а определение метода
Код:
QStyle::drawControl
вообще не нашел
вот прилагаю сурс qstyle.cpp
что делать дальше?


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 20, 2015, 20:17
это чистый виртуальный метод, реализацию надо искать в подклассах.

уже б давно написал свою отрисовку — там намалевать-то иконку (стандартную судя по всему) и многострочный текст.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 20, 2015, 21:29
где писать ....
мы даже не нашли какой метод переопределять надо...


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 20, 2015, 22:38
наследуешься от QStyledItemDelegate, переопределяешь paint(), текст рисуется примерно так:
Код
C++ (Qt)
painter->drawText(option.rect, Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter, index.data().toString());

ну и делегат не забудь установить в свою вьюшку.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 21, 2015, 08:45

вообщем создал класс с++ наследник от QStyledItemDelegate

mydelegate.h
Код:
#ifndef MYDELEGATE_H
#define MYDELEGATE_H

#include <QStyledItemDelegate>
#include <QPainter>


class mydelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit mydelegate(QObject *parent = 0);

signals:

public slots:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

};

#endif // MYDELEGATE_H


mydelegate.cpp
Код:
#include "mydelegate.h"

mydelegate::mydelegate(QObject *parent) :
    QStyledItemDelegate(parent)
{
}

void mydelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_ASSERT(index.isValid());
    painter->drawText(option.rect,Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());

    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);


    //QStyledItemDelegate::paint(painter,option,index);
}


и начал переопределять как вы сказали paint
Код:
void mydelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_ASSERT(index.isValid());
    painter->drawText(option.rect,Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());

    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);

    const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
    QStyle *style = widget ? widget->style() : QApplication::style();
    style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, widget);


    //QStyledItemDelegate::paint(painter,option,index);
}


соответственно две ошибки
/manager20feb/manag20feb/manag/mydelegate.cpp:15: ПЫЙВЛБ: incomplete type 'QStyledItemDelegatePrivate' used in nested name specifier


/manager20feb/manag20feb/manag/mydelegate.cpp:16: ПЫЙВЛБ: incomplete type 'QApplication' used in nested name specifier

в двух строоках
Код:
const QWidget *widget = QStyledItemDelegatePrivate::widget(option);
QStyle *style = widget ? widget->style() : QApplication::style();
что может быть ?

я разобрался вообщем мне не понятно откуда это
Код:
QStyledItemDelegatePrivate::widget(option);
QStyledItemDelegatePrivate--- вообще это что и как его подцепить?


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 21, 2015, 11:14
а если я пишу вот так вот
Код:
void mydelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    
    painter->drawText(option.rect,Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());
    QStyledItemDelegate::paint(painter,option,index);
}

то получается такая картина
(http://s020.radikal.ru/i702/1502/11/a25f8b2ab400.png) (http://www.radikal.ru)


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 21, 2015, 16:17
QStyledItemDelegatePrivate — вроде по названию должно быть понятно, что это недоступный извне исходников класс.

QStyledItemDelegate::paint(painter,option,index); вызывать не нужно — это выполняет дефолтную отрисовку.

тебе еще надо определить размер в QStyledItemDelegate::​sizeHint() по идее.

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


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 21, 2015, 17:20
Код:
void mydelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
   
    painter->drawText(option.rect,Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());

}
вообщем если делаю вот так сами папки не отрисовываются .Отрисовывается только названия папок и файлов.
Я так понял должен быть метод который отрисовывает папки...

Код:
QStyledItemDelegate::​sizeHint(option,index)
возвращает QSize...
я должен передать я так понял в метод который рисует саму папку?
ща попробую перевести доку...


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 21, 2015, 17:58
я делаю так

Код:
void mydelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{


      
    painter->save();  // в доке написано что нужно вызывать до рисовки
        QStyleOptionViewItemV4 opt = option;
        initStyleOption(&opt, index);

        painter->drawText(option.rect,Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());
        QStyledItemDelegate::sizeHint(option,index);
        painter->restore();  // после завершения рисовки


}
в доке про паинт написано использовать до начало рисования
Код:
painter->save(); 
а после рисовки   
Код:
painter->restore();
также как я понял нужно использовать  
Код:
initStyleOption(&opt, index);
вопрос а чем же рисовать саму папку?


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 21, 2015, 18:25
вроде вот разобрался
Код:
void mydelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QPixmap icon(":/Icon/icon/kde_folder24.png");
    painter->save();

    QStyleOptionViewItemV4 opt = option;
    initStyleOption(&opt, index);
    painter->drawPixmap(option.rect,icon);
    painter->drawText(option.rect,Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());
    QStyledItemDelegate::sizeHint(option,index);
    painter->restore();
}


но получается такая картина
(http://s04.radikal.ru/i177/1502/a5/22f746730562.png) (http://www.radikal.ru)
это немного не то....
     


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 21, 2015, 22:12
ну так вместо option.rect подставляй нужный прямоугольник для иконки и текста, координаты вычислить несложно.

иконка по идее должна быть где-то в самом Qt и отрисовываться стандартным образом, необязательно тащить для этого кастомную.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 21, 2015, 22:34
вот таки вопрос как вычислить координаты??

я знаю что иконка моя 24 на 24....


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 21, 2015, 23:57
ну (0,0) - верхний левый угол. если твоя иконка сидит в этом углу, значит ее rect (0, 0, 24, 24).

текст находится под иконкой, значит его у-координата равна icon.y+icon.height (ну или чуть больше, если отступ понадобится), ну а начинается он от левого края (т.е. х == 0). ширина равна всей доступной ширине, а высота вычисляется как общая высота минус text.y.

если иконка по ширине меньше доступной ширины, то думаю отцентрировать ее по горизонтали труда не составит.


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 22, 2015, 07:51
как я понял нужно сделать так
Код:
painter->drawPixmp(QRect(0,0,24,24),icon);
painter->drawText(QRect(0,icon.height(),  ,   ),Qt::TextWordWrap | Qt::AlignHCenter | Qt::AlignVCenter,index.data().toString());

но я не понял как вычислить ширину текста и его высоту....
можно подробнее?

вы пишите
Цитировать
ширина равна всей доступной ширине
---это каким методом нужно воспользоваться чтоб вычислить?
Цитировать
, а высота вычисляется как общая высота минус text.y5
--общую высоту как вычислять??
вообщем как вычислить "общую высоту" и "доступную ширину"...
нет что то вы мне не то сказали по поводу координат x и y....
у меня файловая система подгружает же в листвиев
и если QRect(0,0,24,24) - для иконки то все иконки в одной точке...


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 22, 2015, 08:22
Цитировать
иконка сидит в этом углу
в том то и дело ничего не сидит в углу
смотрите 2 сообщение темы это же файловая система....
и она должна быть распределена (ну ваш кеп)
и того координаты х и y должны будут вычисляться как то динамически....
так в итоге как посчитать координаты то?


Название: Re: центрирование отображения папок в Listview
Отправлено: Igors от Февраль 22, 2015, 09:36
ну (0,0) - верхний левый угол...
Все это хорошо, но кто/как будет собственно центрировать? Когда дело дошло до рисования - rect уже определен. Хорошо, в стиле наверняка есть возможность его пересчитать - но как обеспечить желаемую "ровность"? Напр в 1 иконке оказалось много текста, и нужно чтобы вся строка (и/или весь столбец) равнялись на макс ширину/высоту. Где это задать?

2koldun90 Во-первых, текст "не бесконечен". Попробуйте в Вындоуз увеличивать имя файла - скоро оно все-таки обрежется. Во-вторых, Вы взяли довольно мерзкую задачу :) У меня была схожая проблема - договорился с заказчиком "оставить как есть", жалко тонны времени. Ну и в третьих - не надо все время спрашивать типа "а что мне делать?", "что мне делать?"  :)


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 22, 2015, 11:09
вы советуете не париться по поводу что имена длинных папок и файлов обрываются и типо сказать и так сойдет


Название: Re: центрирование отображения папок в Listview
Отправлено: Igors от Февраль 22, 2015, 14:56
вы советуете не париться по поводу что имена длинных папок и файлов обрываются и типо сказать и так сойдет
Да вполне (аттач). Равнять "и по строке и по столбцу" - ну это проблематично, да и времени жалко разбипаться. Тоже мне, "типо-добросовестный"  :)

Edit: и для полноты картины - второй аттач. Тут все "ровно", но разбазаривается место


Название: Re: центрирование отображения папок в Listview
Отправлено: koldun90 от Февраль 22, 2015, 15:21
можете код скинуть отрисовки вашей очень нужно как вы добились и такого результата...

ps: ладно не буду париться оставлю все как во втором посте темы
ограничюсь

Код:
if (role==QT::sizehintrole)
{
     return QSize(80,60);
}


Название: Re: центрирование отображения папок в Listview
Отправлено: Igors от Февраль 22, 2015, 15:27
можете код скинуть отрисовки вашей очень нужно как вы добились и такого результата...
Аттач


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 22, 2015, 16:00
цитировать лень.

да, перепутал — вместо (0,0) надо брать option.rect.topLeft().

с центрированием проблемы не вижу, например для иконки: QRect(0, 0, 24, 24).moveCenter(option.rect.center().x(), 12)

я думал, что если задать достаточно большой размер айтема (через модель), то option.rect.size() будет у всех одинаковым, что сразу даст выравнивание по сетке, разве нет? (не пробовал)


Название: Re: центрирование отображения папок в Listview
Отправлено: Igors от Февраль 22, 2015, 16:10
я думал, что если задать достаточно большой размер айтема (через модель),
А как через модель?

то option.rect.size() будет у всех одинаковым, что сразу даст выравнивание по сетке, разве нет? (не пробовал)
Да, с вкл grid нет проблем, но размер ячейки фиксирован, придется заряжать его с запасом и лист может выглядеть "пустовато"


Название: Re: центрирование отображения папок в Listview
Отправлено: kambala от Февраль 22, 2015, 16:38
я думал, что если задать достаточно большой размер айтема (через модель),
А как через модель?
отдать Qt::SizeHintRole в data()


Название: Re: центрирование отображения папок в Listview
Отправлено: Igors от Февраль 23, 2015, 11:39
По умолчанию размер айтема вычисляется как сумма/объединение

- QRect иконки
- QRect текста
- QRect еще чего-то

При рисовании эти QRect вычисляются точно так же, только ограничиваются размером айтема, который уже готов. Поэтому изменение размера айтема (через модель или как) может "обрезать" рисование, но не "расширить". Др словами с бОльшим размером айтем займет больше места, но отрисуется так же. Конечно если мы сами будем и рисовать - все норм, но это накладно. Куда проще изменить StyleOption