Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Bepec от Апрель 19, 2012, 10:42



Название: SizeHint или размер столбца.[Решено]
Отправлено: Bepec от Апрель 19, 2012, 10:42
Приветствую всех ;)


Проблема: После переопределения делегата(наследован от QItemDelegate), выявились 2 проблемы:

1) При вызове tableView->resizeToColumns(), возвращается двойной размер отрисованной области. Причём в paintEvent с самого начала отрисовки приходит двойной размер :/
Переопределение sizeHint'a не помогает.(Кстати
Код:
вопрос
, за что тогда отвечает sizeHint? - он отвечает за общий размер item'а. Далее пример из QItemDelegate)

Решение: Не переопределённый sizeHint использует размер строки, возвращаемой из модели с ролью Qt::DisplayRole.
Для корректного расчёта размеров, нужно в sizeHint возвращать свой размер(вычисляемый)
В качестве примера выдержка из QItemDelegate

Код:
QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
                              const QModelIndex &index) const
{
    QVariant value = index.data(Qt::SizeHintRole);
    if (value.isValid())
        return qvariant_cast<QSize>(value);
    QRect decorationRect = rect(option, index, Qt::DecorationRole);
    QRect displayRect = rect(option, index, Qt::DisplayRole);
    QRect checkRect = rect(option, index, Qt::CheckStateRole);

    doLayout(option, &checkRect, &decorationRect, &displayRect, true);

    return (decorationRect|displayRect|checkRect).size();
}

2) Текст рисуется не по центру ячейки, а прямо-таки почти впритык к верхней границе.

Решение: в нижеприведённом коде, boundingRect возвращает строку, у которой высота равна высоте шрифта.
Как лечить - увеличивать Rect до высоты ячейки
Код:
        tmpRect.setHeight(outRect.height());

Код:
void LogDelegate::paint(QPainter *painter,
           const QStyleOptionViewItem &option,
           const QModelIndex &index) const
{
    
    painter->setClipRegion(option.rect);
    QString dataStr(index.model()->data(index).toString());
    QString tmpStr;
    int pos;
    QFont font;
    QRect tmpRect;
    QRect outRect(option.rect.topLeft(), option.rect.bottomLeft());
    for(;ttt.contains("##");)
    {
        pos = dataStr.indexOf("##");
        dataStr.remove(0, pos+2);
        tmpStr = dataStr.mid(1, (ttt.indexOf("##")-1));
        
        if (dataStr.at(0) == 'I')
        {
            if (type == 1)
                continue;
            painter->setPen(Qt::red);
        }

        if (dataStr.at(0) == 'R')
        {
            if (type == 0)
                continue;    
            if (type != 1)
                font.setStrikeOut(true);
            painter->setPen(Qt::blue);
        }
        painter->setFont(font);
        tmpRect = painter->boundingRect(outRect, Qt::AlignVCenter, tmpStr);
        painter->drawText(tmpRect, Qt::AlignVCenter, tmpStr);
        outRect = tmpRect;
        painter->drawLine(tmpRect.topLeft(),tmpRect.bottomRight());
      
        //промежуток между частями - чистый
        font.setStrikeOut(false);
        painter->setPen(Qt::black);


        tmpRect = painter->boundingRect(option.rect, option.displayAlignment, "  ");
        tmpRect.moveTo(outRect.topRight());
        outRect = tmpRect;
        painter->drawLine(tmpRect.topLeft(),tmpRect.bottomRight());

    }
}


Название: Re: SizeHint или размер столбца.
Отправлено: GreatSnake от Апрель 19, 2012, 11:55
1) При вызове tableView->resizeToColumns(), возвращается двойной размер отрисованной области. Причём в paintEvent с самого начала отрисовки приходит двойной размер :/
Что такое "двойной размер" и почему он возвращается после неизвестной нам resizeToColumns()?

Цитировать
Кстати вопрос, за что тогда отвечает sizeHint?)

Цитата: assistant
Returns the size needed by the delegate to display the item specified by index, taking into account the style information provided by option.

When reimplementing this function, note that in case of text items, QItemDelegate adds a margin (i.e. 2 * QStyle::PM_FocusFrameHMargin) to the length of the text.

Кстати, если хочешь, чтобы работали стили, забудь про QItemDelegate и используй QStyledItemDelegate.


Название: Re: SizeHint или размер столбца.
Отправлено: Bepec от Апрель 19, 2012, 12:11
Угу. Спасибо. Я эту информацию уже читал. Вот только она как бы не соответствует действительности, или я что-то не так делаю.

Двойной размер это - размер отрисованной области, умноженный на 2.

начало области - _B
конец области - _E
начало ячейки - BC
конец ячейки - EC

Получается что-то типа :
       /*                                  */ = область размером с отрисованный текст.

BC_B/*тут отрисовываем текст */_E/*                                  *//*                                  */EC


resizeToColumns() это функция QTableView, которая изменяет размер столбцов в соответствии с sizeHint делегата. НО при возврате в sizeHint делегата значений {(0,0), (100,100), (1000,1000)} ничего не меняется. Увы.


Название: Re: SizeHint или размер столбца.
Отправлено: GreatSnake от Апрель 19, 2012, 12:17
resizeToColumns() это функция QTableView, которая изменяет размер столбцов в соответствии с sizeHint делегата. НО при возврате в sizeHint делегата значений {(0,0), (100,100), (1000,1000)} ничего не меняется. Увы.
Что-то я не вижу такой функции. Есть resizeColumnsToContents().
Показывай твой sizeHint().


Название: Re: SizeHint или размер столбца.
Отправлено: Bepec от Апрель 19, 2012, 12:25
случай 1: - он у меня не переопределён. эффект присутствует.
случай 2:
Код:
QSize LogDelegate::sizeHint(const QStyleOptionViewItem &option,
               const QModelIndex &index ) const
{
    return QSize(option.rect.width(), option.rect.height());
}

случай 3,4,5: меняется только возвращаемый размер на 0,0; 100,100; 1000,1000;
Код:
QSize LogDelegate::sizeHint(const QStyleOptionViewItem &option,
               const QModelIndex &index ) const
{
    return QSize(1000,1000);
}


И проблема в чём так-то как указать делегату этот самый блин размер ячейки?
update: не "общий размер ячейки на текущий момент", а "размер ячейки, необходимый для корректного отображения содержимого на экране".


Название: Re: SizeHint или размер столбца.
Отправлено: GreatSnake от Апрель 19, 2012, 12:38
Ещё раз про sizeHint():
Цитировать
Returns the size needed by the delegate to display the item specified by index, taking into account the style information provided by option.

Похоже у тебя с английским что-то совсем никак ибо перевод всё объясняет:
Цитировать
Возвращает размер необходимый делегату для отображения элемента указанного индекса с учетом стиля.
Т.е. твой sizeHint() должен вернуть размер текста, который ты пытаешься отрисовать в paint() но без учёта границ option.rect.
Т.е. если требуется отобразить строку "Abc", то должно возвращаться QFontMetrics( option.font ).boundingRect( "Abc" ).size();


Название: Re: SizeHint или размер столбца.
Отправлено: Bepec от Апрель 19, 2012, 12:44
Кхм. Как бы я это читал, а что он объясняет?

По идее этот размер должен использоваться для определения, весь текст отображён на экране, или нет. А так же для определения ширины колонки.

Цитировать
void QTableView::resizeColumnsToContents () [slot]
Resizes all columns based on the size hints of the delegate used to render each item in the columns.

Так же интересно, что если он не переопределён(sizeHint), а даже если и переопределён, то разницы совершенно никакой.

update на твой update:
Я как бы верю, что размер в QSize(1000, 1000), должен как бы быть достаточным, для отображения 20 символов. И уж точно он должен как- то реагировать хоть на малый размер, хоть на большой.
Но разницы то нет Оо...


Название: Re: SizeHint или размер столбца.
Отправлено: GreatSnake от Апрель 19, 2012, 12:51
Так же интересно, что если он не переопределён(sizeHint), а даже если и переопределён, то разницы совершенно никакой.
Похоже всё дело в том, что строку, которую ты установил для Qt::DisplayRole ты не отображаешь, а используешь как установленную для Qt::UserRole. А дефолтный sizeHint() пытается определить размер для "левой" строки.

Кстати, а ты уверен, что твой sizeHint() вызывается?


Название: Re: SizeHint или размер столбца.
Отправлено: Bepec от Апрель 19, 2012, 12:57
Я её вообще не отображаю ;) Там лежат сырые данные, которые обрабатываются в делегате и приводятся в юзерочитабельский вид и отрисовываются.

Хм. Проблема исчезла, после нескольких правок(а перед ними были десятки безуспешных) и пересборки проекта... В недоумении.

PS самое удивительное, что уверен. Дебагер там ловит спокойно заход.


Название: Re: SizeHint или размер столбца.
Отправлено: GreatSnake от Апрель 19, 2012, 12:58
Я её вообще не отображаю ;) Там лежат сырые данные, которые обрабатываются в делегате и приводятся в юзерочитабельский вид и отрисовываются.
Ты-то не отображаешь, а вот дефолтный sizeHint() использует её для подсчёта размера.


Название: Re: SizeHint или размер столбца.
Отправлено: Bepec от Апрель 19, 2012, 13:08
Оппаньки. Благодарю за эту замечательную, гениальнейшую мысль. Озарило меня теперь ;)

Тема логически пришла к завершению.  Благодарю за помощь.