首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用自定义QItemDelegate实现QTableView的Qt

使用自定义QItemDelegate实现QTableView的Qt
EN

Stack Overflow用户
提问于 2013-05-21 00:27:16
回答 3查看 34.5K关注 0票数 19

我遵循Qt提供的Spin代理教程,尝试实现我自己的QItemDelegate。它将用于指定一个QComboBox来表示QTableView单元中的数据,但它不起作用。

我最大的问题是,我不知道什么时候我的QItemDelegate将被利用。

  • 何时使用itemModel->setData()或何时使用itemModel->setItem()。我会怀疑setItem(),因为我重新实现了一个QItemDelegate (强调“项”),但是本教程使用setData(),并且运行良好。
  • 我知道,如果指定的QItemDelegate不能工作,它将使用默认的,但是,既然我指定的那个不能工作,我该怎么做呢?
  • 什么时候我应该怀疑QTableView使用我的委托。我想指定每个单元格使用哪些委托。这是可能的还是QTableView在整个过程中只使用一个委托?
  • 一旦QComboBoxQTableView显示,我将如何指定填充它的项

我在这里实现了QItemDelegate

  • 我试图添加要使用QComboBox的单元格的部分在mainwindow.cpp后面的注释"Enabled“下面。

qcomboboxitemdelegate.h

代码语言:javascript
复制
#ifndef QCOMBOBOXITEMDELEGATE_H
#define QCOMBOBOXITEMDELEGATE_H

#include <QItemDelegate>
#include <QComboBox>

class QComboBoxItemDelegate : public QItemDelegate
{
    Q_OBJECT

public: 

    explicit QComboBoxItemDelegate(QObject *parent = 0);

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index);
    void setEditorData(QWidget *editor, const QModelIndex &index);
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index);
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,     const QModelIndex &index);

signals:

private:

};

#endif // QCOMBOBOXITEMDELEGATE_H

qcomboboxitemdelegate.cpp

代码语言:javascript
复制
#include "qcomboboxitemdelegate.h"
#include <QDebug>

QComboBoxItemDelegate::QComboBoxItemDelegate(QObject *parent)
: QItemDelegate(parent)
{

}

QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, const   QStyleOptionViewItem &option, const QModelIndex &index) {
    // create widget for use
    QComboBox* comboBox = new QComboBox(parent);
    return comboBox;
}

void QComboBoxItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) {
    // update model widget
    QString value = index.model()->data(index, Qt::EditRole).toString();
    qDebug() << "Value:" << value;
    QComboBox* comboBox = static_cast<QComboBox*>(editor);
    comboBox->setCurrentIndex(comboBox->findText(value));
}

void QComboBoxItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,   const QModelIndex &index) {
    // store edited model data to model
    QComboBox* comboBox = static_cast<QComboBox*>(editor);
    QString value = comboBox->currentText();
    model->setData(index, value, Qt::EditRole);
}

void QComboBoxItemDelegate::updateEditorGeometry(QWidget *editor, const     QStyleOptionViewItem &option, const QModelIndex &index) {
    editor->setGeometry(option.rect);
}

mainwindow.cpp :这就是我初始化QStandardItemModel的地方

代码语言:javascript
复制
void MainWindow::init() {
    itemModel = new QStandardItemModel(this);
}

void MainWindow::setupUi() {
    this->setWindowTitle("QAlarmClock");        
    QStringList labelList;
    labelList << "Alarm Name" << "Time" << "Enabled";
    itemModel->setHorizontalHeaderLabels(labelList);    
    ui->tableView->setModel(itemModel);
    ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableView->setItemDelegate(comboBoxItemDelegate);
}

void MainWindow::on_actionNew_triggered() {
    alarmDialog = new AlarmDialog(this);
    connect(alarmDialog, SIGNAL(on_close()), this, SLOT(on_alarmDialog_close()));
    alarmDialog->exec();
}

mainwindow.cpp :这就是我更新QStandardItemModel的地方

代码语言:javascript
复制
void MainWindow::on_alarmDialog_close() {
    QString alarmName = alarmDialog->getAlarmName();
    QDateTime alarmDateTime = alarmDialog->getDateTime();

    itemModel->insertRow(itemModel->rowCount());
    int rowCount = itemModel->rowCount();

    // Alarm Name
    QStandardItem* alarmItem = new QStandardItem(QIcon("res/alarmclock.ico"),  alarmName);
    itemModel->setItem(rowCount - 1 , 0, alarmItem);

    // Date Time
    QStandardItem* dateTimeItem = new QStandardItem();
    dateTimeItem->setText(alarmDateTime.toString());
    dateTimeItem->setEditable(false);
    itemModel->setItem(rowCount - 1, 1, dateTimeItem);

    // Enabled
    QStandardItem* enabledItem = new QStandardItem();
    QList<QStandardItem*> optionList;
    optionList << new QStandardItem("Enabled") << new QStandardItem("Disabled");
    enabledItem->appendRows(optionList);
    itemModel->setItem(rowCount - 1, 2, enabledItem);
}

编辑1

qcomboboxdelegate.cpp

代码语言:javascript
复制
QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) {
    // create widget for use
    qDebug() << "Column: " << index.column();
    if (index.column() == 2) {
        QComboBox* comboBox = new QComboBox(parent);
        QStringList values;
        values << "Enabled" << "Disabled";
        comboBox->addItems(values);
        return comboBox;
    } else {
        return QItemDelegate::createEditor(parent, option, index);
    }
}

mainwindow.cpp

代码语言:javascript
复制
void MainWindow::on_alarmDialog_close() {
    QList<QStandardItem*> row;

    QString alarmName = alarmDialog->getAlarmName();
    QDateTime alarmDateTime = alarmDialog->getDateTime();
    QString status = "Enabled";

    // Alarm Name
    QStandardItem* alarmItem = new QStandardItem(QIcon("res/alarmclock.ico"), alarmName);
    row << alarmItem;

    // Date Time
    QStandardItem* dateTimeItem = new QStandardItem();
    dateTimeItem->setText(alarmDateTime.toString());
    dateTimeItem->setEditable(false);
    row << dateTimeItem;

    // Enabled
    QStandardItem* statusItem = new QStandardItem(status);
    row << statusItem;

    itemModel->appendRow(row);
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-05-21 07:21:42

首先,您应该对模型列有一个描述:

代码语言:javascript
复制
enum Columns
{
    COL_NAME,
    COL_TIME,
    COL_STATUS
}

您的委托应该只为最后一列工作。

下面是一个如何填充模型的示例:

代码语言:javascript
复制
for (int i = 0; i < 5; ++i)
{
    QStandardItem *itemName = new QStandardItem(QString("name %1").arg(i));
    QStandardItem *itemTime = new QStandardItem(QString("time %1").arg(i));

    QString status;
    if (i % 2 == 0)
    {
        status = "Enabled";
    }
    else
    {
        status = "Disabled";
    }

    QStandardItem *itemStatus = new QStandardItem(status);

    QList<QStandardItem*> row;
    row << itemName << itemTime << itemStatus;

    model->appendRow(row);
}

正如我所说,你的代表应该只为最后一栏工作。因此,所有已重新实现的方法都应该有如下所示的列检查:

代码语言:javascript
复制
QWidget* QComboBoxItemDelegate::createEditor(QWidget *parent, 
                            const QStyleOptionViewItem &option, 
                            const QModelIndex &index) 
{
    if (index.column() == COL_STATUS)
    {
        QStringList values;
        values << "Enabled" << "Disabled";

        QComboBox* comboBox = new QComboBox(parent);
        comboBox->addItems(values);
        return comboBox;
    }
    else
    {
        return QItemDelegate::createEditor(parent, option, index);
    }
}

应该将此检查添加到其他方法:如果当前列不是status列,则应该使用基类(QItemDelegate)实现。

然后将您的代表设置为您的观点:

代码语言:javascript
复制
ui->tableView->setItemDelegate(new ComboBoxDelegate);

如果一切都做对了,如果您试图编辑它的值,组合框将出现在最后一列中。

票数 17
EN

Stack Overflow用户

发布于 2018-11-07 19:28:24

更简单的是,我发现QTableView::setItemDelegateForColumn()可以为一列出色地工作。例如,在MainWindow中,您可以成为一个成员:

代码语言:javascript
复制
QComboBoxItemDelegate dgtComboDelegate;

然后,在您的ctor或init()中,您可以

代码语言:javascript
复制
ui->tableView->setItemDelegateForColumn(2, dgtComboDelegate);

如果希望在单个单元格上发生这种情况,则需要在index.column()和index.row()上进行测试。

您知道,您也不需要创建一个QTableView就可以做到这一点。看到了吗?:

Qt - Centering a checkbox in a QTable

OP没有给出表小部件或视图的声明;但是它有QTableView标记。这两者都应该同样有效。

在前一种情况下,您可以执行ui->tableWidget->setItemDelegateForColumn(2, dgtComboDelegate);,而不必创建自己的模型。只需在您创建的项上使用setData()来初始化它们的值。

票数 4
EN

Stack Overflow用户

发布于 2013-05-21 14:52:00

因此,我发现我没有覆盖正确的函数原型..!我忘记了它们在原型中有const,这意味着我没有覆盖任何函数,所以它使用的是默认函数。下面是必须重新实现的正确的虚拟函数:http://qt-project.org/doc/qt-5.0/qtwidgets/qitemdelegate.html

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16660292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档