crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> изменение высоты ячеек QTableView, для которого установлен делегат на основе QTextEdit
Steklova Olga
  опции профиля:
сообщение 2.4.2012, 18:55
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 198
Регистрация: 27.9.2011
Из: Санкт-Петербург
Пользователь №: 2912

Спасибо сказали: 5 раз(а)




Репутация:   4  


Здравствуйте! :) Помогите, пожалуйста, разобраться.
У меня для одной из колонок QTableView установлен делегат на основе QTextEdit.
В процессе увеличения ширины окна с помощью мыши у меня не так, как хотелось бы, меняется отображение многострочного текста в ячейках QTableView. Вот что получается в процессе увеличения ширины окна (см. рис1):

Из всех состояний выглядят так, как я предполагала и хотела, только состояния 1, 3, 4, 8, 10, 12. В этих состояниях текст отображается не сокращенно, а полностью. Как сделать так, чтобы текст всегда отображался полностью - не понимаю. (Безусловно, я учитываю то, что это возможно только в том случае, если места, отведенного для QTableView в окне, хватает для отображения хотя бы одного самого широкого слова из текста всех ячеек таблицы.)

Предполагаю следующее.
Когда из состояния 1 я расширяю окно, то в тот момент, когда текст в какой-то ячейке может уже занять меньшее количество строк, tableView->verticalHeader() пересчитывает высоту строк tableView. Но почему-то при этом текст сначала отображается сокращенно, а позже, при дальнейшем расширении окна, отображается уже полностью.
Потом все это повторятся с какой-нибудь другой ячейкой.


Смотрела тут на форуме темы:
http://www.forum.crossplatform.ru/index.ph...ents+QTableView
("QTableView::resizeColumnsToContents, неожидаемое поведение")
и
http://www.forum.crossplatform.ru/index.ph...leView&st=0
("Изменение высоты и ширины ячеек., QTableView").
Но решения не нашла. Смотреть исходники Qt для меня сложно.

Код у меня такой:
создание делегата: http://www.forum.crossplatform.ru/index.php?showtopic=8385
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>

class QStandardItemModel;
class QTableView;

#include "delegate.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    QStandardItemModel* model;
    QTableView* tableView;
    TextEditDelegate* delegate;
};

#endif // MAINWINDOW_H
mainwindow.cpp
#include <QtGui/QStandardItemModel>
#include <QtGui/QTableView>
#include <QtGui/QHeaderView>

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    model = new QStandardItemModel(5, 2);
    tableView = new QTableView();
    delegate = new TextEditDelegate();
    
    for (int row = 0; row < 5; ++row) {
        for (int column = 0; column < 2; ++column) {
            QModelIndex index = model->index(row, column, QModelIndex());
            switch(column)
            {
            case 0:
                model->setData(index, QVariant(
                        row+1)); break;
            default:
                switch(row)
                {
                case 0:
                    model->setData(index, QVariant(
                            "")); break;
                case 1:
                    model->setData(index, QVariant(
                            "Абв"
                            "  PRIVETPRIVET 1 01234"
                            "  PRIVET 2 01234"
                            "  PRIVET 3 01234"
                            "  PRIVET 4 01234")); break;
                case 2:
                    model->setData(index, QVariant(
                            "PRIVET PRIVET 1 01234"
                            "  Абв"
                            "  PRIVET 2 01234"
                            "  PRIVET 3 01234"
                            "  PRIVET 4 01234")); break;
                case 3:
                    model->setData(index, QVariant(
                            "Абв"
                            "  PRIVETPRIVET 1 01234"
                            "  PRIVET 2 01234"
                            "  PRIVET 3 01234")); break;
                default:
                    model->setData(index, QVariant(
                            "Абв"
                            "  PRIVETPRIVET 1 01234"
                            "  PRIVET 2 01234"
                            "  PRIVET 3 01234"
                            "  PRIVET 4 01234")); break;
                }
                break;
            }
        }
    }

    tableView->setModel(model);
    tableView->setItemDelegateForColumn(1, delegate);
    tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    tableView->setSelectionBehavior(QAbstractItemView::SelectRows);

    tableView->resizeColumnToContents(0);
    tableView->horizontalHeader()->setStretchLastSection(true);

    tableView->verticalHeader()->hide();
    tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
//    tableView->setTextElideMode(Qt::ElideNone);

    if (model->rowCount() > 0)
        tableView->setCurrentIndex(model->index(0, 0));

    setCentralWidget(tableView);

    setWindowTitle("Text Edit Delegate");
    setGeometry(100, 250, 170, 500);
}

MainWindow::~MainWindow()
{

}

Подумала, что надо использовать
tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
чтобы высота строк tableView пересчитывалась автоматически.

Если отремить строку
tableView->setTextElideMode(Qt::ElideNone);
то возникает другая проблема. В этом случае текст всегда отображается не сокращенно, а полностью. Но зато высота строк tableView пересчитывается неверно и возникают состояния, когда высота получается меньше, чем необходимо для отображения всего текста ячеек. Вот так (см. рис2):



Так тоже не получается то, что хочется:
main.cpp
#include <QtCore/QTextCodec>
#include <QtGui/QApplication>

#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("Windows-1251"));

    MainWindow mainWindow;
    mainWindow.show();

    mainWindow.slot_resizeRowsToContents();

    return app.exec();
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
...
//    tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
//    tableView->setTextElideMode(Qt::ElideNone);
    connect(this->btn_resizeRowsToContents, SIGNAL(clicked()),
            this, SLOT(slot_resizeRowsToContents()));
...
}

void MainWindow::slot_resizeRowsToContents()
{
    setUpdatesEnabled(false);
    tableView->resizeRowsToContents();
    setUpdatesEnabled(true);

    tableView->update();
}
В этом случае, после нажатия кнопки "resizeRowsToContents", текст иногда продолжает отображаться сокращенно, вот так (см. рис3):


Может быть, я не в том порядке что-то пишу в своем коде? Или вообще что-то не так делаю?
:unknown:
В этом архиве - папка с файлами проекта и картинками экрана:
Прикрепленный файл  test_texteditdelegate_forum1.zip ( 128,14 килобайт ) Кол-во скачиваний: 265


Сообщение отредактировал Steklova Olga - 2.4.2012, 19:02
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 3.4.2012, 20:06
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


к сожалению придётся делать свой делегат, в котором нужно будет принимать решение о том как отображать текст при заданной ширине столбца.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Steklova Olga
  опции профиля:
сообщение 3.4.2012, 21:44
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 198
Регистрация: 27.9.2011
Из: Санкт-Петербург
Пользователь №: 2912

Спасибо сказали: 5 раз(а)




Репутация:   4  


А я рассчитывала на то, что мне хватит созданного мною примитивного делегата, а вот этот оператор сам за меня все автоматически пересчитает:
tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);

Цитата
придётся делать свой делегат, в котором нужно будет принимать решение о том как отображать текст при заданной ширине столбца
Я совсем-совсем не понимаю, как это сделать... :unsure: А Вы знаете?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Steklova Olga
  опции профиля:
сообщение 4.4.2012, 21:52
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 198
Регистрация: 27.9.2011
Из: Санкт-Петербург
Пользователь №: 2912

Спасибо сказали: 5 раз(а)




Репутация:   4  


Теперь я поняла, что
Цитата
Так как представление у меня редактировать не надо, то делегата для редактирования мне не нужно,
надо просто указать подходящий режим для представления:
tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);

Жаль только, что он работает, по-моему, кривовато, поэтому вопрос у меня остался открытым, как
Цитата(Litkevich Yuriy)
принимать решение о том, как отображать текст при заданной ширине столбца

У меня подозрение, что в какие-то моменты происходит переключение с установленного мною режима QHeaderView::ResizeToContents на какой-то другой.

Сообщение отредактировал Steklova Olga - 5.4.2012, 17:15
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Snake174
  опции профиля:
сообщение 5.4.2012, 7:00
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 89
Регистрация: 18.4.2011
Из: Миасс
Пользователь №: 2613

Спасибо сказали: 9 раз(а)




Репутация:   0  


Попробуй в своей модели установить SizeHintRole:
QVariant Model::data( const QModelIndex &index, int role ) const
{
  if (!index.isValid())
    return QVariant();

  if (index.row() >= static_cast<int>( количество строк )
    return QVariant();

  if (index.column() >= количество столбцов)
    return QVariant();

  if (role == Qt::DisplayRole || role == Qt::ToolTipRole || role == Qt::StatusTipRole)
  {
    for (register int i = 0; i < количество столбцов; ++i)
    {
      if (index.column() == i)
        return текстовые данные;
    }
  }

  if (role == Qt::SizeHintRole)
  {
    QFontMetrics fm( QApplication::font() );
    int h = fm.boundingRect( текстовые данные ).height();
    
    QSize defSize;
    defSize.setHeight( h + 4 );

    return defSize;
  }

  return QVariant();
}


Попробуй в своей модели установить SizeHintRole:
QVariant Model::data( const QModelIndex &index, int role ) const
{
  if (!index.isValid())
    return QVariant();

  if (index.row() >= static_cast<int>( количество строк )
    return QVariant();

  if (index.column() >= количество столбцов)
    return QVariant();

  if (role == Qt::DisplayRole || role == Qt::ToolTipRole || role == Qt::StatusTipRole)
  {
    for (register int i = 0; i < количество столбцов; ++i)
    {
      if (index.column() == i)
        return текстовые данные;
    }
  }

  if (role == Qt::SizeHintRole)
  {
    QFontMetrics fm( QApplication::font() );
    int h = fm.boundingRect( текстовые данные ).height();
    
    QSize defSize;
    defSize.setHeight( h + 4 );

    return defSize;
  }

  return QVariant();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
wiz29
  опции профиля:
сообщение 5.4.2012, 9:27
Сообщение #6


Старейший участник
****

Группа: Участник
Сообщений: 600
Регистрация: 7.7.2010
Из: Санкт-Петербург
Пользователь №: 1866

Спасибо сказали: 94 раз(а)




Репутация:   12  


попробуй просто отображать содержимое делегата для текстовой ячейки

Приведу схематично:

1. Устанавливаешь конкретный делегат для отображения строк.
2. Переопределяешь метод void QItemDelegate::drawDisplay ( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QString & text ) const
Конфигурация области рисования в нее передается, далее просто отображаешь текст через QPainter c теми параметрами, которые требуются.

Сообщение отредактировал wiz29 - 5.4.2012, 9:42
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
wiz29
  опции профиля:
сообщение 5.4.2012, 10:15
Сообщение #7


Старейший участник
****

Группа: Участник
Сообщений: 600
Регистрация: 7.7.2010
Из: Санкт-Петербург
Пользователь №: 1866

Спасибо сказали: 94 раз(а)




Репутация:   12  


Вот на основе изначального примера что получилось.

немного поменял файл

Сообщение отредактировал wiz29 - 5.4.2012, 10:15
Прикрепленные файлы
Прикрепленный файл  test_texteditdelegate_forum1.zip ( 128,57 килобайт ) Кол-во скачиваний: 270
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Steklova Olga
  опции профиля:
сообщение 5.4.2012, 15:07
Сообщение #8


Участник
**

Группа: Участник
Сообщений: 198
Регистрация: 27.9.2011
Из: Санкт-Петербург
Пользователь №: 2912

Спасибо сказали: 5 раз(а)




Репутация:   4  


Спасибочки, wiz29, Вы очень умный! :give_rose:
При просмотре текст теперь отображается так, как было задумано.
Вот только я еще даже не смотрела класс QPainter. Посмотрю.
Надо мне хотя-бы книжку Земскова "Qt на примерах" полностью прочитать, а не писать программу интуитивно, бегая по верхам помощи (по классам Qt), книжек, форума и googlе :)

Есть только маленький вопросик сейчас: что в Вашем примере надо поменять, чтобы при просмотре представления цвет текста в выбранной строке в колонке с делегатом становился (как это принято) белым, а не так, как сейчас (черным) (см. рис)?


1. На будущее, если делать представление редактируемым,
то недостаточно переопределить только createEditor и drawDisplay так, как сейчас.

2. Сейчас мое представление не редактируемое,
поэтому переопределение createEditor в этом варианте я убрала, как совершенно не нужное.

3. Рассказываю дальше, зачем все это надо.
У меня в таблице БД сохраняется переписка двух абонентов (их сообщения друг другу в виде простого текста (не html), время посылки сообщения, ID написавшего сообщение абонента).
В соотв. с моим алгоритмом, в процессе переписки эту таблицу отображать не надо.
После окончания переписки (я знаю, когда это произойдет) надо отобразить таблицу сообщений.
Сначала надо отобразить все сообщения.
После этого можно будет их сортировать / фильтровать (это я знаю, как сделать).

Но вот я думаю, что, так как сообщения могут быть достаточно длинными, хорошо бы было предусмотреть возможность двух вариантов отображения сообщений и переключения между ними с помощью группы кнопок "Сокращенно", "Полностью".
Сначала отобразить все сообщения в первом варианте, сокращенно (каждое - в одну строку, с "..."),
при нажатии кнопки "Полностью" отобразить все сообщения во втором варианте, полностью,
при нажатии кнопки "Сокращенно" вернуться к первому варианту.
Мне кажется, это было бы очень удобно.
:D
Принимаются предложения, как прикрутить к имеющемуся коду сокращенный вариант.

А перерисовку может сократить как-то? Или не стоит об этом беспокоиться?
Например, не постоянно пересчитывать, как отобразить текст в процессе изменения размера окна,
а сделать это сначала при первом отображении таблицы сообщений,
а следующий раз (в случае изменения размера окна) сделать по окончании изменения размера окна, при отпускании мыши.


И еще, пока что, открыт вопрос, как корректно сохранять сообщения неизвестной заранее длины в БД Firebird 2.1 и отображать их потом в представлении (там проблемы с русским текстом и, видимо, с драйвером), об этом моя тема тут.
Если бы этот вопрос решился, то я вместо работы с сообщениями длиной не более 1000 символов,
перешла бы к работе с сообщениями, неограниченными по длине. Так надо по алгоритму.
И тогда эта ветка программы была бы доделана. ;)

Сообщение отредактировал Steklova Olga - 6.4.2012, 10:36
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
wiz29
  опции профиля:
сообщение 5.4.2012, 15:46
Сообщение #9


Старейший участник
****

Группа: Участник
Сообщений: 600
Регистрация: 7.7.2010
Из: Санкт-Петербург
Пользователь №: 1866

Спасибо сказали: 94 раз(а)




Репутация:   12  


Цитата(Steklova Olga @ 5.4.2012, 16:07) *
что в Вашем примере надо поменять, чтобы при просмотре представления цвет текста в выбранной строке в колонке с делегатом становился (как это принято) белым, а не так, как сейчас (черным) (см. рис)?


Модификация.

Прикрепленные файлы
Прикрепленный файл  test_texteditdelegate_forum1.zip ( 128,58 килобайт ) Кол-во скачиваний: 323
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Steklova Olga
  опции профиля:
сообщение 5.4.2012, 17:03
Сообщение #10


Участник
**

Группа: Участник
Сообщений: 198
Регистрация: 27.9.2011
Из: Санкт-Петербург
Пользователь №: 2912

Спасибо сказали: 5 раз(а)




Репутация:   4  


Благодарю, Вас, wiz29 ! Теперь просмотр поля типа VARCHAR(1000) в QTableView чудно работает ! :clapping:
P.S. внесла дополнение в свое сообщение 8

Сообщение отредактировал Steklova Olga - 6.4.2012, 10:41
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 23.11.2024, 3:40