判断QTableView是否有打开的编辑器

发布于 2024-09-13 23:09:07 字数 316 浏览 3 评论 0原文

有没有办法确定 QTableView 在当前单元格中是否有打开的编辑器?我需要处理以下情况:

  • 用户双击单元格并编辑数据,但使单元格处于“编辑”状态
  • 在 UI 的另一部分,将执行更改底层模型的选定行的操作。
  • 回到我的观点,我想确定新选择的行是否与打开的行相同。如果没有,我需要采取行动。 (提示用户?自动提交?恢复?)

我了解了如何获取当前项目,并且可以获取该项目的委托,但我没有看到任何我希望的 isEditMode() 属性去寻找。

有人能指出我正确的方向吗?

Is there any way to determine if a QTableView has an open editor in the current cell? I need to handle the following situation:

  • A user double-clicks a cell and edits the data, but leaves the cell in the "edit" state.
  • On another part of the UI, an action is taken that changes the selected row of the underlying model.
  • Back on my view, I want to determine if the newly selected row is the same as the open row. If not, I need to take an action. (Prompt the user? Commit automatically? Revert?)

I see how to get the current item, and can get the delegate on that item, but I don't see any isEditMode() property I was hoping to find.

Can someone point me in the right direction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

情何以堪。 2024-09-20 23:09:07

只需检查返回值是否

State QAbstractItemView::state () const

QTableView::EditingState

Just check whether the return value of

State QAbstractItemView::state () const

is

QTableView::EditingState
明月松间行 2024-09-20 23:09:07

您可以子类化QTableView,以便能够访问state() 函数,不幸的是,该函数受到保护。但是,我没有尝试这样做。

如果您已有 QStyledItemDelegate 子类,则可以使用它来跟踪编辑器当前是否打开。但是,您不能只使用 setEditorData/setModelData,因为当用户取消编辑时,不会调用 setModelData。相反,您可以跟踪编辑器本身的创建和销毁。

class MyItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyItemDelegate( QObject* parent = nullptr );
    ~MyItemDelegate();

    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;

    bool isEditorOpen() const   { return *m_editorCount > 0; }

protected:
    int* m_editorCount;

protected slots:
    void onEditorDestroyed( QObject* obj );
};

实现:

MyItemDelegate::MyItemDelegate( QObject* parent ) :
    QStyledItemDelegate( parent )
{
    m_editorCount = new int;
    *m_editorCount = 0;
}

MyItemDelegate::~MyItemDelegate()
{
    delete m_editorCount;
}

QWidget* MyItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    // create an editor, can be changed as needed
    QWidget* editor = QStyledItemDelegate::createEditor( parent, option, index );

    connect( editor, SIGNAL(destroyed(QObject*)), SLOT(onEditorDestroyed(QObject*)));
    printf( "editor %p created\n", (void*) editor );
    (*m_editorCount)++;

    return editor;
}

void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    ...
}

void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    ...
}

void MyItemDelegate::onEditorDestroyed( QObject* obj )
{
    printf( "editor %p destroyed\n", (void*) obj );
    (*m_editorCount)--;
}

在某些情况下,例如当使用光标键移动到树中的下一项时,Qt 将首先创建新编辑器,然后销毁旧编辑器。因此,m_editorCount 必须是整数而不是布尔值。

不幸的是,createEditor() 是一个 const 函数。因此,您无法创建 int 成员。相反,创建一个指向 int 的指针并使用它。

You can subclass QTableView in order to be able to access the state() function, which is unfortunately protected. However, I did not try that.

If you already have an QStyledItemDelegate subclass, you can use it to track whether an editor is currently open. However, you can't just use setEditorData/setModelData, because setModelData won't be called, when the user cancels editing. Instead, you can track the creation and destruction of the editor itself.

class MyItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    MyItemDelegate( QObject* parent = nullptr );
    ~MyItemDelegate();

    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;

    bool isEditorOpen() const   { return *m_editorCount > 0; }

protected:
    int* m_editorCount;

protected slots:
    void onEditorDestroyed( QObject* obj );
};

Implementation:

MyItemDelegate::MyItemDelegate( QObject* parent ) :
    QStyledItemDelegate( parent )
{
    m_editorCount = new int;
    *m_editorCount = 0;
}

MyItemDelegate::~MyItemDelegate()
{
    delete m_editorCount;
}

QWidget* MyItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    // create an editor, can be changed as needed
    QWidget* editor = QStyledItemDelegate::createEditor( parent, option, index );

    connect( editor, SIGNAL(destroyed(QObject*)), SLOT(onEditorDestroyed(QObject*)));
    printf( "editor %p created\n", (void*) editor );
    (*m_editorCount)++;

    return editor;
}

void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    ...
}

void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    ...
}

void MyItemDelegate::onEditorDestroyed( QObject* obj )
{
    printf( "editor %p destroyed\n", (void*) obj );
    (*m_editorCount)--;
}

On some occasions, e.g. when moving to the next item in the tree using the cursor keys, Qt will create the new editor first and then destroy the old one. Hence, m_editorCount must be an integer instead of a bool.

Unfortunately, createEditor() is a const function. Therefore, you cannot create an int-member. Instead, create a pointer to an int and use that.

妳是的陽光 2024-09-20 23:09:07

连接到底层模型 dataChanged 信号

void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )

您可以检查数据已更改的单元格是否与 currentIndex 相同

QModelIndex QAbstractItemView::currentIndex () const

您无法知道当前单元格是否直接打开编辑器,但可以检查视图是否在 QAbstractItemView::EditingState 中

State QAbstractItemView::state () const

它应该是足够做你想做的事。

Connect to underlying model dataChanged signal

void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )

You can check if the cell where data has changed is the same than the currentIndex

QModelIndex QAbstractItemView::currentIndex () const

You cannot know if the current cell had an open editor straight, but can check if the view is in QAbstractItemView::EditingState

State QAbstractItemView::state () const

It should be enough to do what you want.

梦巷 2024-09-20 23:09:07

对您的委托进行子类化,使其包含一个访问器来告诉您何时进行编辑:

void MyDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const {
    // _isEditing  will have to be mutable because this method is const
    _isEditing = true; 
    QStyledItemDelegate::setEditorData(editor, index);
}

void MyDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const {
    QStyledItemDelegate::setModelData(editor, model, index);
    _isEditing = false;
}

bool MyDelegate::isEditing() const { return _isEditing; }

然后您只需检查委托即可了解发生了什么。或者和/或如果您不喜欢可变的,您可以发出信号,以便您知道委托处于什么状态。

Subclass your delegate so that it includes an accessor that tells you when it's editing:

void MyDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const {
    // _isEditing  will have to be mutable because this method is const
    _isEditing = true; 
    QStyledItemDelegate::setEditorData(editor, index);
}

void MyDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const {
    QStyledItemDelegate::setModelData(editor, model, index);
    _isEditing = false;
}

bool MyDelegate::isEditing() const { return _isEditing; }

Then you can just check the delegate to see what's going on. Alternatively and/or if you don't like the mutable, you can emit signals so you know what state the delegate is in.

烈酒灼喉 2024-09-20 23:09:07

如果您知道正在编辑的项目的索引,则可以调用 indexWidget() 并尝试强制转换它。如果它有效,您不仅知道您正在编辑,而且还可以方便地使用编辑器小部件。

EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
    //yep, ur editing bro
}

If you know the index of the item being edited, you can call indexWidget() and attempt to cast it. If it's valid, you not only know you're editing, but you also have your editor widget handy.

EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
    //yep, ur editing bro
}
墨小墨 2024-09-20 23:09:07

这是一个想法,在编辑开始之前获取编辑/组合小部件甚至很有帮助...

只需发出一个信号并在主窗口中使用它...这就是我在编辑之前在 QTableWidget 中获取组合框的方法。 ..

首先在 ComoBoxItemDelegate 中创建一个信号...

signals:
   void OnComboEdit(QComboBox* pCombo) const;

然后在 createEditor 方法中发出信号...

QWidget* ComboBoxItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    // Create the combobox and populate it
    QComboBox* cb = new QComboBox(parent);
    emit OnComboEdit(cb);
    return cb;
}

并在 MainWindow 中声明一个函数来接收信号...

void MainWindow::OnComboEidt(QComboBox *pCB) const
{
    qDebug() << "Combo Eidt Singal Received";
}

然后最后在 MainWindow 的构造函数中连接它...

ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget);
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt);
ui->tableWidget->setItemDelegateForColumn(0, cbid);

Here is an idea, its even helpful to get the edit/combo widget before the edit begins...

just emit a signal and consume it in the mainwindow... this is what I used one to get combo box in QTableWidget before editing...

first create a signal in ComoBoxItemDelegate...

signals:
   void OnComboEdit(QComboBox* pCombo) const;

then emit the signal in the createEditor method...

QWidget* ComboBoxItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    // Create the combobox and populate it
    QComboBox* cb = new QComboBox(parent);
    emit OnComboEdit(cb);
    return cb;
}

and in the MainWindow declare a function to receive the singal...

void MainWindow::OnComboEidt(QComboBox *pCB) const
{
    qDebug() << "Combo Eidt Singal Received";
}

Then finally in the constructor of MainWindow connect it...

ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget);
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt);
ui->tableWidget->setItemDelegateForColumn(0, cbid);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文