8

Assuming I have a QTableWidgetItem item and I just wanna validate data that users enter. Example, users only enter a number into that item otherwise the program will show a warning dialog.

I also search on that document page but I didn’t find similar function with setValidator() function.

How can I use a validator for that QTableWidgetItem item?

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
Tan Viet
  • 1,983
  • 6
  • 25
  • 36

4 Answers4

9

Assuming what you really want is to have QValidate-able cells, you could populate the cell with a QLineEdit instance instead. Here's an example that uses QDoubleValidator, but any QValidator will work:

QLineEdit *edit = new QLineEdit(ui->myTable);
edit->setValidator(new QDoubleValidator(edit));
ui->myTable->setCellWidget(row, col, edit);

By default, QLineEdit will fill the cell and is drawn with a frame. To preserve the appearance of the table, you can turn the frame off by calling the following function a priori:

QLineEdit::setFrame(false);

One annoying thing about this solution is that you'll have to call

QWidget* QTableWidget::cellWidget(row, col) const

to subsequently access the QLineEdit instance in each cell, which means you'll have to cast the pointer to QLineEdit* also. (See qobject_cast()). It's a bit verbose but workable.

Terrabits
  • 997
  • 2
  • 15
  • 19
  • Nice workaround! Although the lineedit first cell (0, 0) is a bit misplaced. Every other cell looks great but the very first one seems to be too high, too left, too wide and too tall. – Uroc327 Oct 30 '14 at 11:11
4

I can think of two different ways you can handle this. There may be other solutions as well.

You could subclass the QTableWidgetItem and reimplement the setData function. If you pick up an invalid value, you can emit an error message.

You could subclass QStyledItemDelegate and either add a QValidator to the editor QWidget by reimplementing createEditor or reimplement the setModelData and examine the user input there. Once again, you can emit an error message if there's invalid data.

Check the documentation of each to see which would be more appropriate for your project.

QTableWidgetItem

QStyledItemDelegate

RobbieE
  • 4,280
  • 3
  • 22
  • 36
1

I use this solution where you have a QLineEdit in each cell. the validator is for scientific numbers (e.g. 2e-17)

for(int trow=0; trow <= 2; trow++ )
{
    for(int tcolumn=0; tcolumn <= 3; tcolumn++ )
    {
        QLineEdit * tableline = new QLineEdit;
        tableline->setValidator( new QDoubleValidator(0, 100, 2, this) );
        ui->tableWidget->setCellWidget ( trow, tcolumn,  tableline);
    }
MrMaavin
  • 11
  • 2
1

There's easy way to achieve this.

Just use one of the signals of QTableWidget - cellChanged(int,int);

QObject::connect(m_pTableWidget, SIGNAL(cellChanged(int,int)),
                         this, SLOT(OnTableWidgetCellChanged(int,int)));

Inside slot function (OnTableWidgetCellChanged(int row,int column)), use a switch case with column to validate each column seperately.

Get the input text from user of that particular column, and store as QString. Now convert that QString to int by passing the bool variable and check the status of bool variable. If its false, then user entered is not a valid number. example is shown as below :

bool bRetValue = false;
QString strValue = m_pTableWidget->item(row, VALUE_INDEX)->text();

int nValue = strValue.toInt(&bRetValue);
if(bRetValue == false)
{
  // show dialog to user to enter only numbers
}

If you want to convert to double or other type, simply convert the value to qvariant and can follow same procedure.

QVariant qvarValue(strValue);
double dVal = qvarValue.toDouble(&bRetValue);
if(bRetValue == false)
{
  // show dialog to user to enter only numbers
}

If you want to be more specific you can use QRegExp or QRegularExpression(Qt5)

QRegularExpression regexp("enter regx here",
                              QRegularExpression::CaseInsensitiveOption);
QRegularExpressionMatch regxmatch = regexp.match(strValue);
if (regxmatch.hasMatch())
{
    // your functionality
}
else
{
    // show dialog to user to enter only numbers
}