Determinare se QTableView ha un editore aperto
-
26-09-2019 - |
Domanda
C'è un modo per determinare se un QTableView
ha un editore aperto nella cella corrente? Ho bisogno di gestire la seguente situazione:
- Un utente fa doppio clic su una cella e modifica i dati, ma lascia la cellula nello stato "modifica" .
- In un'altra parte della UI, viene intrapresa un'azione che cambia la riga selezionata del modello sottostante.
- Ritornare mio punto di vista, voglio per determinare se la riga appena selezionata è la stessa della fila aperta. In caso contrario, ho bisogno di prendere un'azione. (Richiedere all'utente? Commettere automaticamente? Ripristina?)
vedo come ottenere l'elemento corrente, e può ottenere il delegato su tale elemento, ma non vedo alcuna proprietà isEditMode()
speravo di trovare.
Qualcuno può punto nella giusta direzione me?
Soluzione
sottoclasse il delegato in modo che esso include una funzione di accesso che ti dice quando è la modifica:
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; }
Poi si può solo controllare il delegato per vedere cosa sta succedendo. In alternativa e / o se non ti piace il mutable
, è possibile emettere segnali in modo da sapere in quale stato il delegato è in.
Altri suggerimenti
Basta selezionare se il valore di ritorno di
State QAbstractItemView::state () const
è
QTableView::EditingState
Collega al modello sottostante segnale DataChanged
void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )
È possibile controllare se la cella in cui i dati è cambiato è lo stesso che il currentIndex
QModelIndex QAbstractItemView::currentIndex () const
Non è possibile sapere se la cella corrente ha avuto un editor di scala, ma può controllare se la vista è in QAbstractItemView :: EditingState
State QAbstractItemView::state () const
Dovrebbe essere sufficiente per fare quello che vuoi.
È possibile creare una sottoclasse QTableView
al fine di essere in grado di accedere alla funzione state()
, che è purtroppo protetto. Tuttavia, non ho provato questo.
Se si dispone già di una sottoclasse QStyledItemDelegate
, è possibile utilizzarlo per monitorare se un editore è aperto. Tuttavia, non si può semplicemente utilizzare setEditorData
/ setModelData
, perché setModelData
non sarà chiamato, quando l'utente annulla la modifica. Invece, è possibile monitorare la creazione e la distruzione di l'editor in sé.
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 );
};
Implementazione:
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)--;
}
In alcuni casi, ad esempio quando si sposta al successivo elemento nella struttura con i tasti cursore, Qt creerà il nuovo editor prima e poi distruggere quello vecchio. Quindi, m_editorCount
deve essere un intero invece di un bool.
Purtroppo, createEditor()
è una funzione const
. Di conseguenza, non è possibile creare un int
membri. Invece, creare un puntatore ad un int
e l'uso che.
Se si conosce l'indice della voce in fase di modifica, è possibile chiamare indexWidget()
e tentare di lanciarlo. Se è valido, non solo si sa sta modificando, ma avete anche il vostro editor widget di portata di mano.
EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
//yep, ur editing bro
}
Ecco un'idea, la sua anche utile per ottenere il widget di modificare / combo prima della modifica ha inizio ...
solo emette un segnale e consumare nel MainWindow ... questo è quello che ho usato uno per ottenere casella combinata in QTableWidget prima di modificare ...
prima creare un segnale in ComoBoxItemDelegate ...
signals:
void OnComboEdit(QComboBox* pCombo) const;
poi emettere il segnale nel metodo 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;
}
e nelle MainWindow dichiarare una funzione per ricevere il singal ...
void MainWindow::OnComboEidt(QComboBox *pCB) const
{
qDebug() << "Combo Eidt Singal Received";
}
Poi finalmente nel costruttore di MainWindow collegarlo ...
ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget);
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt);
ui->tableWidget->setItemDelegateForColumn(0, cbid);