Доступ к входному значению делегата из модели - PullRequest
2 голосов
/ 11 июня 2019

Я использую пользовательский QTableView с пользовательским QAbstractTableModel и QItemDelegate. Мне нужно было получить доступ к содержимому редактора делегата, пока пользователь его редактирует, и после нескольких попыток я не смог найти ничего удовлетворительного.

Действительно, я пробовал несколько вещей.
Первое: попытка получить доступ к текущему входу делегата (созданному с помощью createEditor) через свойство, определенное в QItemDelegate, но ... кажется, что ничего не существует. Вот почему я попытался добавить свойство QWidget* editor и установить его в createEditor.
К сожалению, QItemDelegate s createEditor должен быть константным, что делает меня неспособным установить там свое свойство (и так как я не контролирую то, что вызывает createEditor, я не могу сделать это до или после).

Я действительно не знаю, что здесь делать. На самом деле, мне также нужно было знать, когда пользователь начал (или прекратил) редактирование содержимого ячейки, чего я в итоге достиг, создав два const сигнала (editingStarted и editingStopped). Я мог бы, вероятно, создать сигнал const editorOpened(QWidget*), но это просто плохо и уродливо ...

Я не могу поверить, что ничего "официального" не существует для достижения того, что я пытаюсь сделать, отсюда и этот вопрос. Если у меня все пойдет не так с самого начала, я был бы рад узнать. Если у вас есть другие идеи, пожалуйста, предложите.

РЕДАКТИРОВАТЬ: Вот минимальный рабочий пример

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"

#include <QTableView>
#include "mytableview.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    auto tableView = new MyTableView(this);
    setCentralWidget(tableView);
}

MainWindow::~MainWindow()
{
}

MyItemDelegate.h

#ifndef MYITEMDELEGATE_H
#define MYITEMDELEGATE_H

#include <QItemDelegate>
#include <QLineEdit>
#include <QStandardItemModel>

class MyItemDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    MyItemDelegate(QObject* parent);

    virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
    virtual void onCloseEditor();

    virtual ~MyItemDelegate() = default;

signals:
    // Const signals trick
    void editingStarted() const;
    void editingFinished() const;
    void editorOpened(const QWidget*) const;
};

#endif // MYITEMDELEGATE_H

MyItemDelegate.cpp

#include "myitemdelegate.h"

MyItemDelegate::MyItemDelegate(QObject* parent) : QItemDelegate(parent)
{
    connect(this, &QItemDelegate::closeEditor, this, &MyItemDelegate::onCloseEditor);
}

QWidget* MyItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    auto lineEdit = new QLineEdit(parent);
    emit editingStarted();
    emit editorOpened(lineEdit);
    return lineEdit;
}

void MyItemDelegate::onCloseEditor()
{
    emit editingFinished();
}

MyTableView.h

#ifndef MYTABLEVIEW_H
#define MYTABLEVIEW_H

#include <QTableView>
#include <QDebug>
#include "myitemdelegate.h"

class MyTableView : public QTableView
{
    Q_OBJECT
public:
    explicit MyTableView(QWidget *parent = nullptr);

signals:

public slots:
};

#endif // MYTABLEVIEW_H

MyTableView.cpp

#include "mytableview.h"

MyTableView::MyTableView(QWidget *parent) : QTableView(parent)
{
    MyItemDelegate* delegate = new MyItemDelegate(this);
    QStandardItemModel* model = new QStandardItemModel(this);
    setItemDelegate(delegate);
    setModel(model);

    QList<QList<QStandardItem*>> items;
    for(int i = 0; i < 10; i++)
    {
        items << QList<QStandardItem*>();
        for (int j = 'A'; j < 'E'; j++)
            items[i] << new QStandardItem(QString("%1,%2").arg(i).arg(static_cast<char>(j)));
    }

    for (const auto& row : items)
        model->appendRow(row);

    connect(delegate, &MyItemDelegate::editingStarted, []() {
        qDebug() << "Editing started";
    });

    connect(delegate, &MyItemDelegate::editingFinished, []() {
        qDebug() << "Editing finished";
    });

    connect(delegate, &MyItemDelegate::editorOpened, [](const QWidget* editor) {
        auto lineEdit = qobject_cast<const QLineEdit*>(editor);
        connect(lineEdit, &QLineEdit::textChanged, [](const QString& text) {
            qDebug() << text;
        });
    });
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

Example output

1 Ответ

0 голосов
/ 02 июля 2019

Следующее решение может соответствовать вашим потребностям.Я только что определил новый сигнал внутри делегата и подключился к нему внутри класса, которому принадлежит делегат.

MyItemDelegate.h

#ifndef MYITEMDELEGATE_H
#define MYITEMDELEGATE_H

#include <QStyledItemDelegate>

class MyItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyItemDelegate(QObject* parent);

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

    virtual ~MyItemDelegate() = default;

signals:
    void valueChanged(const QString&);
};

#endif // MYITEMDELEGATE_H

MyItemDelegate.cpp

#include "myitemdelegate.h"
#include <QLineEdit>

MyItemDelegate::MyItemDelegate(QObject* parent) : QStyledItemDelegate(parent)
{
}

QWidget* MyItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    auto lineEdit = new QLineEdit(parent);
    connect(lineEdit, &QLineEdit::textChanged, this, &MyItemDelegate::valueChanged);
    return lineEdit;
}

MyTableView.cpp

#include "mytableview.h"
#include <QStandardItemModel>

MyTableView::MyTableView(QWidget *parent) : QTableView(parent)
{
    MyItemDelegate* delegate = new MyItemDelegate(this);
    QStandardItemModel* model = new QStandardItemModel(this);
    setItemDelegate(delegate);
    setModel(model);

    QList<QList<QStandardItem*>> items;
    for(int i = 0; i < 10; i++)
    {
        items << QList<QStandardItem*>();
        for (int j = 'A'; j < 'E'; j++)
            items[i] << new QStandardItem(QString("%1,%2").arg(i).arg(static_cast<char>(j)));
    }

    for (const auto& row : items)
        model->appendRow(row);

    connect(delegate, &MyItemDelegate::valueChanged, [](auto v) { qDebug() << v; });
}
...