I fill the comboBox with items from database. When I try to add new item, erasing all items and adding them again, if db is being changed, I see these errors:
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
QSqlQuery::value: not positioned on a valid record created
terminate called after throwing an instance of 'std::invalid_argument' what(): stoi
21:41:04: Debugging of C:\Users\79107\Downloads\build-food_calculator-Desktop_Qt_6_2_2_MinGW_64_bit-Debug\debug\food_calculator.exe has finished with exit code 3.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
MainWindow::foodListConstructor();//function, that fills the comboBox
}
void MainWindow::foodListConstructor()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("food_list.db");
db.open();
QSqlQuery query("SELECT food_name FROM food", db);
if(query.isActive())
{
while(query.next())
{
ui->comboBox->addItem(query.value(0).toString());
}
}
}
void MainWindow::on_action_3_triggered()
{
AddFood af(this);// in this new window a user writes what he wants to add
af.setModal(true);
af.exec();
this->ui->comboBox->clear();
this->ui->comboBox->addItem("test");
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("food_list.db");
db.open();
QSqlQuery query1("SELECT food_name FROM food", db);
if(query1.isActive())
{
while(query1.next())
{
ui->comboBox->addItem(query1.value(0).toString());
}
}
How to make it work and not to dupliacte items (this happens if I remove "this->ui->comboBox->clear();")?
CodePudding user response:
If you call foodListConstructor()
multiple times, you are going to be calling addDatabase()
multiple times. Which is perfectly fine, per the documentation:
Adds a database to the list of database connections using the driver type and the connection name connectionName. If there already exists a database connection called connectionName, that connection is removed.
So it would seem you are simply seeing debug messages being output internally by Qt. This is not a real error, so just ignore it. Although, there is no point in adding the same database over and over. I would suggest just adding it once, and then use QSqlDatabase::database()
to access it when needed.
The QSqlQuery
error is pretty self-explanatory. You tried to read a field value when the query was not on an active record. Again, that appears like another internal debug message, not a real error. Per the documentation:
An invalid
QVariant
is returned if field index does not exist, if the query is inactive, or if the query is positioned on an invalid record.
Why are you getting an invalid QVariant
from an inactive SQL record? That I couldn't say. You will have to figure that out for yourself.
But it explains the final terminate
message, which is a real error. You are calling toString()
on an invalid QVariant
:
Calling QVariant::toString() on an unsupported variant returns an empty string.
Somewhere along the way, std::stoi()
is being called with a string that doesn't represent an integer value (ie, likely the empty string you are adding to the comboBox
), so it throws a std::invalid_argument
exception that you are not catching, which is escaping out of your app's main function, causing the C runtime to call std::terminate()
to exit the app.
Where is std::stoi()
being called? You need to search your code for that. Do you have some event handler hooked up to the comboBox
?
With that said, try something more like this:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("food_list.db");
foodListConstructor();
}
void MainWindow::foodListConstructor()
{
ui->comboBox->clear();
QSqlDatabase db = QSqlDatabase::database("QSQLITE");
QSqlQuery query("SELECT food_name FROM food", db);
while (query.next())
{
QVariant v = query.value(0);
if (v.isValid())
ui->comboBox->addItem(v.toString());
}
}
void MainWindow::on_action_3_triggered()
{
AddFood af(this);
af.setModal(true);
af.exec();
foodListConstructor();
}