How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?
-
I know how to add a QComboBox to the table, but how to connect a QComboBox's signal and know the row/column of the table?
I use the following code to add a QComboBox to a tablewidget and it succeeded:
QComboBox *comBox = new QComboBox();
comBox->addItem("Y");
comBox->addItem("N");
ui->tableWidget->setCellWidget(i,0,comBox);And I tried to connect the currentIndexChanged() signal to the window:
connect(comBox,SIGNAL(currentIndexChanged(int)),this,SLOT(tableComboIndexChanged(int)));
And I can receive the signal.
But how can I know the QComboBox's row/column of the table from the slot function?void MainWindow::tableComboIndexChanged(int index)
{
QComboBox *comBox = qobject_cast<QComboBox *>(sender());
//?? comBox's parent is tableWiget, isn't it??}
I kind of thought of a method, which is to subclass QComboBox, and put the column/row information into the subclass's private data.
But is there any official method in the QTableWidget class to do this thing? I can't find any information anywhere and I think it's weird there is no such method, since once someone add a widget to the table, he must want to do something. -
@ailika said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
So it's hard to acomplish this. I've already read half the documentation ,which seems there is no complex example of it. It seems I won't be able to find the solution directly.
It's not that hard, have a look at https://forum.qt.io/post/422423
need to be able to popup when I click the arrow part of the combobox
This is straightforward, at the end of
ComboBoxDelegate::setEditorData
callqobject_cast<QComboBox*>(editor)->showPopup()
and make sureQAbstractItemView::CurrentChanged
is set as an edit trigger -
@ailika said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
I kind of thought of a method, which is to subclass QComboBox, and put the column/row information into the subclass's private data.
That is a possibility. As might be searching for the combobox (
sender()
) in the table widget's cell widgets till you find it.However, the best would be to give up now on your
SIGNAL
/SLOT()
macros, change over to new style signals and slots, and use C++ lambdas to pass the necessary extra information to the slot from theconnect()
.It is a separate question as to why you care about what row/column in the table the combobox lies in when you are dealing with its index changed.
-
@JonB said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
and
Thank you for answering.
I didn't kown the new style signal and slot, I will see to it later.
In fact,the row and columnis not important, I care only ablout which combo box's date changes. Note that all rows whose columns are the same have combo boxs, so I have to know which row's combo has changed.
I have try some table widget's signal like cellChanged and itemChanged,but they do not work as I think. I don't think using click signal is a good option.
In fact if I subclass combo and find the sender,I will not need the column and row, I will know the exat combo which changes from combo's private data. -
@JonB Im still confused. Even if I use new style signal and slot and use lamba to pass extra information. But the widget who send the signal is combo which is a standard widget, which is to say it can't send the "row/column" information I wanted. It seems I still have to subclass combo.
-
@ailika said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
is to say it can't send the "row/column" information I wanted
You can pass that at the time you are doing the
connect()
. Since you createsetCellWidget(i,0,comBox)
something like:connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=](int index) { tableComboIndexChanged(i, 0, index); }); void MainWindow::tableComboIndexChanged(int row, int column, int index) { }
-
I'm sorry I'm not familiar with advanced usage of c++, such as lamba. So I don't understand the the code.
Do you mean when I use connect, I can set a fixed inforation and when I receive the signal in the slot function I can get the information? If it is so, it is a better method than subclassing the combo box. But currently it seems I can just use subclassing method. Learning lamba is not a prority.
In fact, I'm a new QT learner also. I have just read a book and haven't done much practice.I'm very confused with my data presentation. It seems there are several ways, it seems hard to choose.
If I use standard QTableWidget, I think I need to process the data in the parent widget, don't I? So I need to know the row and column badly. This is the simple way, but it seems not so "tidy".
If I use the model/view structure, I can process the date in the self-defined model, maybe I don't need this information that much. But the model/view structure is very complicated.
So what's the better way to present the data? -
@ailika said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
I'm sorry I'm not familiar with advanced usage of c++, such as lamba. So I don't understand the the code.
I am sorry of you don't understand. All you should have to do is copy that code, provided it's correct, which I think it is. And read up on C++ lambdas if you want to understand it.
So I need to know the row and column badly.
If this is indeed true then you should be using the lambda as the only way to pass extra parameters to the slot I showed you. That's what's required to send the extra row/column information.
Otherwise you're on your own. If you want to do it with your sub-classing that's up to you.
-
Don't reinvent the wheel,
setCellWidget
is the wrong tool for the job (as it is in 99.9% of the cases). You should use a delegate, have a look at https://wiki.qt.io/Combo_Boxes_in_Item_Views -
@VRonin said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
Views
I m leaning the table widget. Firstly , I use the sellWidget to try it out, since it's very simple. After this, I will try to use the delegate model view method, and see which one suits most. I think its the most complicate part in QT. -
-
@ailika said in How to use QTableWidget::setCellWidget() to set a widget such as a QComboBox and do the further handling?:
I have to double click the item then the combox shows.
Have a look at your setting for editTriggers. If your behaviour is QAbstractItemView::DoubleClicked only you can change that.
-
@ailika
That is correct. The code you copied which @VRonin referred you to produces a combobox only when the user wishes to edit a cell. Otherwise the cell just shows the current value. Little point in showing a combobox when you're not editing something. When you have 10,000 rows in your table view @VRonin is trying to save you from having 10,000 comboboxes present all the time, which is "expensive/inefficient". -
I haven't think of this problem. If I have 10000 combox, I will have to create 10000 objects which will "swallow" the RAM. This indeed is a problem. So this is his really purpose, not a defect?
In fact, I don't use the table to do some data process which may contain thousands of data. I need only 250 rows and need it to be displayed.
Currently, I think the createEdit method can't work. I think I should use 'QStyleOptionComboBox' instead, am I right? But this really difficult, I haven't seen any complete example in the network. Currently I can only display a text in the combox item, but it can't popup. It seems that I should study QStyle function first and see whether I can solve my problem. -
@ailika
Even 250 comboboxes is quite a lot.Anyway, I don't know what doesn't work for you. If you follow the code in @VRonin's Combo Boxes in Item Views you should find:
- Initially all items are displayed with their current values, no comboboxes.
- Then you click or double-click in a cell and it turns into a combobox.
- Then you click on the combobox to get the popup and do the editing.
- Then you click away or whatever and it reverts to the text value.
-
@JonB
250is quite alot? I have seen other similar application who has 250 combox. But they ard made by MFC and c#. so it's not unreasonable quantity.
I have used the code and it works like you said.
But what I need is to to display them initially not display on edit. The display on edit way just don't fit into the application. If I cant solve it even by QStyle, I will use the setCellWidget way or just do not use the combobox. Just use a dialog to edit the date and use the table to dislpay text(the dialog is destined to be used what ever method I use.) -
@ailika
In that case: either it's possible to have a delegate for normal, non-edit viewing which "looks like" a combobox --- I don't know if you can do that, as you say maybeQStyleOption
something --- and then it has to change into a real combobox on click. Or, also as you say, go back to your preferredsetCellWidget()
. In which case I showed earlier how you can access the row/column, or the actual combobox, in the slot, which is what you originally asked for.