Solved How to apply validation on cells in a QTableWidget?
-
@SGaist said in How to apply validation on cells in a QTableWidget?:
QLineEdit
For 1 here is what I have so far:
void MainWindow::addSub(int row, int col) { auto *edit = new QLineEdit; QRegExp regExp("/^[^'\"]*$/"); auto *validator = new QRegExpValidator(regExp, this); edit->setValidator(validator); auto item = new QTableWidgetItem(); ui->tableWidget->setItem(row, col, item); } void MainWindow::addRow(int &last) { last = ui->tableWidget->rowCount(); ui->tableWidget->insertRow(last); addSub(last, 0); }
How do I actually connect the QLineEdit object called "edit" to the QTableWidget object?
-
@Guerrian
Hi
you cannot connect external QLineEdit.
You must do as in example and make delegate.
http://doc.qt.io/qt-5/qtwidgets-itemviews-spinboxdelegate-example.html
However, instead of spin box, you returns you LineEdit with validator ( as code is now)
in CreateEditor.
Its important to read about how delegates works.
http://doc.qt.io/qt-5/qstyleditemdelegate.html -
@mrjj Do I have to use a model / view based architecture (QTableView) to go down this path?
-
@Guerrian
no, it works the same via setItemDelegateForColumn and friends.
The *Widgets version are also views, but comes wrapped up with own internal model and
its meant for convenience.
However, in the long run, you might be more happy with *Views. -
To add to @mrjj, use QRegularExpression and not QRegExp, that one is deprecated.
-
When I add the delegate to the QTableWidget the cells disappear i.e. there is no text editor in the table. I assume this is because I have not implemented a paint method for the delegate. I do no know how to do this:
class TextDelegate : public QStyledItemDelegate { Q_OBJECT public: TextDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const override; void setEditorData(QWidget *editor, const QModelIndex &index) const override; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; TextDelegate::TextDelegate(QObject *parent): QStyledItemDelegate(parent) { } QWidget *TextDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QLineEdit *editor = new QLineEdit(parent); editor->setFrame(false); QRegularExpression regExp("/^[^'\"]*$/"); auto *validator = new QRegularExpressionValidator(regExp, parent); editor->setValidator(validator); return editor; } void TextDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); lineEdit->setText("test value"); } void TextDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { } void TextDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->tableWidget->setHorizontalHeaderLabels(QStringList() << tr("Name")); TextDelegate delegate; ui->tableWidget->setItemDelegate(&delegate); }
-
Hi
Do you mean when not in edit mode ? -
@mrjj I mean the cells have disappeared from the screen in all modes. There is nothing in the table except for the column and row text.
-
@Guerrian
Hi
There is a natural explanation to that.
You delegate runs out of scope and gets deleted. :)TextDelegate delegate; // local var, wont survive the constructor ui->tableWidget->setItemDelegate(&delegate);
do like this
ui->tableWidget->setItemDelegate(new TextDelegate(this));
and it will draw as expected.
-
@mrjj Nice one. I got further with this, but two problems still remain:
- The editor still allows quotes in the input.
- The text in the QTableWidget is not being updated when I leave the cell.
In the case of 2 I added a debug line, but the function doesn't get called:
void TextDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); QString value = lineEdit->text(); qDebug() << "value: " << value; model->setData(index, value, Qt::EditRole); }
This is what my createEditor function looks like now:
QWidget *TextDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const { QLineEdit *lineEdit = new QLineEdit(parent); lineEdit->setFrame(false); QRegularExpression regExp("/^[^'\"]*$/"); QRegularExpressionValidator *validator = new QRegularExpressionValidator(regExp, parent); lineEdit->setValidator(validator); QSignalMapper *mapper = new QSignalMapper(lineEdit); mapper->setMapping(lineEdit, 0); QObject::connect(lineEdit, SIGNAL(textEdited(bool)), mapper, SLOT(map())); QObject::connect(mapper, SIGNAL(mapped(QWidget *)), this, SIGNAL(commitData(QWidget *))); return lineEdit; }
I'm not sure about the id parameter in the mapping.
-
What are you doing with that QSignalMapper ?
By the way, use qobject_cast and not static_case with QObject based classes.
-
@SGaist said in How to apply validation on cells in a QTableWidget?:
What are you doing with that QSignalMapper ?
I'm not sure, this is all new to me.
By the way, use qobject_cast and not static_case with QObject based classes.
Thanks
-
In that case, don't use it. Follow the SpinBox Delegate example as suggested and just replace the QSpinBox editor by the QLineEdit + QRegularExpressionValidator. And IIRC, you even just have to re-implement only the createEditor method
-
@SGaist
OK, but why is my setModelData not being executed? -
Did you remove the mapper ?
Are you sure that your editor is used in the first place ? -
@SGaist said in How to apply validation on cells in a QTableWidget?:
Did you remove the mapper ?
Yes.
Are you sure that your editor is used in the first place ?
Well yes, because createEditor is called when I click on the QTableWidget to edit a cell.
-
Can you show your current call and a minimal QTableWidget setup that uses it ?
-
@Guerrian said in How to apply validation on cells in a QTableWidget?:
The editor still allows quotes in the input.
That's because your regular expression is wrongly escaped, raw string literals are a blessing in cases like this one:
QRegularExpression regExp(QStringLiteral(R"**(^[^'\"]*$)**"));
The text in the QTableWidget is not being updated when I leave the cell.
Make sure you use
override
in the declaration ofsetModelData
to avoid the usual pitfall. -
@VRonin
After I corrected the regular expression, my code worked.