basically I am working with a treeviewer in Java (org.eclipse.jface.viewers.TreeViewer).
Now my problem is, that I want to add an childelement/ item to an existing knot.
First of all my tree looks like this:
Knot A
Knot B
Knot C
>child1
>child2
These children(child1, child2) arent added manually, they are generated before I get my hands on the tree itself.
I create the treeviewer:
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
I populate the treeviewer:
viewer.setInput(....elements());
which generates the state from above.
viewer.getTree().getItem(0) returns the correct knot A of my tree.
But I cant add a new child to an existing knot.
I tried the following and other things:
TreeItem newItem = new TreeItem(items[0], SWT.NONE); and
viewer.add(items[0], newItem); with a newly created item
viewer.refresh();
Theoretically I could manipulate the arrayList which populates the treeviewer in the first place but that would be really bad I think.
I really do not know what I am doing wrong right now.
I guess it is a quite silly question. If that is the case, then I am sorry.^^
Thank you for your help, I am grateful for every hint that you can offer.
Updating your 'model' (the data you give to setInput) is the correct way to update the tree. Call TreeViewer.refresh() or TreeViewer.refresh(element) to get the tree viewer to update the tree from the model.
When you are using TreeViewer you never create TreeItem objects - the viewer does that. Everything you pass to the refresh, update, add ... methods are objects from your model not TreeItems.
Related
I want to design a ContextMenu with a TreeView functionality. I didnt found anything how can be done. I want to design a custom TableMenu (that button at the end of table header which can show hide the columns), using a treeView structure in ContextMenu, so the user can show/hide a group of columns, like 1-3, 4-6, and so on, or any kind of grouping, but still keeping the one by one show/hiding. The best way would be a tree structure, so if the user hides the parent all of its children are hidden and vice-versa.
Is there any possibility to adapt somehow the TreeView into ContextMenu?
I would like something like this with CheckBoxes for instance:
Each parent node would be an item that represents a group of columns, and each child would be a column.
P.S.
I know how to create and add a custom ContextMenu as tableMenu (I have got it from here : https://gist.github.com/Roland09/d92829cdf5e5fee6fee9) , I'm interested in how to set a tree structure to context menu instead of the list structure.
I also know that I can add the parent like a "simple" item to the context menu, then handle as a parent, but then I Have to implement every functionality of a TreeItem, but I prefer a much simpler way if it exists.
I am building a JTreeTable. I found some starter code and have come pretty far. In the end my goal is to be able to have different data at different levels like a hierarchical list.
Currently, I have it working with data at different levels. However, I am running up against a wall when it comes to changing the columns as a next goal. From where I currently stand I have 3 more milestones:
Show different set of columns for different levels
Ability to adjust column widths for different levels
Ensure the JTree part of the table always stays to left
I am getting close to closing out this task but again stuck at the first of these 3.
Since creating a JTreeTable is complex, the minimum example leverages several class listed below in the image:
I am happy to post the code to any of those classes but I also did not want clog the question with useless code. First let me show the functionality I want.
The first image is when the top level is selected and the second image is when the second level is selected. Notice how the columns are different. That is what I want to happen in my application.
Top level selected:
Second level selected:
So one way I tried to solve this problem, is when the list selection is changed inside this section of code:
ListSelectionListener listener = (ListSelectionEvent e) -> {
TreeTableModelAdapter adapter = (TreeTableModelAdapter) JTreeTable.this.getModel();
//Need to see why this breaks.
JTreeTable.this.getTableHeader().setColumnModel(adapter.getColumnModel());
};
this.getSelectionModel().addListSelectionListener(listener);
This code is in the initialization of the JTreeTable. I have tried setting the column model on both the TableHeader and the table as well. Below is what happens then when I select a row:
The columns just disappear on me. The creation of the column model is happening in the TreeTableModelAdapter class with the following method:
public TableColumnModel getColumnModel(){
DefaultTableColumnModel model = new DefaultTableColumnModel();
for(int i=0;i<getColumnCount();i++){
TableColumn column = new TableColumn();
column.setIdentifier(getColumnName(i));
model.addColumn(column);
}
return model;
}
Any direction would be very helpful. Again happy to post any code you think could be helpful to answer the question. Just put a comment in and I will add it right away.
I will add the milestones as I find them in case this helps others, but for now this question is answered.
Milestone 1
I was actually able to solve the first milestone. The key is to trigger the creation of the columns of the column model, not to create a new column model. Below is the code for when the row selection is changed:
//Change columns depending on row
ListSelectionListener listener = (ListSelectionEvent e) -> {
createDefaultColumnsFromModel();
};
this.getSelectionModel().addListSelectionListener(listener);
This code creates the columns based on the row selected in the JTree part of the JTreeTable. The TreeTableModelAdapter implements the getColumnCount() and getColumnName() methods by also passing the selected row in the JTree to the JTreeTableModel so that the columns and their names are dynamically retrieved based on a particular node in the JTree. The key for this for me was trigger those to be called again to update the JTreeTable.
Milestone 2
Adjusting column widths based on the data level proved to be much more difficult than I had originally anticipated. In order to retain the cells state when the column model changed I had to disconnect the painting of the cells from it. This is a hairy process because this is done inside BasicTableUI and the method that gets the rectangle of the cell is private. So I had to subclass it, overload the paint() method and create my own methods that get called inside the paint method. There was a lot of copy pasting so that I could call normally private methods. I just renamed them and referenced these methods instead. The way the ui class was designed did not make it very flexible. Below is 2 images where I am selecting different levels and the columns are obviously different widths at different levels.
Milestone 3
I was able to make this work by keeping track of the view in the model. This seems very dirty to me as the model should separated from the view. Since the tree column's class is unique, I just returned the right class if that column was the first in the view.
The one problem I have with this technique is that I get unexpected behavior where the value returned is not consistent. I attempted to resolve this by overriding JTree.covertValueToText(). Since a JTree only expects 1 value and depending on the sequence of columns in the view this value could change. So in overriding this method I check the stored index for the JTree column's value. Again this causes the unexpected behavior. I will update the post if I find the fix.
I've ran into a weird problem which I can't seem to fix. I'm making a table view which one column has a checkbox inside of it.
Although I'm trying to add a change listener to the CheckBoxTableCell but not having any luck.
If I do this:
final CheckBoxTableCell<Plugin, Boolean> ctCell = new CheckBoxTableCell<>();
enabled.setCellFactory(p -> ctCell);
The checkbox's do not show up at all on the tableview.
But if I do this:
enabled.setCellFactory(p -> new CheckBoxTableCell<>());
The checkboxes show up fine? Why does the second one show the checkboxes but the first one doesn't? Please help!
In the first case you create an object and pass it multiple times. As per JavaFX scene graph documentation a node can only be attached to a single parent and a parent cannot have duplicate children.
In the second case you create a new object every time to populate the cells. This is what should be done, as the method expects a factory, in other words an object that produces a new object every call.
I'm writting an RCP application which has an application model that can be simplified as below:
==================================================
= lpart || rpart1 | rpart2 =
= -------------------- || ---------------------- =
= <a table> || <some sfuff about =
= || the selected item> =
==================================================
The window is divided into two part stacks: left and right
The left PS contains one part, and the part contains only a table
The right PS contains two parts, each will show some details about the selected item in the table
The problem:
It seems that Eclipse is lazily initializing my part implementation class. If I call MPart.getObject() on rpart2 before I ever clicked the tab, it returns null. Can I make Eclipse to initialize all my part implementation class when it starts up.
How can I tell which one of rpart1 and rpart2 is showing. I want to avoid loading data for both parts whenever the selection of the table changes, after all, only one of them is really showing.
What I want to achieve:
Whenever an item gets selected, both rpart1 and rpart2 get notified and remember the selection (item id or sth. similar). It will be impossible if rpart2 is lazily initialized.
Only the part that is currently showing will fetch the details it needs. It will be impossible if a part cannot tell whether it is showing.
When the other part gets selected, it will fetch and display its data according to the remembered selection. Well, this is the only part I know how to do it.
Any help would be really appreciated! Thanks a lot!
You can use the EPartService addPartListener method to add a listener that is notified about all part activation (and other) events.
I think EPartService.isPartVisible(MPart) (rather than MPart.isVisible()) solves your first problem.
In the eclipse plugin I am working on, I want to make editable the content of a List (org.eclipse.swt.widgets.List). However, most of the examples I have found show only how to add an item editor to either a swt Table or a Tree. Is it possible to do the same with a list ?, or should I try to replace my list with a single column table ?.
This is how I instantiate the list:
new List (theComposite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL)
Can you use JFace's TableViewer and CellEditors? That's much easier and it already does a lot of stuff for you. You only need to hide the headers and use only a single column, as you already pointed out. Then it should look like a List.