Combobox in Qtableview
-
@n-2204 said in Combobox in Qtableview:
connect(ui.tableView->model(), SIGNAL(rowsInserted), ui.tableView_2->model(), SLOT(changedvalue()));
This is wrong - again: use the new signal/slot syntax to catch such errors on compile time. And if you don't want then watch the output to stdout during debugging!
-
@Christian-Ehrlicher
I, and you, have repeatedly advised @n-2204 to change from the old macros to the new style, and provided the necessary links (e.g. https://forum.qt.io/topic/126193/spinbox-input-add-rows, I think we posted 4 times there to this effect). Precisely because the user keeps getting the connections wrong. It seems the user is not interested in making the effort to change their ways, and prefers to make the same mistakes and keep posting for others to sort out.... -
-
but signal/slot should work for both the ways
It does but in case you make a mistake the new syntax lets you know straight away when you try to compile and it's not just a warning in the console while the program runs.
Also the new connection is fasterthere is change in column 1 row values and @VRonin you told to use signal rowinserted() ?
In that case you would use the conveniently named
dataChanged
signalvoid tool::changedvalue()
please do no rebuild all the widgets everytime something changes.
setIndexWidget
is already super inefficient, if you keep recreating them your program will probably stutter a lot -
So when i am passing my values in a Qstring that time its coming in combobox but same when i try using table1 column1 rows value that time only last row value is adding in Combobox values looks like all values not appending
Where need to make changes?connect(ui.tableView->model(), &QAbstractItemModel::dataChanged, this, &Gearcycle_model::changedvalue); void tool::changedvalue() { QAbstractItemModel* table1 = ui.tableView->model(); QAbstractItemModel* table2 = ui.tableView_2->model(); for (int i = 0, maxI = table2->rowCount();i <= maxI;++i)//combobox in table2 col1 { for (int r = 0, maxI = table1->rowCount();r < maxI;++r)//getvalue fromtable1 { QComboBox* combo = new QComboBox(); //QString list1[10] = { table1->data(table1->index(r, 0)).toString() };//store value in list QString list1[4] = { "input 1","input 2","input3","input 4" }; qDebug() << "table index" << r; for (int j = 0; j < 3; j++) { combo->addItem(list1[j]); qDebug() << "combox values" << list1[j];//pass list to combobox qDebug() << "list j=" << j; } ui.tableView_2->setIndexWidget(ui.tableView_2->model()->index(i, 1), combo); qDebug() << "row value i=" << i; } } }
-
@n-2204 said in Combobox in Qtableview:
So when i am passing my values in a Qstring that time its coming in combobox but same when i try using table1 column1 rows value that time only last row value is adding in Combobox values looks like all values not appending
Where need to make changes?connect(ui.tableView->model(), &QAbstractItemModel::dataChanged, this, &Gearcycle_model::changedvalue); void tool::changedvalue() { QAbstractItemModel* table1 = ui.tableView->model(); QAbstractItemModel* table2 = ui.tableView_2->model(); for (int i = 0, maxI = table2->rowCount();i <= maxI;++i)//combobox in table2 col1 { for (int r = 0, maxI = table1->rowCount();r < maxI;++r)//getvalue fromtable1 { QComboBox* combo = new QComboBox(); //QString list1[10] = { table1->data(table1->index(r, 0)).toString() };//store value in list
when passing this that time only last row value is coming in combobox
QString list1[4] = { "input 1","input 2","input3","input 4" };
this is working when i am passing QString list1[4] = { "input 1","input 2","input3","input 4" }; in combobox
for (int j = 0; j < 3; j++) { combo->addItem(list1[j]); qDebug() << "combox values" << list1[j];//pass list to combobox qDebug() << "list j=" << j; } ui.tableView_2->setIndexWidget(ui.tableView_2->model()->index(i, 1), combo); qDebug() << "row value i=" << i; } } }
yes, looks like some small change will be needed during addItem in combobox
-
ya it works thankyou.
void tool::rowvalue1() { QAbstractItemModel* table1 = ui.tableView->model(); QAbstractItemModel* table2 = ui.tableView_2->model(); for (int i = 0, maxI = table2->rowCount();i < maxI;++i)//combobox in table2 col1 { QComboBox* combo = new QComboBox(); combo->setDuplicatesEnabled(false); for (int r = 0, maxI = table1->rowCount();r < maxI;++r)//getvalue fromtable1 { QString list1[10] = { table1->data(table1->index(r, 0)).toString() };//store value in list for (int j = 0; j < 1; ++j) {
--using uniqueSet trying to add only unique values(no duplicate values) in Combobox but its not working is this correct way ? or any other way to do this ?
QSet<QString> uniqueSet; if (!uniqueSet.contains(list1[j]))//add only unique values in combobox { uniqueSet.insert(list1[j]); combo->addItem(list1[j]); //add list to combobox qDebug() << " values " << list1[j]; } } ui.tableView_2->setIndexWidget(table2->index(i, 1), combo); } } }
-
thanks for your answers
but what i shared i working code
and now i asked -
using uniqueSet trying to add only unique values(no duplicate values) in Combobox but this way not working is this correct way ? or any other way to do this ?this it might be very simple for you or you are expert but i am new C++ and Qt so i am having so many doubts may be silly.
Thanks -
@n-2204 said in Combobox in Qtableview:
no its 10
j<10No, the code you pasted reads:
for (int j = 0; j < 1; ++j)
That's
1
, not10
. Or are you saying you want help to fix your code but you don't paste the actual code you want help with?using uniqueSet trying to add only unique values(no duplicate values) in Combobox but this way not working
If your pasted code is to be believed, you seem to declare
QSet<QString> uniqueSet;
inside thej
loop.QSet<QString> uniqueSet; if (!uniqueSet.contains(list1[j]))//add only unique values in combobox
This will always be true.
uniqueSet
is always empty. -
Hi
- any other way ?
Well your idea with QSet<QString> uniqueSet; was fine, but the logic/location was not right
and i think QStringList might be easier.so this would do it. ( i assume you want a combo on each row in table 2 with same non-dub values in the combo)
QAbstractItemModel *table1 = ui->tableView->model(); QAbstractItemModel *table2 = ui->tableView_2->model(); QStringList guesslist; for (int r = 0, maxI = table1->rowCount(); r < maxI; ++r) { //for all value rows guesslist.append( table1->data(table1->index(r, 0)).toString() );//store value in stringlist } guesslist.removeDuplicates(); // strip dubs for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i) { //for all rows QComboBox *combo = new QComboBox(); // make combo combo->addItems(guesslist); //add list to combobox ui->tableView_2->setIndexWidget(table2->index(i, 1), combo);// add combo }
But a word of warning. If you have many rows then setIndexWidget can become quite heavy for
smaller devices and the app might lag. The cure is using a delegate as fully shown here ( thx VRonin :)https://forum.qt.io/topic/125906/qtableview-combobox-in-columns/10
This also has the benefit that you don't need to copy anything around. its using the values directly. always updated.
-
QStringList might be easier
guesslist.removeDuplicates(); // strip dubsOk Thanks!! but still looks like empty row value is coming in Combobox
if you have many rows then setIndexWidget can become quite heavy for
smaller devices and the app might lagI am having 6-7 rows in my table
I'm not using delegate as I need to read index, selection and apply some condition based on Combobox values in other columns ...,for some further req.
Thanks
-
Hi
- Ok Thanks!! but still looks like empty row value is coming in Combobox
Yes we add empty ones too but you can just dont do that.
for (int r = 0, maxI = table1->rowCount(); r < maxI; ++r) { //for all value rows QString str = table1->data(table1->index(r, 0)).toString(); if ( ! str.IsEmpty() ) guesslist.append( str );//store value in stringlist }
-
@mrjj said in Combobox in Qtableview:
for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i) { //for all rows
QComboBox *combo = new QComboBox(); // make combo
combo->addItems(guesslist); //add list to combobox
ui->tableView_2->setIndexWidget(table2->index(i, 1), combo);// add combo
}Slight tweak to avoid recreating the combobox every time:
for (int i = 0, maxI = table2->rowCount(); i < maxI; ++i) { //for all rows const QModelIndex idx = table2->index(i, 1); QComboBox *combo = qobject_cast<QComboBox*>(ui->tableView_2->indexWidget(idx)); if(!combo){ combo = new QComboBox(); // make combo ui->tableView_2->setIndexWidget(idx , combo);// add combo } combo->model()->removeRows(0,combo->count(),combo->rootModelIndex()); combo->addItems(guesslist); //add list to combobox }
@n-2204 said in Combobox in Qtableview:
I'm not using delegate as I need to read index, selection and apply some condition based on Combobox values in other columns
You can do that with delegates too. Probably even easier.
-
@VRonin @mrjj
1.
Actually when I'm using both the ways to add values in Combobox
one thing happening ,if I added some values in column0 table1 then select in combobox and again adding values in table1 Column0 that time combobox selection go awayI am using dataChanged() signal
connect(ui.tableView->model(), &QAbstractItemModel::dataChanged, this,
&tool::rowvalue1);
Is it because of this signal ? how can i prevent this ??- As I'm using SLOT::rowvalue1() to add combobox in Qtableview
now how can i take index() of combobox as there is SIGNAL::QComboBox::currentIndexChanged, , so again I need to write SLOT for index
void tool::IndexChanged(int index)
{
combo->setCurrentIndex(combo->currentIndex());
//but combo will be inaccessible here ??
}
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&tool::IndexChanged);
Is this correct way ?
- As I'm using SLOT::rowvalue1() to add combobox in Qtableview
-
@n-2204 said in Combobox in Qtableview:
Is it because of this signal ? how can i prevent this ??
It's because you recreate the entire list every time. You should just add/remove only the items that changed
You can use
std::bind
to forward the combo to the slotvoid IndexChanged(int index, QComboBox* combo){ /// do stuff }
connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, std::bind(&tool::IndexChanged, this, std::placeholders::_1, combo));