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?

È stato utile?

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top