Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: создание делегата для QTableView на основе QTextEdit
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Модель/Представление
Steklova Olga
Всем привет! :)
У меня в БД FireBird есть следующая таблица:
CREATE TABLE T_MSG_VC(
    F_RECORD_NMB      D_INTEGER NOT NULL,
    F_MSG_TEXT_VC     VARCHAR(1000) NOT NULL
);
Хочу ее отобразить в QTableView.
Оператор должен иметь возможность просмотра таблицы, а редактирование данных должно быть запрещено.
Для этого мне, видимо, нужно создать делегат.
Посмотрите, пожалуйста, для моего случая достаточно того, что я написала?
delegate.h
#ifndef DELEGATE_H
#define DELEGATE_H

#include <QtGui/QItemDelegate>

class TextEditDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    TextEditDelegate(QObject *parent = 0);

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const;
};

#endif
delegate.cpp
#include <QtGui/QTextEdit>

#include "delegate.h"

TextEditDelegate::TextEditDelegate(QObject *parent)
    : QItemDelegate(parent)
{
}

QWidget *TextEditDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex &/* index */) const
{
    QTextEdit *editor = new QTextEdit(parent);

    return editor;
}
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    ...
    tableView = new QTableView();
    delegate = new TextEditDelegate();

    tableView->setItemDelegateForColumn(1, delegate);
    tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ...
}
...
Пока не говорю о размерах ячеек QTableView. Об этом позже... :)
Litkevich Yuriy
Цитата(Steklova Olga @ 2.4.2012, 17:21) *
Оператор должен иметь возможность просмотра таблицы, а редактирование данных должно быть запрещено.
Это достигается установкой триггеров редактирования - EditTriggers

Если же нужно ограничить редактирование определённых данных (строки или столбца) лучше сделать свою модель, которая переопределяет один единственный метод:
virtual Qt::ItemFlags flags ( const QModelIndex & index ) const

и для некторого(ых) индекса НЕ будет возвращать Qt::ItemIsEditable
Steklova Olga
Спасибо, Юрий, это все понятно :)
А в классе TextEditDelegate ничего больше не надо переопределять (если, конечно, не нужно редактирование текста)?
Litkevich Yuriy
если сделаешь свою модель, то свой делегат вообще не нужно делать, если, конечно, он не специфический.
Steklova Olga
И все же, если я остановлюсь на использовании моего делегата, простого до крайности, то вот этого достаточно?
QWidget *TextEditDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex &/* index */) const
{
    QTextEdit *editor = new QTextEdit(parent);
    return editor;
}

Цитата
если сделаешь свою модель, то свой делегат вообще не нужно делать, если, конечно, он не специфический.
И как мне без использования делегата указать в модели, что при ее отображении в QTableView надо будет использовать QTextEdit?
wiz29
Если внутри QVariant будет строка то фабрика по умолчанию создаст делегат для строк как QLineEdit.

см. тут
Litkevich Yuriy
Steklova Olga, ты про делегат не правильно понимаешь.

Коротко:
Делегат - класс, объект которого создаёт представление, этот класс в обычном режиме рисует элемент данных в определённом месте представления (получая данные непосредственно из модели).
Рисование элемента осуществляется в функции делегата paint().
Когда пользователь переходит в режим редактирования данных (а тебе это не нужно), представление вызывает у делегата целую пачку методов, начиная с createEditor(), которая просто создаёт виджет-редактор.

Виджет-редактор - виджет, который создаётся делегатом только для редактирования данных. По завершении редактирования виджет-редактор разрушается.


Поняла?

П.С.
Только сейчас стал понимать, в чём проблема (описаная в другой теме) в твоём делегате. Видимо ты создаёшь объект QTextEdit в качестве виджета-редактора, и ожидаешь что делегат в обычном режиме будет себя вести как QTextEdit. Хотя делегат в этом режиме самостоятельно занимается рисованием элемента на экране.
Steklova Olga
Спасибо большое, Юрий, в общих чертах поняла! Ура! :clapping::D

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

А когда мне понадобится редактировать данные в представлении, прямо на экране, то мне НЕ ПОМЕШАЕТ ПОЧИТАТЬ про делегаты подробно, а не просто бездумно списывать. :)

wiz29, спасибо за ссылку, но для редактирования поля типа VARCHAR(1000) делегат для строк как QLineEdit не очень-то подойдет, для этого нужен QTextEdit. Потому что неудобно редактировать такой длинный текст в одной строке.
Steklova Olga
wiz29, а вот что я заметила в части использования QLineEdit в качестве делегата:

1. Если не создавать делегат вручную, но начать редактирование поля типа VARCHAR(1000), то, действительно, на экране появится QLineEdit в этой ячейке,
но, если до выхода из редактирования расширить или сузить мышью окно, то ширина QLineEdit останется такой, как она была до изменения размера окна, а из под него будет видна часть многострочного текста (см рис1).

2. Если создать класс делегата, указав в createEditor
QLineEdit *editor = new QLineEdit(parent);
установить этот делегат для колонки представления, начать редактирование поля типа VARCHAR(1000), то на экране появится QLineEdit в этой ячейке, а, если до выхода из редактирования расширить или сузить мышью окно, то ширина QLineEdit будет корректно меняться в соотв. с меняющимися размерами окна (см рис2).
Получается, что 2-й вариант предпочтительнее :)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.