Qt - signal for when QListWidget row is edited?

2019-02-15 23:12发布

问题:

I am working in Qt4.7, and I have a QListWidget in my dialog. I have a QString that needs to match the current text in the row of this widget (the individual rows are editable). Looking at the signals associated with QListWidget, there seem to be signals for when a different index is selected but none for when the text of a the currently selected row changes. I thought currentTextChanged(QString) would do it, but it didn't. I also thought to try to connect each individual row to something, but QListWidgetItem doesn't have any built-in signals. Does anyone know of a way to do this? Thanks!

回答1:

I guess you need to look into the following signal:

void QListWidget::itemChanged(QListWidgetItem * item)

But be careful because it's being sent every time some property of item changed, not only text. I remember when we ran into the problem once when we changed item colors and got tons of false positive slots called because of that. If you need more fine tuning I guess it's better to write model/view classes yourself and not rely on QListWidget.



回答2:

At first it seems like QListWidget::itemChanged is the way to go, but soon you run into a problem: the signal is sent for everything - inserts, changing colors, checking boxes, and anything else that "changes" the item! Predelnik pointed that out in his answer. Some people have tried to put in flags and filter everywhere by intercepting various signals to find out if editing was the actual event. It gets very messy.

There is also QAbstractItemModel::dataChanged , which would seem like a good solution. It even has a parameter "const QVector& lstRoles" so you could scan for Qt::EditRole and see if it was really edited. Alas, there's a catch - it gets called for everything just like QListWidget::itemChanged and unfortunately, for QListWidget anyway, the roles parameter is always empty when it's called (I tried it). So much for that idea...

Fortunately, there's still hope... This solution does the trick! :

http://falsinsoft.blogspot.com/2013/11/qlistwidget-and-item-edit-event.html

He uses QAbstractItemDelegate::closeEditor, but I prefer using QAbstractItemDelegate::commitData.

So make a connect like so...

connect(ui.pLstItems->itemDelegate(), &QAbstractItemDelegate::commitData, this, &MyWidget::OnLstItemsCommitData);

Then implement the slot like this...

void MyWidget::OnLstItemsCommitData(QWidget* pLineEdit)
{
        QString strNewText = reinterpret_cast<QLineEdit*>(pLineEdit)->text();
    int nRow = ui.pLstItems->currentRow();
        // do whatever you need here....
}

Now you have a slot that gets called only when the list item's text has been edited!