确定QTableView是否具有打开的编辑器

确定QTableView是否具有打开的编辑器,qt,qtableview,Qt,Qtableview,有没有办法确定当前单元格中的QTableView是否有打开的编辑器?我需要处理以下情况: 用户双击单元格并编辑数据,但使单元格处于“编辑”状态 在UI的另一部分,将执行一个操作,以更改基础模型的选定行 回到我的视图,我想确定新选择的行是否与打开的行相同。如果没有,我需要采取行动。(提示用户?自动提交?还原?) 我看到了如何获取当前项,并且可以获取该项上的委托,但是我没有看到我希望找到的任何isEditMode()属性 有人能给我指出正确的方向吗?对您的委托进行子类化,以便它包含一个访问器,在

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

  • 用户双击单元格并编辑数据,但使单元格处于“编辑”状态
  • 在UI的另一部分,将执行一个操作,以更改基础模型的选定行
  • 回到我的视图,我想确定新选择的行是否与打开的行相同。如果没有,我需要采取行动。(提示用户?自动提交?还原?)
我看到了如何获取当前项,并且可以获取该项上的委托,但是我没有看到我希望找到的任何
isEditMode()
属性


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

对您的委托进行子类化,以便它包含一个访问器,在编辑时告诉您:

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; }

然后,您可以检查代理,看看发生了什么。或者和/或如果您不喜欢可变的,您可以发出信号,以便知道代理处于什么状态。

连接到基础模型数据更改信号

void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )
您可以检查数据已更改的单元格是否与currentIndex相同

QModelIndex QAbstractItemView::currentIndex () const
您无法知道当前单元格是否有打开的编辑器,但可以检查视图是否位于QAbstractItemView::EditingState中

State QAbstractItemView::state () const

它应该足以满足您的需要。

您可以将
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的指针并使用它。

只需检查

State QAbstractItemView::state () const


这里有一个想法,它甚至有助于在编辑开始之前获得编辑/组合小部件

只需发出一个信号并在主窗口中使用它。。。这是我在编辑之前在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;
}
并在主窗口中声明一个函数以接收信号

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

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

EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
    //yep, ur editing bro
}
EditWidget*EditWidget=qobject_cast(tableView->indexWidget(tableView->currentIndex());
如果(编辑小部件)
{
//是的,你的编辑兄弟
}

请注意,我想你的意思是可变的,而不是易变的。@Caleb-你说得对。更改--感谢您指出这一点。正如Florian Kusche在其回答中指出的那样,这不起作用,因为只有在提交编辑时才调用setModelData(),而在取消编辑时才调用setModelData()。很好。只是一些评论:最好使用可变int而不是int*。另外,不需要在提供的解决方案中重新实现setEditorData()和setModelData(),因此为了清晰起见,您可以省略它们。是的,您是对的。可变整数会更好一些。我不确定它在该状态下是否足以确定它是用于当前单元格的
ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget);
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt);
ui->tableWidget->setItemDelegateForColumn(0, cbid);
EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
    //yep, ur editing bro
}