I have a QTableView which gets its data from QAbstractTableModel and is a 2d array. Below the TableView I have two comboboxes. User first selects the row in the TableView. Now I want that when the user selects an option from the combobox, I want the selected option to update the display in the TableView selection.
Shown below is the UI. For example if the User Selects REF DES in the class combo box I want the selected row to update its class name to REF DES.
I am using c++ qt5. How do I achieve this with signals and slots?
enter image description here
Currently I have a slot that updates the combobox values based on my selection in tableview. I use something like this.
void GetOptionsClass::slotSelectionChange(const QItemSelection&, const QItemSelection&)
{
int rowidx = ui->line_tableView->selectionModel()->currentIndex().row();
data = model->index(rowidx, 2).data().toString();
if (data == "BOARD GEOMETRY") {
ui->lineSubclass->clear();
ui->lineSubclass->addItems(board_geometry_opts);
ui->lineClass->setCurrentIndex(0);
}
However I want to reverse this. Meaning when I change combobox I want to update the qtableview.
Related
My app should have several languages. English is by default. Problem is that if user will switch to different language, everything will be translated except for ComboBox selected value. This is how it looks:
Code behind ComboBox is:
ObservableList<Currency> currencyItem= CurrencyDA.getCurrencies();
currenciesComboBox.setItems(currencyItem);
Callback<ListView<Currency>, ListCell<Currency>> currencyFactory = lv -> new ListCell<Currency>(){
#Override
protected void updateItem(Currency currency, boolean empty){
super.updateItem(currency, empty);
setText(empty ? "" : interfaceBundle.getString("currency_"+currency.getName()));
}
};
currenciesComboBox.setCellFactory(currencyFactory);
currenciesComboBox.setButtonCell(currencyFactory.call(null));
currenciesComboBox.getSelectionModel().selectFirst();
How can I get selected value refreshed?
From the doc
As the ComboBox internally renders content with a ListView, API exists in the ComboBox class to allow for a custom cell factory to be set. For more information on cell factories, refer to the Cell and ListCell classes. It is important to note that if a cell factory is set on a ComboBox, cells will only be used in the ListView that shows when the ComboBox is clicked. If you also want to customize the rendering of the 'button' area of the ComboBox, you can set a custom ListCell instance in the button cell property. One way of doing this is with the following code :
//(note the use of setButtonCell):
Callback<ListView<String>, ListCell<String>> cellFactory = ...;
ComboBox comboBox = new ComboBox();
comboBox.setItems(items);
comboBox.setButtonCell(cellFactory.call(null));
comboBox.setCellFactory(cellFactory);
So the only thing you have to add is :
currenciesComboBox.setButtonCell(currencyFactory.call(null));
Background:
Suppose I have multiple fragments of a single table in a view, each with a rowExpander.
Expected Behaviour:
If in one table fragment I expand a row, other fragments same indexed row should get expanded. Same for collapse
My Progress:
Sample Fragment:
tableview(dataset) {
column("First Name", Person::firstNameProperty)
column("Last Name", Person::lastNameProperty)
rowExpander(true) {
selectedData.item?.apply {
fire(ExpandDataEvent(dataset.indexOf(this)))
}
column("Mobile Nos.", Person::mobileNumProperty)
column("Email Ids", Person::emailIdProperty)
}
bindSelected(selectedData)
subscribe<ExpandDataEvent> { event ->
selectionModel.select(event.index)
}
}
Event Class:
class ExpandDataEvent(val index: Int) : FXEvent()
What I understand from "subscribe" is that it gets called when an event is fired (currently I am firing the event whenever the user expands the row by either double-click/clicking the plus sign); and since the subscribe is placed inside tableview, it gets called for all the table fragments present (which is what I want). But in the subscribe method I am doing a selectionModel.select(event.index) which only selects the corresponding index row. I want to expand the row (preferably by using the selectionModel)
Question 2:
Is it possible to remove the plus sign column? For rowExpand, if I have set expandOnDoubleClick to true, I dont want the plus sign column in my tableview.
The rowExpander builder returns the actual ExpanderColumn which is basically a normal TableColumn. Save a reference to the expander so that you can operate on it later:
val expander = rowExpander(true) { ... }
Directly below, you can now hide the expander column:
expander.isVisible = false
Now it's easy to toggle the expanded state of a specific row from the event subscriber as well:
subscribe<ExpandDataEvent> { event ->
expander.toggleExpanded(event.index)
selectionModel.select(event.index)
}
You might want to double check that you don't toggle the expander for the tableview that fired the event, so consider including the event source in your event and discriminate on that in the subscriber.
I will investigate if we can add a visible boolean parameter to the rowExpander builder function so you don't need to call isVisible manually :)
I have custom table view that shows content of custom abstract model.
I need to implement mixed selection for these view.
When user clicks on the first column the whole row should be selected (AbstractItemView::SelectRow).
When user clicks on cell in other column just the particular cell should be selected (AbstractItemView::SelectItems).
What need to do to achieve such behaviour?
Just do this:
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
//if(!index.column()) more elegant
if(index.column() == 0)
ui->tableView->selectRow(index.row());
}
Catch clicked() signal and check is it first column. If so, then selectRow() with current row (index.row())
I use here QTableView but QAbstractItemView has clicked signal too.
I'm working on a UI that reads a database and updates it back when items in it are changed. My UI consists of a QListView, and it's populated by QComboBoxes. Now, I can get a signal when a combo box item is changed (though I can't get the index of the widget item that was changed), and I need to let the parent list view know that a member widget's value had changed. Any ideas on how I can get this to work?
A simple hack for obtaining the widget index is to code the widget index into the item data of each combo box item. You could set a QString as itemData which codes a reference to your standard item data and the widget index, e.g.
pComboBox1->setItemText(1, "Item 1");
pComboBox1->setItemData(1, "1-1");
pComboBox1->setItemData(2, "Item 2");
pComboBox1->setItemData(2, "2-1"); // Item 2 in 1st combo box
pComboBox2->setItemText(1, "Item 1");
pComboBox2->setItemData(1, "1-2"); // Item 1 in 2nd combo box
// and so on
I'm using an editable QTableView + QStandardItemModel.
While editing a cell in a table view, I'd like to do something according to the new input data in this specific cell when committing the new data into the table view.
To do this, I need the new input data and the current model index (or column & row number).
I tried some slots such as
virtual void closeEditor (QWidget * editor,
QAbstractItemDelegate::EndEditHint hint)
and
virtual void commitData ( QWidget * editor ).
commitData seems to be what I need, however, the parameter is only the editor and I cannot figure out how to obtain the text in this editor widget.
I looked QTextEdit but it's not a inherited class of QWidget.
I wonder if there's any way to obtain the data (text) and axis (column, row) of an editor widget?
I suggest to implement your own item delegate, inheriting QStandardItemDelegate (or QAbstractItemDelegate). There you can override
void setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const
Simply do you your custom processing and then call QStandardItemDelegate::setModelData(...) to make sure that your model is updated with the newly edited data.
The itemChanged(QStandardItem*) signal is emitted by a QStandardItemModel whenever an item's data changes.
From the given QStandardItem, you can retrieve the row and column directly. To get the displayed text, pass Qt::DisplayRole to the item's data() method.