QTableView displays correct rows and columns but no data in cells.
-
Hi @JonB ,
model.lastError().isValid()) returns false, so it seems there are no errors. (BTW, how do you make that inline code pink?) When I swap the two lines of code as you have suggested, I still get the same result.There are definitely 4 rows of data in the table; see the SSMS screenshot below:
The data also seems to pull correctly into the model. I've modified the code like so:
//new code model = new QSqlQueryModel(this); //Without this line code crashes model->setQuery("SELECT * FROM Batches"); ui->tableView->setModel(model); qDebug() << "LastError is valid?: " << model->lastError().isValid(); qDebug() << "First column output: "; for (int i = 0; i < model->rowCount(); i++) { qDebug() << model->data(model->index(i, 0)).toInt(); }
and this is the output I get in QDebug:
Connection opened successfully!
LastError is valid?: false
First column output:
1
2
3
4
Connection closed successfully! -
Hi @JonB ,
model.lastError().isValid()) returns false, so it seems there are no errors. (BTW, how do you make that inline code pink?) When I swap the two lines of code as you have suggested, I still get the same result.There are definitely 4 rows of data in the table; see the SSMS screenshot below:
The data also seems to pull correctly into the model. I've modified the code like so:
//new code model = new QSqlQueryModel(this); //Without this line code crashes model->setQuery("SELECT * FROM Batches"); ui->tableView->setModel(model); qDebug() << "LastError is valid?: " << model->lastError().isValid(); qDebug() << "First column output: "; for (int i = 0; i < model->rowCount(); i++) { qDebug() << model->data(model->index(i, 0)).toInt(); }
and this is the output I get in QDebug:
Connection opened successfully!
LastError is valid?: false
First column output:
1
2
3
4
Connection closed successfully!@donnpie
OK, at this point you seem to be in inexplicable territory, from what I have seen & others we're spotting anything obvious. You seem to know what you're doing in your code/answers, so that's good!The one bit I don't know about is your
ui->tableView
. I don't do any Creator design-time stuff, make absolutely sure there isn't something "funny" about that table view.So, if it were me, it's time to start divide-and-conquer. Split it up till you spot something, e.g.
-
Move it to a standalone project, with the bare-minimum code. Get rid of all the extraneous lines that clutter up the code, so you can paste entirety here if you have to.
-
Replace the SQL model with a
QStandardItemModel
, populated by hand. That tells you whether it's a SQL thing or a model thing. -
Replace the
QTableView
with aQComboBox
tied to one column, That tells you whether it's a table view thing.
By the time you've done the above, it must be working...!
BTW, if you are able to sub-class the model you're using, you can override its
data()
method, and there you should be seeing all the calls the view is making to display stuff and what is being returned from the model.(BTW, how do you make that inline code pink?)
There's no pinko in what I write, only red! backtick-word-backtick ==
word
. -
-
When and why are you closing the connection to the database ?
-
OK, so I've created a QStandardItemModel and passed that to the QTableView, and things are working well. I can see the text in the body of the table. My QTableView object is bog-standard - I did not change any of its properties.
I changed the query to return a single column and passed it to a new QListView (below the table). As you can see, the listview came up blank. When I hover my mouse over the listview, the rows shade blue, which is telling me that either there are empty rows there or the font of the rows is the same colour as the background. However I do not think it is a font colour issue, because when I click on a row, the backround colour changes to blue, but the text is still not visible. So at this stage I think we can rule out the tableview. It looks like there is an issue with my query/model. For some reason, the model ends up with empty rows.
I thought maybe it had something to do with the fact that I created the SQLQueryModel on the heap, but that does not seem to be the case since the stdItemModel was also created on the heap and seems to be working just fine.
My only working theory at this stage: Maybe there is a timing issue and the model is passed to the ui before the results are properly populated in the model, so effectively I'm passing an empty model to the ui.
Here is the code I used:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); //SQL code //Set up the connection QString dbName = "Plants"; //Name of the database QString serverName = "DESKTOP-F7RC79B\\SQLEXPRESS"; //Name of host machine and server db = QSqlDatabase::addDatabase("QODBC"); //Specify the driver db.setConnectOptions(); //AFAIK this sets up a default connection //Connection string: QString conString = QString("DRIVER={SQL Server};SERVER=%1;DATABASE=%2;" "Trusted_Connection=Yes;").arg(serverName).arg(dbName); db.setDatabaseName(conString); //Pass connection string to db object if (db.open()) { qDebug() << "Connection opened successfully!"; //SQL query model model = new QSqlQueryModel(this); model->setQuery("SELECT BatchID FROM Batches"); //Changed query to return single column //ui->tableView->setModel(model); ui->listView->setModel(model); //test code: pass the model to the listview qDebug() << "LastError is valid?: " << model->lastError().isValid(); qDebug() << "First column output: "; for (int i = 0; i < model->rowCount(); i++) { qDebug() << model->data(model->index(i, 0)).toInt(); } } else { qDebug() << "Connection error: " << db.lastError().text(); } db.close(); qDebug() << "Connection closed successfully!"; //Create a std item model by hand QStandardItemModel *stdModel = new QStandardItemModel(this); int rowCount = 3; int colCount = 3; stdModel->setRowCount(rowCount); stdModel->setColumnCount(colCount); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { QStandardItem *stdItem = new QStandardItem(); stdItem->setText(QString::number(i+j)); stdModel->setItem(i, j, stdItem); } } ui->tableView->setModel(stdModel); //Pass the stdModel to the tableview }
-
On second thought, the model can't be empty because I am able to successfully output the data to qDebug. I've changed the sequence of the code to print the data to qDebug first and then to listview. It prints to qDebug but still does not show up in the listview. So the model does have data in it, but the data does not show up in the listview.
-
I thought maybe it is a machine issue, so I tried it on a different machine with a different database. I still get the same results: the header text shows up but the body text is missing. Could it be a Windows issue? The first machine is running Windows 10 Pro and the second machine is running Windows 10 Enterprise.
Other system information:
Both machines are 64-bit. Both machines run Qt Creator 4.9.1 (Based on Qt 5.12.3 (MSVC 2017, 32 bit), Built on May 26 2019 21:17:08, From revision 168e91b618). Compilers for both machines are MinGW 7.3.0, 32-bit. Qt versions for both machines are 5.13.0. First machine is running SSMS v17.8.1 and second machine is running SSMS v18.1. -
Again: why are you closing the connection to the database ?
-
Again: why are you closing the connection to the database ?
Hi @SGaist, I figured I was done with the connection, so no further need for it.
Holy crap, I just commented out
db.close();
and it worked!!! Thank you very much @SGaist.Although this fixes the problem I don't understand why. Would you mind explaining why the db connection should remain open, and when to close it?
-
So your model can grab more data on demand. If you use a QSqlTableModel, it won't load 100% of the table content in one go for exemple.
-
Again: why are you closing the connection to the database ?
Hi @SGaist, I figured I was done with the connection, so no further need for it.
Holy crap, I just commented out
db.close();
and it worked!!! Thank you very much @SGaist.Although this fixes the problem I don't understand why. Would you mind explaining why the db connection should remain open, and when to close it?