I'm trying to make a table-based interface as follows:
| QComboBox | QPushButton | Empty |
| Some data | Some data | QPushButton |
| Some data | Some data | Empty | (all additional rows resemble this one)
In the first row, I want a QComboBox with some selections that are defined based on the return value of another function, and the QPushButtons are attached to triggers which will insert or remove data.
Assuming I can generate the QComboBox and QPushButtons on my own, how can I get them to be inserted into the QTableView in those locations? I currently have a model which properly stores the data that need to be shown in the locations marked "Some data" and to return no data for the special or "Empty" locations, and I have a QStyledItemDelegate which is supposed to insert these widgets for me, but it only inserts them when I double click the field (which I suppose is the trigger for createEditor).
Figured it out.
QAbstractItemView (and by extension QTableView) have a method called setIndexWidget which can be used to place a widget in a location. By using that method, I can insert the appropriate widgets on initialization without relying on a delegate at all.
Related
I use QTreeView and QSortFilterProxyModel
// Here I determine the index, that was saved before (_lastAddObjectIndex - QModelIndex)
QModelIndex next_index = _proxyModel->index(_lastAddObjectIndex.row(), 0);
// Here I select the row programmatically, and after that I'd like to move to that row (because table might have many rows)
view->selectionModel()->select(next_index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows | QItemSelectionModel::SelectCurrent);
I assume by moving, you mean scrolling. If so, you can achieve this by using this API:
view->scrollTo(next_index);
You can even change the scroll hint if you pass a second parameter to the method. This depends on whether you are happy with the default value, which just makes sure that the item is visible.
You can refer to the documentation for fine-tuning this behaviour further in case you need to.
Versions
pyqt5
python 3.6
Setup
I'm having a few issues with the QTreeView class.
The QTreeView is configured as:
treeView.setSelectionBehavior(QAbstractItemView.SelectRows)
treeView.setSelectionMode(QAbstractItemView.SingleSelection)
There are no custom style sheets on this QTreeView
I've implemented a custom model for the view, and the flags() definition is:
def flags(self, index):
if not index.isValid():
return 0
f = super(RecordTreeModel, self).flags(index)
f = f | Qt.ItemIsSelectable | Qt.ItemIsEnabled
return f
Is there anything else relevant to the situation? I'm not doing anything fancy with my model. No custom painting, no special selection requirements -- everything is straight out of basic model examples besides the way the data structure is accessed.
Issues
Row Selection
When clicking on any column besides the first column, the row will not be selected.
Column Hovering
When hovering over any column besides the first column, the row will not be highlighted
Child Hovering
No child rows are ever highlighted when the mouse hovers over them.
I've been banging my head (and google's search bar) against these problems for several hours, to no avail.
Please let me know if I can provide any additional information!
I have custom QTableView class that shows content of custom model based on QAbstractItemModel. In the model I've implemented all needed methods to support changing rows order by DragAndDrop ( using dropMimeData()).
But I do not know how to update selection in the view after model (and view) changed.
For example:
user clicks on the row, it becomes 'selected';
user drags this row to other place;
rows are swaps in the model and view;
BUT selection stays on the first selected row.
How model can notify view to change selection?
NOTE: I cant to create additional signals and slots because don't use MOC.
The solution is:
In function dropMimeData() need to use beginMoveRows() and andMoveRows() around place where data changed.
Need to process signal QAbstractItemModel::rowsMoved of the model, where we can retrieve index of the target row.
I'm using the radgrid and I need to be able to add a row dynamically based on a certain condition. The table looks something like this:
|col0|col1|
|0,0 |1,0 |
|0,1 |1,1 |
|0,2 |1,2 |
But I want to be able to add pseudo-headers based on a condition:
|col0|col1|
|0,0 |1,0 |
|header |
|0,1 |1,1 |
|0,2 |1,2 |
The header row is not in the underlying data, I just want to add it if the condition is triggered. I don't think I can do this in the ItemTemplate itself, because I need to span all the columns, and this requires a separate table row. But I also can't find any way to accomplish it using code behind.
This seems so basic that I'm sure I'm missing something, but I don't know what it is. I'm also not at all attached to the idea of adding a row, if there's another way to accomplish what I'm trying to do.
Thanks in advance!
For posterity, I never found a way to do this, and ultimately threw out the RadGrid entirely and implemented the required layout with a repeater control that emits a table and rows, and I just emit an extra row for the header when necessary. I remain baffled that something so relatively straightforward does not appear to be possible with the RadGrid.
I need a hierarchical grid that shows data in columns for the parent rows as well as the child rows.
- a parent | 1234 | data | data |
a child | 2222 | data | data |
a child | 212 | data | data |
I've tried to make ADG work, but by default it has all columns except the grouping column blank for parent rows. I think I could use item renderers to push the data out there.
My blocking problem is that my grouping does not seem to work at all. I can see the data when I set dataProvider=MyArrayCollection, but
<mx:GroupingCollection id="GroupingCollection"
source="{this.specificReportData.gridData}">
<mx:Grouping label="childName">
<mx:GroupingField name="parentName" />
</mx:Grouping>
</mx:GroupingCollection>
does not work: no data appears. I've tried having an explicit "childname" column, and not having one. I've tried wrapping it in a HierarchicalCollectionView, but that doesn't work either. I've walked through the basic grouping tutorials and my code and data look like it follows the pattern.
Any ideas?
You must not include parents in your datasource. You need a datasource like this:
a child | 2222 | data | data | parentid | parentname
a child | 212 | data | data | parentid | parentname
And set the groupingfield to parentid or parentname. The grouping makes a hierarchy out of a flat datasource and thus creates the parents for you.
The answer is that the AdvancedDataGrid is not built to do what I want.
It is great at grouping data with common values; it is not good at grouping data where the actual parent elements exist as rows themselves. I also require the sorting and filtering apply to the parent elements only (based on their own data); any visible parent can show their children, and the children never sort.
My two-stage solution is first to process the data by iterating through it and creating an array of parent elements and adding a children array property to them that holds the child elements. Note that these are arrays of references; I am not copying the actual data.
Next, I apply any sorting and filtering to the parent array (perhaps by using an ArrayCollection wrapper) and iterate through the parents, copying the visible ones (and their children if the parent is marked expanded) to a display array. My grid them uses the display array as a simple (e.g. not grouped) dataProvider. A custom item renderer will indent the children and change the expanded property of the parent elements, which will regenerate the display array.
This is not only a simpler and more intuitive solution, it does not require a reader or maintainer to understand the idiosyncrasies of ADG (my motto: No Clever Code).
Thank you Thomas for trying. I'm giving your reply a +1 even though I'm not marking it as the answer.
Cheers