使用 QStyledItemDelegate 子类在 QTableView 中创建按钮
Create PushButtons in QTableView with QStyledItemDelegate subclass
我有完全相同的 problem, but I will use the QTableView widget. I read this 并且想知道我是否可以覆盖 createEditor 函数以使用例如 QFileDialog 来获取新数据。
如果可能的话,谁能给我一个例子来实现这样一个QItemDelegate的子类。
如果没有,谁能给我一个例子来实现 QItemDelegate 的子类, 可以在 QLineEdit 旁边画一个按钮来获得功能 here。
编辑:也许这个问题真的很愚蠢,我没有意识到,因为我离开这个项目大约半年了。
其次:从Qt 5.7更新到5.8安全吗?
- 使用 QStyledItemDelegate,而不是 QItemDelegate。
- 阅读 Qt 手册
- 子类 QStyledItemDelegate 的代码示例(精简):
头文件
#ifndef MYITEMDELEGATE_H
#define MYITEMDELEGATE_H
#include <QStyledItemDelegate>
class KontaktForm;
class MyItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
mutable SubscriberForm *subscriberForm;
public:
explicit MyItemDelegate(QObject *parent = 0);
~MyItemDelegate();
////////!Methods - You don't need all of them
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};
#endif // MYITEMDELEGATE_H
源文件
#include "myitemdelegate.h"
#include "mytreeview.h"
#include <QModelIndex>
#include <QSize>
MyItemDelegate::MyItemDelegate(QObject *parent) : QStyledItemDelegate(parent),
subscriberForm(Q_NULLPTR),
{
}
QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//// return the QSize of the item in Your view
}
void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
////optional : implement custom painting - text, images, drawings, and such
}
QWidget *MyItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
subscriberForm = new SubscriberForm(parent);
////optional additional settings for Your editor
return subscriberForm;
}
void MyItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
////setup the editor - your data are in index.data(Qt::DataRoles) - stored in a QVariant;
QString value = index.model()->data(index,Qt::EditRole).toString();
SubscriberForm *subscriberForm = static_cast<SubscriberForm*>(editor);
}
void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
////optional - if needed - return changed data, from editor to the model in a custom matter
SubscriberForm *subscriberForm = static_cast<SubscriberForm*>(editor);
model->setData(index,QVariant(subscriberForm->getData()),Qt::EditRole);
}
我已尽力而为,这是我的解决方案。
QStyledItemDelegate 子类的代码大部分来自here.
解决方案图片
但是,有一件事我很想解决:(也许有人可以帮助我并发表评论)
QPixmap::grabWidget is deprecated, use QWidget::grab() instead
但看起来 QWidget::grab()
不是用于此目的的正确解决方案。
foo.h:
#ifndef LIBRARYITEMDELEGATE_H
#define LIBRARYITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QWidget>
#include <QPushButton>
#include <QTableView>
class LibraryItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit LibraryItemDelegate(QObject *parent = 0);
~LibraryItemDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
// QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setModelData(QWidget *editor, QAbstractItemModel *modal, const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
public slots:
void cellEntered(const QModelIndex &index);
private:
QTableView *myView;
QPushButton *btn;
bool isOneCellInEditMode;
QPersistentModelIndex currentEditedCellIndex;
};
#endif // LIBRARYITEMDELEGATE_H
foo.cpp:
#include "libraryitemdelegate.h"
#include <QPainter>
#include <QStylePainter>
LibraryItemDelegate::LibraryItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
if(QTableView *tableView = qobject_cast<QTableView*>(parent))
{
myView = tableView;
btn = new QPushButton("...", myView);
btn->hide();
myView->setMouseTracking(true);
connect(myView, SIGNAL(entered(QModelIndex)), this, SLOT(cellEntered(QModelIndex)));
isOneCellInEditMode = false;
}
}
LibraryItemDelegate::~LibraryItemDelegate(){}
void LibraryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
btn->setGeometry(option.rect);
btn->setText("...");
if(option.state == QStyle::State_Selected)
{
painter->fillRect(option.rect, option.palette.highlight());
}
QPixmap map = QPixmap::grabWidget(btn);
painter->drawPixmap(option.rect.x(), option.rect.y(), map);
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}
//QSize LibraryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
//{
// // return the QSize of the item in Your view
//}
QWidget *LibraryItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
QPushButton *btn = new QPushButton(parent);
// btn->setText(index.data().toString());
btn->setText("...");
return btn;
}
else
{
return QStyledItemDelegate::createEditor(parent, option, index);
}
}
void LibraryItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);
// btn->setProperty("data_value", index.data());
btn->setProperty("data_value", "...");
btn->setText("...");
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void LibraryItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);
model->setData(index, btn->property("data_value"));
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}
void LibraryItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
void LibraryItemDelegate::cellEntered(const QModelIndex &index)
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
if(isOneCellInEditMode)
{
myView->closePersistentEditor(currentEditedCellIndex);
}
myView->openPersistentEditor(index);
isOneCellInEditMode = true;
currentEditedCellIndex = index;
}
else
{
if(isOneCellInEditMode)
{
isOneCellInEditMode = false;
myView->closePersistentEditor(currentEditedCellIndex);
}
}
}
实施:
QStandardItemModel *myModel; // This is in the Header file
myModel = new QStandardItemModel(0,2,this);
myModel->setHeaderData(1, Qt::Horizontal, 1, Qt::UserRole);
myModel->setHorizontalHeaderLabels(QStringList(tr("Pfad zu den bibliotheks Ordnern")));
// Set Model and delegate to the View
ui->tableView_pathes->setModel(myModel);
LibraryItemDelegate *delegate = new LibraryItemDelegate(ui->tableView_pathes);
ui->tableView_pathes->setItemDelegate(delegate);
// Stretch only the first column
ui->tableView_pathes->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Stretch);
ui->tableView_pathes->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Fixed);
编辑:这是 tableView 中按钮的代码。将 createEditor 中的信号与 connect(btn, SIGNAL(pressed()), this, SLOT(buttonPressed()));
连接并设置为委托提供对 QStandardItemModel 的引用。
void LibraryItemDelegate::buttonPressed()
{
QString dir = QFileDialog::getExistingDirectory(new QWidget(), tr("Wähle die bibliotheks Ordner"), "/home", QFileDialog::ShowDirsOnly);
qDebug() << "Test: " << dir;
if(!dir.isEmpty())
{
QModelIndex ind = currentEditedCellIndex.model()->index(currentEditedCellIndex.row(), 0);
myModel->setData(ind, dir, Qt::DisplayRole);
}
}
我有完全相同的 problem, but I will use the QTableView widget. I read this 并且想知道我是否可以覆盖 createEditor 函数以使用例如 QFileDialog 来获取新数据。
如果可能的话,谁能给我一个例子来实现这样一个QItemDelegate的子类。
如果没有,谁能给我一个例子来实现 QItemDelegate 的子类, 可以在 QLineEdit 旁边画一个按钮来获得功能 here。
编辑:也许这个问题真的很愚蠢,我没有意识到,因为我离开这个项目大约半年了。
其次:从Qt 5.7更新到5.8安全吗?
- 使用 QStyledItemDelegate,而不是 QItemDelegate。
- 阅读 Qt 手册
- 子类 QStyledItemDelegate 的代码示例(精简):
头文件
#ifndef MYITEMDELEGATE_H
#define MYITEMDELEGATE_H
#include <QStyledItemDelegate>
class KontaktForm;
class MyItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
mutable SubscriberForm *subscriberForm;
public:
explicit MyItemDelegate(QObject *parent = 0);
~MyItemDelegate();
////////!Methods - You don't need all of them
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};
#endif // MYITEMDELEGATE_H
源文件
#include "myitemdelegate.h"
#include "mytreeview.h"
#include <QModelIndex>
#include <QSize>
MyItemDelegate::MyItemDelegate(QObject *parent) : QStyledItemDelegate(parent),
subscriberForm(Q_NULLPTR),
{
}
QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//// return the QSize of the item in Your view
}
void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
////optional : implement custom painting - text, images, drawings, and such
}
QWidget *MyItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
subscriberForm = new SubscriberForm(parent);
////optional additional settings for Your editor
return subscriberForm;
}
void MyItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
////setup the editor - your data are in index.data(Qt::DataRoles) - stored in a QVariant;
QString value = index.model()->data(index,Qt::EditRole).toString();
SubscriberForm *subscriberForm = static_cast<SubscriberForm*>(editor);
}
void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
////optional - if needed - return changed data, from editor to the model in a custom matter
SubscriberForm *subscriberForm = static_cast<SubscriberForm*>(editor);
model->setData(index,QVariant(subscriberForm->getData()),Qt::EditRole);
}
我已尽力而为,这是我的解决方案。 QStyledItemDelegate 子类的代码大部分来自here.
解决方案图片
但是,有一件事我很想解决:(也许有人可以帮助我并发表评论)
QPixmap::grabWidget is deprecated, use QWidget::grab() instead
但看起来QWidget::grab()
不是用于此目的的正确解决方案。
foo.h:
#ifndef LIBRARYITEMDELEGATE_H
#define LIBRARYITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <QWidget>
#include <QPushButton>
#include <QTableView>
class LibraryItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit LibraryItemDelegate(QObject *parent = 0);
~LibraryItemDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
// QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
void setModelData(QWidget *editor, QAbstractItemModel *modal, const QModelIndex &index) const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
public slots:
void cellEntered(const QModelIndex &index);
private:
QTableView *myView;
QPushButton *btn;
bool isOneCellInEditMode;
QPersistentModelIndex currentEditedCellIndex;
};
#endif // LIBRARYITEMDELEGATE_H
foo.cpp:
#include "libraryitemdelegate.h"
#include <QPainter>
#include <QStylePainter>
LibraryItemDelegate::LibraryItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
if(QTableView *tableView = qobject_cast<QTableView*>(parent))
{
myView = tableView;
btn = new QPushButton("...", myView);
btn->hide();
myView->setMouseTracking(true);
connect(myView, SIGNAL(entered(QModelIndex)), this, SLOT(cellEntered(QModelIndex)));
isOneCellInEditMode = false;
}
}
LibraryItemDelegate::~LibraryItemDelegate(){}
void LibraryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
btn->setGeometry(option.rect);
btn->setText("...");
if(option.state == QStyle::State_Selected)
{
painter->fillRect(option.rect, option.palette.highlight());
}
QPixmap map = QPixmap::grabWidget(btn);
painter->drawPixmap(option.rect.x(), option.rect.y(), map);
}
else
{
QStyledItemDelegate::paint(painter, option, index);
}
}
//QSize LibraryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
//{
// // return the QSize of the item in Your view
//}
QWidget *LibraryItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
QPushButton *btn = new QPushButton(parent);
// btn->setText(index.data().toString());
btn->setText("...");
return btn;
}
else
{
return QStyledItemDelegate::createEditor(parent, option, index);
}
}
void LibraryItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);
// btn->setProperty("data_value", index.data());
btn->setProperty("data_value", "...");
btn->setText("...");
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void LibraryItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
QPushButton *btn = qobject_cast<QPushButton*>(editor);
model->setData(index, btn->property("data_value"));
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}
void LibraryItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
void LibraryItemDelegate::cellEntered(const QModelIndex &index)
{
if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
{
if(isOneCellInEditMode)
{
myView->closePersistentEditor(currentEditedCellIndex);
}
myView->openPersistentEditor(index);
isOneCellInEditMode = true;
currentEditedCellIndex = index;
}
else
{
if(isOneCellInEditMode)
{
isOneCellInEditMode = false;
myView->closePersistentEditor(currentEditedCellIndex);
}
}
}
实施:
QStandardItemModel *myModel; // This is in the Header file
myModel = new QStandardItemModel(0,2,this);
myModel->setHeaderData(1, Qt::Horizontal, 1, Qt::UserRole);
myModel->setHorizontalHeaderLabels(QStringList(tr("Pfad zu den bibliotheks Ordnern")));
// Set Model and delegate to the View
ui->tableView_pathes->setModel(myModel);
LibraryItemDelegate *delegate = new LibraryItemDelegate(ui->tableView_pathes);
ui->tableView_pathes->setItemDelegate(delegate);
// Stretch only the first column
ui->tableView_pathes->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Stretch);
ui->tableView_pathes->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Fixed);
编辑:这是 tableView 中按钮的代码。将 createEditor 中的信号与 connect(btn, SIGNAL(pressed()), this, SLOT(buttonPressed()));
连接并设置为委托提供对 QStandardItemModel 的引用。
void LibraryItemDelegate::buttonPressed()
{
QString dir = QFileDialog::getExistingDirectory(new QWidget(), tr("Wähle die bibliotheks Ordner"), "/home", QFileDialog::ShowDirsOnly);
qDebug() << "Test: " << dir;
if(!dir.isEmpty())
{
QModelIndex ind = currentEditedCellIndex.model()->index(currentEditedCellIndex.row(), 0);
myModel->setData(ind, dir, Qt::DisplayRole);
}
}