Добрый день!
Прочитав топик, решил что возможно будет интересна технология работы с делегатами в Qt, которая является часть реализации схемы MVC в Qt.
Но вдаваться в теорию не будем, а рассмотрим простой пример.
Хотя нет, ведь не все знакомы с Qt, приведу определение делегата.
Делегаты — это специальные классы, которые могут использоваться для управления режимами отображения или редактирования ячеек таблицы QTableView, равно как и элементов других представлений.
Все хватит теории. А рассматривать будем самый просто пример: есть некая модель, которая в одном своем элементе (item), хранит пусть файловой системы, и соответственно при изменении пользователем данного элемента нужно вызвать нужный диалог (системы или свой это уже не так важно).
Самый простой способ это при двойном или одинарном клике по элементы вызвать этот диалог. Но это не удобно — случайно кликнул и вдруг выскочил какой-то диалог, да и не принято.
Что тогда можно сделать. А сделать можно следующее — при двойном клике по элементы перевести ячейку в режим редактирования и в ячейке элемента отобразить кнопку, клик по которой и будет вызван диалог выбора пути.
С чего начать — нужен виджет для делегата. По сути это поле ввода (QLineEdit) и кнопка (QToolButton). В стандартной поставке такой виджет не найдет, но это не беда, делаем свой:
Виджет готов, теперь дело за делегатом:
Приведу и реализацию делегата, чтобы было понятно как идет манипуляция данными:
Прочитав топик, решил что возможно будет интересна технология работы с делегатами в Qt, которая является часть реализации схемы MVC в Qt.
Но вдаваться в теорию не будем, а рассмотрим простой пример.
Хотя нет, ведь не все знакомы с Qt, приведу определение делегата.
Делегаты — это специальные классы, которые могут использоваться для управления режимами отображения или редактирования ячеек таблицы QTableView, равно как и элементов других представлений.
Все хватит теории. А рассматривать будем самый просто пример: есть некая модель, которая в одном своем элементе (item), хранит пусть файловой системы, и соответственно при изменении пользователем данного элемента нужно вызвать нужный диалог (системы или свой это уже не так важно).
Самый простой способ это при двойном или одинарном клике по элементы вызвать этот диалог. Но это не удобно — случайно кликнул и вдруг выскочил какой-то диалог, да и не принято.
Что тогда можно сделать. А сделать можно следующее — при двойном клике по элементы перевести ячейку в режим редактирования и в ячейке элемента отобразить кнопку, клик по которой и будет вызван диалог выбора пути.
С чего начать — нужен виджет для делегата. По сути это поле ввода (QLineEdit) и кнопка (QToolButton). В стандартной поставке такой виджет не найдет, но это не беда, делаем свой:
class LineEdit : public QLineEdit
{
Q_OBJECT
public:
LineEdit( const QModelIndex &index, QWidget *parent = 0);
~LineEdit ();
QString getChoice () {return fileName;}
protected:
void resizeEvent(QResizeEvent *); //в этой функции делаем так чтобы текст не залезал под кнопку
private slots:
void pressButton ( ); //здесь вызов диалога выбора файла/каталога
private:
QToolButton *clearButton;
QModelIndex indexSource;
QString fileName;
};
Виджет готов, теперь дело за делегатом:
class CChoicePathDelegate : public QItemDelegate
{
public:
CChoicePathDelegate (QObject *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const; //создаем редактор делегата - это наш виджет
void setEditorData(QWidget *editor, const QModelIndex &index) const; //устанавливаем данные в редакторе
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const; //а здесь данные из редактора передаем уже в модель
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
Приведу и реализацию делегата, чтобы было понятно как идет манипуляция данными:
CChoicePathDelegate::CChoicePathDelegate (QObject *parent)
:QItemDelegate(parent)
{
}
QWidget *CChoicePathDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option, const QModelIndex &index) const
{
LineEdit *dlg = new LineEdit (index, parent); //создаем наше поле ввода с кнопкой
return dlg;
}
void CChoicePathDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
//в этой функции на входе данные из модели и указатель на виджет редактора
QString value = index.model()->data(index).toString(); //получаем что уже есть в модели
LineEdit *fileDialog = static_cast<LineEdit*> (editor); //преобразуем указатель
fileDialog->setText(value); //устанавливаем текст
}
void CChoicePathDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model, const QModelIndex &index) const
{
//сюда попадаем когда редактор делегата теряем фокус/закрывается
LineEdit *fileDialog = static_cast<LineEdit*> (editor);
if (!fileDialog->getChoice().isEmpty())
model->setData(index, fileDialog->getChoice()); //устанавливаем новое значение в модель
}
Теперь в классе представления осталось указать что при редактировании определенной ячейки/строки/столбца будет использован делегат:
view = new QTreeView (this);
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
view->setDragEnabled(true);
view->setAcceptDrops(true);
view->setDropIndicatorShown(true);
CChoicePathDelegate *delegate = new CChoicePathDelegate (this);
view->setItemDelegateForColumn(4, delegate); //вот собственно установка делегата
Пример конечно самый простой, более сложный, но и более интересный - это в приложении работающий с БД, когда нужно вызвать из представления одной таблицы/объекта представление другой, пример, для установки основной единицы измерения номенклатуры из формы номенклатуры нужно вызвать форму подбора единиц измерения.