Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: [РЕШЕНО] QTableView::resizeColumnsToContents, неожидаемое поведение
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt GUI
Litkevich Yuriy
Сталкнулся с неожидаемым поведением функции QTableView::resizeColumnsToContents(). Ширина столбца подгоняется под ширину содержимого заголовка, в случае если первая строка данног столбца пустая:
Нажмите для просмотра прикрепленного файла
Если в первой строке данного столбца что-то есть, то подгоняется под него:
Нажмите для просмотра прикрепленного файла

Я ожидал, что будет подгонятся под самое большое содержимое в столбце. Кто-нибудь может прокоментировать и/или подсказать как добится ожидаемого поведения?
AD
Мне кажется, придется самому переопределить эту функцию: сортировать значения столбца.
kwisp
прям как то не верится.
у тебя вроде бы на втором рисунке подогнан размер под содержимое столбца(первый столбец), но там одинаковые числа. не мог бы ты заполнить столбец разными числами по длинне чтобы данную странность четче увидеть. к примеру самое длинное число не в первой строке...
Litkevich Yuriy
Цитата(kwisp @ 16.1.2009, 17:56) *
не мог бы ты заполнить столбец разными числами по длинне чтобы данную странность четче увидеть. к примеру самое длинное число не в первой строке...
попробую, это просто в базе все.
kwisp
Цитата(kwisp @ 16.1.2009, 14:56) *
прям как то не верится.
у тебя вроде бы на втором рисунке подогнан размер под содержимое столбца(первый столбец), но там одинаковые числа. не мог бы ты заполнить столбец разными числами по длинне чтобы данную странность четче увидеть. к примеру самое длинное число не в первой строке...


о! сообразил. для этого у нас первый рисунок.. точечки после цифр это походу свидетельство о сокращении.
Litkevich Yuriy
пожалуй такое замечание, в примере где в ячейке пусто - в БД NULL
kwisp
void QTableView::resizeColumnsToContents () [slot]

Resizes all columns based on the size hints of the delegate used to render each item in the columns.

меня смущает этот size hints.


int QTableView::sizeHintForColumn ( int column ) const [virtual protected]

Returns the size hint for the given column's width or -1 if there is no model.

If you need to set the width of a given column to a fixed value, call QHeaderView::resizeSection() on the table's horizontal header.

If you reimplement this function in a subclass, note that the value you return will be used when resizeColumnToContents() or QHeaderView::resizeSections() is called. If a larger column width is required by either the horizontal header or the item delegate, the larger width will be used instead.
Litkevich Yuriy
Цитата(kwisp @ 16.1.2009, 18:10) *
меня смущает этот size hints.
дальше то написано
Цитата(kwisp @ 16.1.2009, 18:10) *
each item in the columns
т.е. для каждого элемента в колонке. Вот и не понятно
kwisp
Цитата(Litkevich Yuriy @ 16.1.2009, 15:17) *
Цитата(kwisp @ 16.1.2009, 18:10) *
меня смущает этот size hints.
дальше то написано
Цитата(kwisp @ 16.1.2009, 18:10) *
each item in the columns
т.е. для каждого элемента в колонке. Вот и не понятно


я так понимаю hint это рекомендованный размер. так надо найти где его рекомендовать для итемов по содержимому.

еще совершенно глупое предположение. у тебя совершенно случайно не ограничен размер нигде может просто не помещается содержимое????

To distribute the available space according to the space requirement of each column or row, call the view's resizeColumnsToContents() or resizeRowsToContents() functions.

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

а setStretchLastSection(bool) работает у тебя?
Litkevich Yuriy
Цитата(kwisp @ 16.1.2009, 18:41) *
To distribute the available space according to the space requirement of each column or row,
Буквально: "Чтобы распространять доступное пространство в соответствии с пространством требующимся каждой колонке или строке"

Цитата(kwisp @ 16.1.2009, 18:41) *
у тебя совершенно случайно не ограничен размер нигде может просто не помещается содержимое????
спциально - нет. Вот все что я делаю с представлением:
ui_hourlyreport.h
view = new QTableView(HourlyReport);
view->setObjectName(QString::fromUtf8("view"));

hourlyreport.cpp
view->resizeColumnsToContents();


Цитата(kwisp @ 16.1.2009, 18:41) *
а setStretchLastSection(bool) работает у тебя?
я его неиспользую т.к. кол-во столбцов велико и они не влазят в окно, а это свой ство нужно для обратного случая, чтобы последний столбец заполнял все доступное пространство в представлении
kwisp
извини за то что повторяюсь. считаю, что в данном контексте слово "требующимся" не означает что "по размеру содержимого".
может и ошибаюсь но предположений больше нет.
думаю стоит ковырять в сторону рекомендуемых размеров для элементов столбцов и строк.
ну конечно есть как всегда вариант через одно место с помощью QFontMetrics узнать размер строки и с помощью него менять ширину, но его я не предлагаю.:)

сейчас накатаю примерчик и посомотрю наглядно.
kwisp
Цитата(kwisp @ 16.1.2009, 16:03) *
сейчас накатаю примерчик и посомотрю наглядно.


у меня так получилось если сделать
table.resizeColumnsToContents();
до заполнения то косячит

если после заполнения то все ок.
норма
#include <QApplication>
#include <QTableWidget>
#include <QTableWidgetItem>

int main(int a,char** b)
{
    QApplication app(a,b);
    QTableWidget table(100,100,0);
    int i=2;
    for(int i=0;i<100;++i){
        for(int y=0;y<100;++y){
            table.setItem(i,y,new QTableWidgetItem(QString::number(i*i)));
        }
    }
    table.resizeColumnsToContents();    
    table.show();
    return app.exec();
}


обрезается
#include <QApplication>
#include <QTableWidget>
#include <QTableWidgetItem>

int main(int a,char** b)
{
    QApplication app(a,b);
    QTableWidget table(100,100,0);
    int i=2;
    table.resizeColumnsToContents();
            for(int i=0;i<100;++i){
        for(int y=0;y<100;++y){
            table.setItem(i,y,new QTableWidgetItem(QString::number(i*i)));
        }
    }
        
    table.show();
    return app.exec();
}



с таблицами не работал раньше.
оно то и понятно потому что table.resizeColumnsToContents(); это установка сделать операцию используя имеющиеся данные о размерах строк. а не установка свойства.
Litkevich Yuriy
У меня тоже после заполнения:
HourlyReport::HourlyReport(QWidget* p_parent) : QDialog(p_parent)
{
...
    reportmodel = new QSqlQueryModel;
    view->setModel(reportmodel);
...
}

// Слот обновления
void HourlyReport::slotUpdate()
{
...
    // получим из БД отчет
    qstr = QString("SELECT * FROM P_HORLYPWR_OFMONTH(%1, CAST ('%2' AS DATE))")
            .arg(strpoint).arg(strdate);
    reportmodel->setQuery(qstr, db);
    
    //view->resizeColumnsToContents();
    setHeader(); //Устанавливаем текст заголовков
    view->resizeColumnsToContents();
...
}
если перенести ресайз до установки заголовков, то они тоже плющатся
kwisp
Цитата(Litkevich Yuriy @ 16.1.2009, 17:55) *
У меня тоже после заполнения:
....
если перенести ресайз до установки заголовков, то они тоже плющатся



ну а если перенести ресайз поставив его после заполнения таблицы и заполнения заголовков???
собери мои примеры если есть время посмотри.
Litkevich Yuriy
Цитата(kwisp @ 16.1.2009, 20:59) *
ну а если перенести ресайз поставив его после заполнения таблицы???
дак так и есть заполняется модель в строке reportmodel->setQuery(qstr, db); а в таблице отображается за счет связи модели с таблицей (т.е. "само")
kwisp
Цитата(Litkevich Yuriy @ 16.1.2009, 18:08) *
Цитата(kwisp @ 16.1.2009, 20:59) *
ну а если перенести ресайз поставив его после заполнения таблицы???
дак так и есть заполняется модель в строке reportmodel->setQuery(qstr, db); а в таблице отображается за счет связи модели с таблицей (т.е. "само")


жесть. что могу сказать. время стучать в бубен и бегать вокруг костра.
мое предложение - это же слот resizeColumnsToContents(), соедини его с каким нить сигналом. пусть для проверки даже с кликом на кнопке или еще каким чтобы вызвать его гарантированно после того как все в таблице заполнено....извини если несу чушь по кусочку кода сложно понять как что у тебя организовано.
SABROG
Где-то я такое уже видел. Попробуй такие варианты:

setUpdatesEnabled(false)
...
view->resizeColumnsToContents();
...
setUpdatesEnabled(true)


view->resizeColumnsToContents();
view->update();


emit view->resizeColumnsToContents();
kwisp
Цитата(SABROG @ 16.1.2009, 22:17) *
emit view->resizeColumnsToContents();


можно по-подробнее что это такое за конструкция это что вызов слота???
Litkevich Yuriy
Цитата(kwisp @ 16.1.2009, 21:13) *
мое предложение - это же слот resizeColumnsToContents(), соедини его с каким нить сигналом. пусть для проверки даже с кликом на кнопке или еще каким чтобы вызвать его гарантированно после того как все в таблице заполнено
да так помогло:

получается, что заполнение представления из модели происходит несколько асинхронно.
Хотя это для меня небыло очевидно, т.к. когда данные из БД выбирались другой ХП, существенно мение оптимальной, время на выборку занимало несколько мин. При этом всеравно текст в ячейках обрезался.

Но тут видимо ключевой момент асинхронное заполнение представления из модели. Представление еще незаполнено, а метод resizeColumnsToContents уже вызван.
Litkevich Yuriy
кое чего накопал, чтобы избавится от многоточия, можно сделать так:
view->setTextElideMode(Qt::ElideNone);

но resizeColumnsToContents() ведет себя по прежнему.
kwisp
Цитата(Litkevich Yuriy @ 17.1.2009, 6:02) *
да так помогло:


:)
Litkevich Yuriy
вот только для конечного пользователя это не вариант. Пока отложил, через некоторое время еще буду думать.

вот в трэкере списочек, но я пока не понял, то что уменя это исправлено или нет.
kwisp
засада.
я так понял что у тебя в другом потоке заполняется таблица.
Цитата
Представление еще незаполнено, а метод resizeColumnsToContents уже вызван.


может следить за заполнением и по окончании последнего сигнал на который повесить уже этот resizeColumnsToContents() ???
особой надежды на трекер не оставляй многие задачи там могут висеть очень долго.
Litkevich Yuriy
Цитата(kwisp @ 17.1.2009, 14:15) *
я так понял что у тебя в другом потоке заполняется таблица.
это все без моего участия, см. сообщение №13 reportmodel->setQuery(qstr, db); устанавливается запрос и далее модель сама его исполняет, получает из БД результат, ну а представление его отображает. Насчет асинхронности это лишь догадка. Но похоже асинхронности всетаки нет, т.к. если запрос тяжелый то GUI виснит.

Цитата(kwisp @ 17.1.2009, 14:15) *
может следить за заполнением и по окончании последнего сигнал на который повесить уже этот resizeColumnsToContents() ???
я не нашел способа узнать когда отображение завершится. Была дикая мысль использовать событие перерисовки. Но это крайность.
kwisp
в какой последовательности заполняется таблица???
если заполнение и отрисовка связаны жестко, то можно использовать

void QTableWidget::cellChanged ( int row, int column ) [signal] для последней ячейки это будет один из крайних моментов заполнения а следовательно после него можнол делать resizeColumnsToContents()

думаю стоит попробовать.
Litkevich Yuriy
Цитата(kwisp @ 17.1.2009, 16:10) *
в какой последовательности заполняется таблица???
не понял вопроса?

Цитата(kwisp @ 17.1.2009, 16:10) *
QTableWidget
я непользуюсь виджетом, у меня представление и модель
kwisp
Цитата(Litkevich Yuriy @ 17.1.2009, 13:20) *
Цитата(kwisp @ 17.1.2009, 16:10) *
в какой последовательности заполняется таблица???
не понял вопроса?


ну ты знаешь какая ячейка заполниться последней??? сигнал void QTableWidget::cellChanged ( int row, int column ) [signal] передает номер строки и столбца в которой меняются значения.
если повесить слот resizeColumnsToContents() на сигнал о заполнении этой ячейки???

можно быстренько проверить сработает или нет просто соединив этот сигнал со слотом resizeColumnsToContents() нагрузит конечно процессор но зато узнаем....
Litkevich Yuriy
Цитата(kwisp @ 17.1.2009, 16:23) *
ну ты знаешь какая ячейка заполниться последней???
нет, я незнаю зарание сколько строк вернет БД
kwisp
Цитата(Litkevich Yuriy @ 17.1.2009, 13:33) *
Цитата(kwisp @ 17.1.2009, 16:23) *
ну ты знаешь какая ячейка заполниться последней???
нет, я незнаю зарание сколько строк вернет БД


а кол-во столбцов знаешь?
а ячейка вообще какая нибудь может остаться не тронутой, т.е не заполняться???
заполнение даже пустой строкой считается что ячейка заполнена

если заполняются все ячейки гарантированно и ты знаешь колличество столбцов то можно вызывать resizeColumnsToContents() только когда редактируются ячейки последнего столбца по сигналу
QTableWidget::cellChanged ( int row, int column )

а так больше идей как то не находится....
Litkevich Yuriy
Цитата(kwisp @ 17.1.2009, 16:40) *
ячейки последнего столбца по сигналу
QTableWidget::cellChanged ( int row, int column )


Цитата(Litkevich Yuriy @ 17.1.2009, 16:21) *
Цитата(kwisp @ 17.1.2009, 16:10) *
QTableWidget
я непользуюсь виджетом, у меня представление и модель
kwisp
Цитата(Litkevich Yuriy @ 17.1.2009, 13:50) *
Цитата(kwisp @ 17.1.2009, 16:40) *
ячейки последнего столбца по сигналу
QTableWidget::cellChanged ( int row, int column )

Цитата(Litkevich Yuriy @ 17.1.2009, 16:21) *
Цитата(kwisp @ 17.1.2009, 16:10) *
QTableWidget
я непользуюсь виджетом, у меня представление и модель



ясно, тогда удачи. ;)
Litkevich Yuriy
Ответ на вопрос найден:
Все работает, но размер подгоняется только для видимой части виджета!

Уменя на первом снике в видимой части (а она была в самом верху, когда вызывался метод QTableView::resizeColumnsToContents()) небыло ни каких данных.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.