I'm trying to use the JScrollPane component in Java - jscrollpane

Hi guys i would like you to help me display parallel arrays on a JScrollPane. The arrays are of String and double data types. Here is my sample code: String[] items = {"fish","frog"}; double[] prices = {12,19}; I'm supposed to put them on the JScrollPane, with the element in position 0 of the items array next to the prices position 0 and so on;

Any reason you can't put your data in JTable and add the table to the scroll pane?
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
class ItemTableModel extends AbstractTableModel {
final String[] items;
final double[] prices;
public ItemTableModel(String[] items, double[] prices) {
checkNotNull(items);
checkNotNull(prices);
checkArgument(items.length == prices.length);
this.items = items;
this.prices = prices;
}
#Override
public int getRowCount() {
return items.length;
}
#Override
public int getColumnCount() {
return 2;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return items[rowIndex];
case 1:
return prices[rowIndex];
default:
throw new IllegalArgumentException();
}
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return String.class;
case 1:
return Object.class;
default:
throw new IllegalArgumentException();
}
}
#Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
return "Item";
case 1:
return "Price";
default:
throw new IllegalArgumentException();
}
}
}
public class Example {
public static void main(String[] args) {
Runnable createAndShowGui = new Runnable() {
#Override
public void run() {
createAndShowGui();
}
};
SwingUtilities.invokeLater(createAndShowGui);
}
private static void createAndShowGui() {
String[] items = { "fish", "frog" };
double[] prices = { 12, 19 };
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
ItemTableModel tableModel = new ItemTableModel(items, prices);
JTable table = new JTable(tableModel);
//table.setTableHeader(null); // uncomment to hide the table header
frame.setContentPane(new JScrollPane(table));
frame.pack();
frame.setVisible(true);
}
}

Related

GWT CellTree inside a DataGrid does not react to mouse-clicks

I have put a GWT-CellTree in a DataGrid. It works except for one thing: When clicking on the tree-expand-icon, nothing happens. I have tried to minimize the
code needed to reproduce the problem...
How can this be fixed ?
best regards, Magnus
package com.raybased.gwt.configtool.client.grid;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SimpleLayoutPanel;
public class HelloWorld implements EntryPoint {
public void onModuleLoad() {
DataGrid grid= (DataGrid) new NodesGrid().getTable();
grid.setWidth("100%");
SimpleLayoutPanel slp = new SimpleLayoutPanel();
slp.add(grid);
RootLayoutPanel.get().add(slp);
}
}
package com.raybased.gwt.configtool.client.grid;
import com.google.gwt.cell.client.ClickableTextCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.dom.client.Style;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.text.shared.AbstractSafeHtmlRenderer;
import com.google.gwt.text.shared.SafeHtmlRenderer;
import com.google.gwt.user.cellview.client.*;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.view.client.ListDataProvider;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
public class NodesGrid {
private AbstractCellTable<Node> table = new DataGrid<>();
private Column nameColumn;
private Column<Node, String> showBlocksColumn;
private final Set<Integer> showBlocks = new HashSet<>();
public Column getNameColumn() {
return nameColumn;
}
public AbstractCellTable<Node> getTable() {
return table;
}
public NodesGrid() {
table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
table.setWidth("100%");
CustomCellTableBuilder c = new CustomCellTableBuilder(this, table);
table.setTableBuilder(c);
Node nodes = new Node();
nodes.setName("hello");
nodes.setId(123);
Node n2 = new Node();
n2.setName("testing");
nodes.getBlocks().add(n2);
ListDataProvider<Node> dataProvider = new ListDataProvider<>();
dataProvider.addDataDisplay(table);
List<Node> list = dataProvider.getList();
list.add(nodes);
addShowBlocks();
nameColumn = getSorter(list, "Name", Comparator.comparing(Node::getName), Node::getName);
}
private Column getSorter(List<Node> list,
String name,
Comparator<Node> cmp,
Function<Node, String> supplier) {
TextColumn<Node> column = new TextColumn<Node>() {
#Override
public String getValue(Node object) {
return supplier.apply(object);
}
};
table.addColumn(column, name);
column.setSortable(true);
ColumnSortEvent.ListHandler<Node> columnSortHandler = new ColumnSortEvent.ListHandler<>(list);
columnSortHandler.setComparator(column, cmp);
table.addColumnSortHandler(columnSortHandler);
table.getColumnSortList().push(column);
return column;
}
public Column<Node, String> getShowBlocksColumn() {
return showBlocksColumn;
}
public Set<Integer> getShowBlocks() {
return showBlocks;
}
void addShowBlocks() {
SafeHtmlRenderer<String> anchorRenderer = new AbstractSafeHtmlRenderer<String>() {
#Override
public SafeHtml render(String object) {
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendHtmlConstant("(<a href=\"javascript:;\">").appendEscaped(object)
.appendHtmlConstant("</a>)");
return sb.toSafeHtml();
}
};
showBlocksColumn = new Column<Node, String>(new ClickableTextCell(anchorRenderer)) {
#Override
public String getValue(Node node) {
if (showBlocks.contains(node.getId())) {
return "hide blocks";
} else {
return "show blocks";
}
}
};
showBlocksColumn.setFieldUpdater(new FieldUpdater<Node, String>() {
#Override
public void update(int index, Node node, String value) {
if (showBlocks.contains(node.getId())) {
showBlocks.remove(node.getId());
} else {
showBlocks.add(node.getId());
}
table.redrawRow(index);
}
});
table.addColumn(showBlocksColumn);
table.setColumnWidth(0, 10, Style.Unit.EM);
}
}
package com.raybased.gwt.configtool.client.grid;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
import com.google.gwt.user.cellview.client.TreeNode;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;
import java.util.ArrayList;
import java.util.List;
public class NodesTree {
private CellTree tree;
public NodesTree(Node node) {
TreeViewModel model = new CustomTreeModel(node);
tree = new CellTree(model, null);
tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
TreeNode rootNode = tree.getRootTreeNode();
openAll(rootNode);
}
private static class TopLevel {
private final String name;
private List<Node> blocks = new ArrayList<>();
public TopLevel(String name) {
this.name = name;
}
public TopLevel(String name, List<Node> blocks) {
this.name = name;
this.blocks = blocks;
}
public String getName() {
return name;
}
public List<Node> getBlocks() {
return blocks;
}
}
private static class CustomTreeModel implements TreeViewModel {
private final List<TopLevel> topLevels;
private final SingleSelectionModel<String> selectionModel
= new SingleSelectionModel<>();
public CustomTreeModel(Node node) {
topLevels = new ArrayList<>();
{
TopLevel blocksNode = new TopLevel("Blocks", new ArrayList(node.getBlocks()));
topLevels.add(blocksNode);
}
{
TopLevel outgoing = new TopLevel("Outgoing");
topLevels.add(outgoing);
}
{
TopLevel incoming = new TopLevel("Incoming");
topLevels.add(incoming);
}
}
public <T> NodeInfo<?> getNodeInfo(T value) {
if (value == null) {
// LEVEL 0.
ListDataProvider<TopLevel> dataProvider
= new ListDataProvider<>(
topLevels);
Cell<TopLevel> cell = new AbstractCell<TopLevel>() {
#Override
public void render(Context context, TopLevel value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant(" ");
sb.appendEscaped(value.getName());
}
};
return new DefaultNodeInfo<>(dataProvider, cell);
} else if (value instanceof TopLevel) {
// LEVEL 1.
ListDataProvider<Node> dataProvider = new ListDataProvider<>(((TopLevel) value).getBlocks());
Cell<Node> cell = new AbstractCell<Node>() {
#Override
public void render(Context context, Node value, SafeHtmlBuilder sb) {
if (value != null) {
sb.appendHtmlConstant(" ");
sb.appendEscaped("(" + value.getName() + ")");
}
}
};
return new DefaultNodeInfo<>(dataProvider, cell);
} else if (value instanceof Node) {
// LEVEL 2 - LEAF.
String params = "test";
ArrayList<String> str = new ArrayList<>();
str.add(params);
ListDataProvider<String> dataProvider = new ListDataProvider<>(str);
return new DefaultNodeInfo<>(dataProvider, new TextCell(), selectionModel, null);
}
return null;
}
public boolean isLeaf(Object value) {
if (value instanceof String) {
return true;
}
return false;
}
}
private void openAll(TreeNode rootNode) {
if (rootNode == null) return;
for (int i = 0; i < rootNode.getChildCount(); i++) {
TreeNode node = rootNode.setChildOpen(i, true);
openAll(node);
}
}
public Widget getWidget() {
return tree;
}
}
package com.raybased.gwt.configtool.client.grid;
import com.google.gwt.dom.builder.shared.DivBuilder;
import com.google.gwt.dom.builder.shared.TableCellBuilder;
import com.google.gwt.dom.builder.shared.TableRowBuilder;
import com.google.gwt.dom.client.Style;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.cellview.client.AbstractCellTable;
import com.google.gwt.user.cellview.client.AbstractCellTableBuilder;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.view.client.SelectionModel;
public class CustomCellTableBuilder extends AbstractCellTableBuilder<Node> {
NodesGrid nodesGrid;
private final String rowStyle;
private final String selectedRowStyle;
private final String cellStyle;
private final String selectedCellStyle;
/**
* Construct a new table builder.
*
* #param cellTable the table this builder will build rows for
*/
public CustomCellTableBuilder(NodesGrid nodesGrid, AbstractCellTable<Node> cellTable) {
super(cellTable);
this.nodesGrid = nodesGrid;
AbstractCellTable.Style style = cellTable.getResources().style();
rowStyle = style.evenRow();
selectedRowStyle = " " + style.selectedRow();
cellStyle = style.cell() + " " + style.evenRowCell();
selectedCellStyle = " " + style.selectedRowCell();
}
#Override
protected void buildRowImpl(Node rowValue, int absRowIndex) {
// Calculate the row styles.
SelectionModel<? super Node> selectionModel = cellTable.getSelectionModel();
boolean isSelected =
(selectionModel == null || rowValue == null) ? false : selectionModel
.isSelected(rowValue);
StringBuilder trClasses = new StringBuilder(rowStyle);
if (isSelected) {
trClasses.append(selectedRowStyle);
}
String cellStyles = cellStyle;
if (isSelected) {
cellStyles += selectedCellStyle;
}
TableRowBuilder row = startRow();
row.className(trClasses.toString());
buildRow(row, rowValue, cellStyles, nodesGrid.getShowBlocksColumn());
buildRow(row, rowValue, cellStyles, nodesGrid.getNameColumn());
row.endTR();
if (nodesGrid.getShowBlocks().contains(rowValue.getId())) {
buildBlockRow(rowValue, cellStyles);
}
}
void buildRow(TableRowBuilder row, Node rowValue, String cellStyles, Column column) {
TableCellBuilder td = row.startTD();
td.className(cellStyles);
td.style().outlineStyle(Style.OutlineStyle.NONE).endStyle();
renderCell(td, createContext(0), column, rowValue);
td.endTD();
}
private void buildBlockRow(Node rowValue, String cellStyles) {
TableRowBuilder row = startRow();
buildCell(rowValue, cellStyles, row);
row.endTR();
}
private void buildCell(Node rowValue, String cellStyles, TableRowBuilder row) {
NodesTree hw = new NodesTree(rowValue);
TableCellBuilder td = row.startTD().colSpan(5);
td.className(cellStyles);
DivBuilder div = td.startDiv();
String t = hw.getWidget().getElement().getInnerHTML();
div.html(SafeHtmlUtils.fromTrustedString(t));
div.end();
td.endTD();
}
}
package com.raybased.gwt.configtool.client.grid;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Node implements Serializable {
String name;
List<Node> blocks = new ArrayList<>();
String params;
int id;
public Node() {
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Node> getBlocks() {
return blocks;
}
}

assertion failed: Unknown column layout data

When I create combo box in particular only one 3rd column using table viewer in Eclipse SWT.
I think I've done everything ok until now, however when I compile the code then i get error:
Code:
public void createPartControl(Composite parent) {
Composite tableComposite = new Composite(parent, SWT.NONE);
tableColumnLayout = new TableColumnLayout();
tableComposite.setLayout(tableColumnLayout);
tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
true));
tableViewer = new TableViewer(tableComposite, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
tableViewer.setContentProvider(ArrayContentProvider.getInstance());
// TODO viewer.setLabelProvider(new ViewLabelProvider());
table = tableViewer.getTable();
// Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
String[] titles = { "Threat Name", "Category Name", "Status",
"Priority", "Description", "Justification" };
int[] bounds = { 100, 100, 100, 100 };
TableViewerColumn col = createTableViewerColumn(titles[2], bounds[2], 2);
col.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
Dummy p = (Dummy) element;
return p.getValue();
}
});
col.setEditingSupport(new FirstValueEditingSupport(tableViewer));
}
private SelectionAdapter getSelectionAdapter(final TableColumn column,
final int index) {
SelectionAdapter selectionAdapter = new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
tableViewer.refresh();
}
};
return selectionAdapter;
}
private static class Dummy {
public String value;
public Dummy(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
public static class FirstValueEditingSupport extends EditingSupport {
private final TableViewer viewer;
private final CellEditor editor;
private final String[] possibleValues = { "Mitigated",
"Not Applicable", "Not Started", "Needs Investigation" };
public FirstValueEditingSupport(TableViewer viewer) {
super(viewer);
this.viewer = viewer;
this.editor = new ComboBoxCellEditor(viewer.getTable(),
possibleValues);
}
#Override
protected CellEditor getCellEditor(Object element) {
return editor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
Dummy dummy = (Dummy) element;
int index = 0;
for (int i = 0; i < possibleValues.length; i++) {
if (Objects.equals(possibleValues[i], dummy.getValue())) {
index = i;
break;
}
}
return index;
}
#Override
protected void setValue(Object element, Object value) {
Dummy dummy = (Dummy) element;
int index = (Integer) value;
dummy.setValue(possibleValues[index]);
viewer.update(element, null);
}
}
private void fillRows(String shortdesc, String categ, String descp) {
System.out.println("fillRows call from above method.");
TableColumn status_Name_Col = tableViewer.getTable().getColumn(2);
System.out.println("**************** status_Name_Col ************ "
+ status_Name_Col);
tableViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(
SelectionChangedEvent selectionChangedEvent) {
StructuredSelection selection = (StructuredSelection) selectionChangedEvent
.getSelection();
System.out.println(((Dummy) selection.getFirstElement())
.getValue());
}
});
List<Dummy> elements = new ArrayList<>();
for (int i = 0; i < Connection.Number_Of_Connection; i++) {
elements.add(new Dummy("First option"));
}
tableViewer.setInput(elements);
tableColumnLayout.setColumnData(status_Name_Col, new ColumnWeightData(
1, true));
tableViewerColumn.setEditingSupport(new FirstValueEditingSupport(
tableViewer));
}
Questions:
how to display combo box in particular only one column?
You must not do the TableViewer setInput call until you have set up everything on the table. All the content providers, label providers, column layouts, editing support, .... must be set before setInput is called.
You must also call setColumnData for every column you create.

Javafx Combobox list index set to -1 when executing combobox.get(someobject)

I have a combo box that is populated with the following ObservableList:
final ObservableList<SimplePerson> persons = FXCollections.observableArrayList(
new SimplePerson("Jacob", 1),
new SimplePerson("Isabella", 2),
new SimplePerson("Ethan", 3),
new SimplePerson("Emma", 4),
new SimplePerson("Michael", 5)
);
The combobox's selected index will be set to -1, the combobox's textbox will be populated with "Michael", and the "Michael" item in the drop down list will not be selected when I run
setValue(new SimplePerson("Michael",5))
Here is some example code (SSCCE)
import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.property.IntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.util.Callback;
import javafx.scene.control.ListView;
import javafx.scene.control.ListCell;
public class ComboBoxDemo extends Application {
public class SimplePerson {
private StringProperty name;
private IntegerProperty id;
private String somethingElse;
public SimplePerson(String name, Integer id) {
setName(name);
setId(id);
}
public final void setName(String value) {
nameProperty().set(value);
}
public final void setId(Integer id) {
idProperty().set(id);
}
public String getName() {
return nameProperty().get();
}
public int getId() {
return idProperty().get();
}
public StringProperty nameProperty() {
if (name == null) {
name = new SimpleStringProperty(this, "name");
}
return name;
}
public IntegerProperty idProperty() {
if (id == null) {
id = new SimpleIntegerProperty(this, "id");
}
return id;
}
#Override
public String toString() {
return name.get();
}
}
final ObservableList<SimplePerson> persons = FXCollections.observableArrayList(
new SimplePerson("Jacob", 1),
new SimplePerson("Isabella", 2),
new SimplePerson("Ethan", 3),
new SimplePerson("Emma", 4),
new SimplePerson("Michael", 5)
);
#Override
public void start(Stage stage) throws Exception {
final ComboBox<SimplePerson> cb = new ComboBox<>();
final ComboBox<String> cb2 = new ComboBox<>();
cb.setItems(persons);
cb.setEditable(true);
cb.setConverter(new StringConverter<SimplePerson>() {
#Override
public String toString(SimplePerson p) {
if (p != null) {
System.out.println("Looking up toString " + p.getName());
return p.getName();
} else {
System.out.println("Looking up toString null");
return "";
}
}
#Override
public SimplePerson fromString(String name) {
if (cb.getValue() != null) {
((SimplePerson) cb.getValue()).setName(name);
cb.show();
System.out.println("Here I am" + ((SimplePerson) cb.getValue()).getName());
return (SimplePerson) cb.getValue();
}
System.out.println("Returning null");
return null;
}
});
stage.setScene(new Scene(cb));
stage.show();
cb.setCellFactory(new Callback<ListView<SimplePerson>, ListCell<SimplePerson>>() {
#Override
public ListCell<SimplePerson> call(ListView<SimplePerson> l) {
return new ListCell<SimplePerson>() {
#Override
protected void updateItem(SimplePerson item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
System.out.println("I'm null");
} else {
System.out.println("Go get them " + item.getName());
setText(item.getName());
}
}
};
}
});
cb.setValue(new SimplePerson("Michael", 5));
System.out.println(cb.getSelectionModel().getSelectedIndex());
System.out.println(cb.getValue().getName());
}
public static void main(String[] args) {
launch(args);
}
}
The drop down list will select the right item when the ObservableList contains Strings
ObservableList<String>
You are passing a new Object to setValue() into the ComboBox. The Michael that is displayed when the ComboBox pops up is not same as the Michael in the dropdown.
If you pass cb.setValue(new SimplePerson("xyz", 5)); then the ComboBox will show the initially selected item as xyz, where xyz is not in the List of Person.
To set the exact object, you need to fetch them from their original reference, which in your case is the ObservableList<SimplePerson> persons. To fetch Michael, we use its index :
cb.setValue(persons.get(4));

JList update freezes display but not JFrame setTitle

If I update a JList with a long number of html formatted items then the controls stop responding and indicators won't update. This makes sense, the event thread is busy. The title can still be set though. Why is this?
Here's some (long) code demonstrating this:
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.*;
public class JListTest extends JFrame {
class TestListModel extends AbstractListModel<String> {
private static final long serialVersionUID = JListTest.serialVersionUID;
private boolean useHtml;
private String[] formattedList = new String[] {};
public int getSize() {
return formattedList.length;
}
public String getElementAt(int index) {
return formattedList[index];
}
public void setUseHtml(boolean useHtml) {
this.useHtml = useHtml;
}
public String getNewListItem() {
if (useHtml) {
return "<html><div style='padding:2px"
+ ";background-color:#EDF5F4;color:black'><div style='padding:2px;font-weight:500;'>"
+ "Item " + (100 * Math.random())
+ "</div>"
+ "This will change!"
+ "</div></html>";
} else {
return "Item " + (100 * Math.random());
}
}
public void updateItems() {
formattedList = new String[] {"<html><h1>Loading!</h1></html>"};
fireContentsChanged(this, 0, 1);
Thread buildItems = new Thread() {
#Override
public void run() {
final String[] tempList = new String[3000];
for (int i=0; i<tempList.length; i++) {
tempList[i] = getNewListItem();
}
// Just show the string bashing's done
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
formattedList = new String[] {"<html><h1>Updating!</h1></html>"};
fireContentsChanged(TestListModel.this, 0, 1);
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Update
SwingUtilities.invokeLater(new Runnable() {
public void run() {
formattedList = tempList;
fireContentsChanged(TestListModel.this, 0, formattedList.length);
}
});
}
};
buildItems.start();
}
}
protected static final long serialVersionUID = 1L;
public JListTest() {
JPanel controlPanel = new JPanel();
JButton updaterControl = new JButton("Add 3000");
final JCheckBox useHtmlControl = new JCheckBox("Use HTML");
final TestListModel model = new TestListModel();
JList<String> list = new JList<String>(model);
JScrollPane scrollPane = new JScrollPane(list);
final JLabel durationIndicator = new JLabel("0");
controlPanel.add(useHtmlControl, BorderLayout.WEST);
controlPanel.add(updaterControl, BorderLayout.EAST);
getContentPane().add(controlPanel, BorderLayout.PAGE_START);
getContentPane().add(scrollPane, BorderLayout.CENTER);
getContentPane().add(durationIndicator, BorderLayout.PAGE_END);
useHtmlControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setUseHtml(useHtmlControl.isSelected());
}
});
useHtmlControl.setSelected(false);
updaterControl.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.updateItems();
}
});
Timer counter = new Timer();
counter.schedule(new TimerTask() {
#Override
public void run() {
String previousCounter = durationIndicator.getText();
String newCounter = Integer.toString(
Integer.parseInt(previousCounter) + 1);
durationIndicator.setText(newCounter);
setTitle(newCounter);
}
}, 0, 100);
}
public static void main(String args[]) {
JListTest jlt = new JListTest();
jlt.pack();
jlt.setSize(300, 300);
jlt.setVisible( true );
}
}
The answer is pretty obvious - because Window title is not a Swing component, it's OS native entity.
So changes don't have to go through Swing Event Queue, but go to XDecoratedPeer.updateWMName directly in case of Unix and to some other class in other OSes.
The more interesting question would be how to avoid that UI blocking, but I don't think that's possible with just Swing, you'll have to implement some lazy loading, or rendering in batches.

GWT - Add and remove nodes in celltree

Here I have an complete and very easy example to dynamically add/remove
nodes to an celltree. My example is not working very well. It seems there
is an refresh problem. Only closing/expanding the nodes will show the correct
result. I also did not found any answer in this forum which fits to this problem.
Maybe somebody can try my example and tell me where the problem is.
Any other hint is also very appreciated.
Greetings, Marco
import java.util.ArrayList;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;
public class MyCelltreeTest implements EntryPoint {
private AbsolutePanel absolutePanel;
private CellTree cellTree;
private Button btnAdd;
private Button btnRemove;
private MyTreeModel myTreeModel;
private SingleSelectionModel<MyNode> selectionModelCellTree = null;
#Override
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
rootPanel.add(getAbsolutePanel(), 0, 0);
}
private AbsolutePanel getAbsolutePanel() {
if (absolutePanel == null) {
absolutePanel = new AbsolutePanel();
absolutePanel.setSize("612px", "482px");
absolutePanel.add(getCellTree(), 0, 0);
absolutePanel.add(getBtnAdd(), 265, 428);
absolutePanel.add(getBtnRemove(), 336, 428);
}
return absolutePanel;
}
private CellTree getCellTree() {
if (cellTree == null) {
myTreeModel = new MyTreeModel();
cellTree = new CellTree(myTreeModel, null);
cellTree.setSize("285px", "401px");
}
return cellTree;
}
private Button getBtnAdd() {
if (btnAdd == null) {
btnAdd = new Button("Add");
btnAdd.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
MyNode node = selectionModelCellTree.getSelectedObject();
if(node != null)
myTreeModel.addNew(node, "Bla");
}
});
}
return btnAdd;
}
private Button getBtnRemove() {
if (btnRemove == null) {
btnRemove = new Button("Remove");
btnRemove.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
MyNode node = selectionModelCellTree.getSelectedObject();
if(node != null)
myTreeModel.remove(node);
}
});
}
return btnRemove;
}
public class MyNode {
private String name;
private ArrayList<MyNode> childs; //nodes childrens
private MyNode parent; //track internal parent
private MyCell cell; //for refresh - reference to visual component
public MyNode(String name) {
super();
parent = null;
this.name = name;
childs = new ArrayList<MyNode>();
}
public void addSubMenu(MyNode m) {
m.parent = this;
childs.add(m);
}
public void removeMenu(MyNode m) {
m.getParent().childs.remove(m);
}
public boolean hasChildrens() {
return childs.size()>0;
}
public ArrayList<MyNode> getList() {
return childs;
}
public MyNode getParent() {
return parent;
}
public void setCell(MyCell cell) {
this.cell = cell;
}
public void refresh() {
if(parent!=null) {
parent.refresh();
}
if (cell!=null) {
cell.refresh(); //refresh tree
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class MyTreeModel implements TreeViewModel {
private MyNode officialRoot; //default not dynamic
private MyNode studentRoot; //default not dynamic
private MyNode testRoot; //default not dynamic
private MyNode root;
public MyNode getRoot() { // to set CellTree root
return root;
}
public MyTreeModel() {
selectionModelCellTree = new SingleSelectionModel<MyNode>();
root = new MyNode("root");
// Default items
officialRoot = new MyNode("Cat"); //some basic static data
studentRoot = new MyNode("Dog");
testRoot = new MyNode("Fish");
root.addSubMenu(officialRoot);
root.addSubMenu(studentRoot);
root.addSubMenu(testRoot);
}
//example of add add logic
public void addNew(MyNode myparent, String name) {
myparent.addSubMenu(new MyNode(name));
myparent.refresh(); //HERE refresh tree
}
public void remove(MyNode objToRemove) {
objToRemove.removeMenu(objToRemove);
objToRemove.refresh();
}
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
ListDataProvider<MyNode> dataProvider;
MyNode myValue = null;
if (value == null) { // root is not set
dataProvider = new ListDataProvider<MyNode>(root.getList());
} else {
myValue = (MyNode) value;
dataProvider = new ListDataProvider<MyNode>(myValue.getList());
}
MyCell cell = new MyCell(dataProvider); //HERE Add reference
if (myValue != null)
myValue.setCell(cell);
return new DefaultNodeInfo<MyNode>(dataProvider, cell, selectionModelCellTree, null);
}
#Override
public boolean isLeaf(Object value) {
if (value instanceof MyNode) {
MyNode t = (MyNode) value;
if (!t.hasChildrens())
return true;
return false;
}
return false;
}
}
public class MyCell extends AbstractCell<MyNode> {
ListDataProvider<MyNode> dataProvider; //for refresh
public MyCell(ListDataProvider<MyNode> dataProvider) {
super();
this.dataProvider = dataProvider;
}
public void refresh() {
dataProvider.refresh();
}
#Override
public void render(Context context, MyNode value, SafeHtmlBuilder sb) {
if (value == null) {
return;
}
sb.appendEscaped(value.getName());
}
}
}
Thanks Ümit for your explanation.
I tried the close-reopen version.
I have replaced my refresh method with the methods below.
Adding is working but removing not.
Very strange the whole topic. I'm very suprised that these basic
functions are not really supported by GWT.
Can somebody give me more help to run a real working example.
public void refresh() {
closeReopenTreeNodes(cellTree.getRootTreeNode());
}
private void closeReopenTreeNodes(TreeNode node) {
if(node == null) {
return;
}
for(int i = 0; i < node.getChildCount(); i++) {
if(node.getChildValue(i).equals(this)){
if(node.getParent() != null){
node.getParent().setChildOpen(i, false);
//node.getParent().setChildOpen(i, true);
}
node.setChildOpen(i, false);
node.setChildOpen(i, true);
}
TreeNode child = node.setChildOpen(i, node.isChildOpen(i));
closeReopenTreeNodes(child);
}
}
Here my third try:
This way is recommended by gwt-commiter.
Please see following issue:
http://code.google.com/p/google-web-toolkit/issues/detail?id=7160
Current status:
* Adding is possible
* Removing is possible if not last child!
So, last open point, refresh the tree if last open child!
package com.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;
public class MyCelltreeTest2 implements EntryPoint {
private AbsolutePanel absolutePanel;
private CellTree cellTree;
private Button btnAdd;
private Button btnRemove;
private MyTreeModel myTreeModel;
private SingleSelectionModel<MyNode> selectionModelCellTree = null;
private Map<MyNode, ListDataProvider<MyNode>> mapDataProviders = null;
private ListDataProvider<MyNode> rootDataProvider = null;
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
rootPanel.add(getAbsolutePanel(), 0, 0);
}
private AbsolutePanel getAbsolutePanel() {
if (absolutePanel == null) {
absolutePanel = new AbsolutePanel();
absolutePanel.setSize("612px", "482px");
absolutePanel.add(getCellTree(), 0, 0);
absolutePanel.add(getBtnAdd(), 265, 428);
absolutePanel.add(getBtnRemove(), 336, 428);
}
return absolutePanel;
}
private CellTree getCellTree() {
if (cellTree == null) {
myTreeModel = new MyTreeModel();
cellTree = new CellTree(myTreeModel, null);
cellTree.setSize("285px", "401px");
}
return cellTree;
}
private Button getBtnAdd() {
if (btnAdd == null) {
btnAdd = new Button("Add");
btnAdd.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
MyNode node = selectionModelCellTree.getSelectedObject();
myTreeModel.add(node, "Bla");
}
});
}
return btnAdd;
}
private Button getBtnRemove() {
if (btnRemove == null) {
btnRemove = new Button("Remove");
btnRemove.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
MyNode node = selectionModelCellTree.getSelectedObject();
myTreeModel.remove(node);
}
});
}
return btnRemove;
}
public class MyNode {
private String name;
private ArrayList<MyNode> childs; //nodes childrens
private MyNode parent; //track internal parent
public MyNode(String name) {
super();
parent = null;
this.name = name;
childs = new ArrayList<MyNode>();
}
public boolean hasChildrens() {
return childs.size()>0;
}
public ArrayList<MyNode> getList() {
return childs;
}
public MyNode getParent() {
return parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class MyTreeModel implements TreeViewModel {
public MyTreeModel() {
selectionModelCellTree = new SingleSelectionModel<MyNode>();
mapDataProviders = new HashMap<MyCelltreeTest2.MyNode, ListDataProvider<MyNode>>();
}
public void add(MyNode myparent, String name) {
MyNode child = new MyNode(name);
//root-node
if(myparent == null){
rootDataProvider.getList().add(child);
mapDataProviders.put(child, rootDataProvider);
}
else{
ListDataProvider<MyNode> dataprovider = mapDataProviders.get(myparent);
myparent.childs.add(child);
child.parent = myparent;
dataprovider.refresh();
}
}
public void remove(MyNode objToRemove) {
ListDataProvider<MyNode> dataprovider = mapDataProviders.get(objToRemove);
dataprovider.getList().remove(objToRemove);
// mapDataProviders.remove(objToRemove);
dataprovider.refresh();
dataprovider.flush();
if(objToRemove.parent != null){
ListDataProvider<MyNode> dataproviderParent = mapDataProviders.get(objToRemove.parent);
objToRemove.parent.childs.remove(objToRemove);
dataproviderParent.refresh();
dataproviderParent.flush();
}
else{
rootDataProvider.refresh();
rootDataProvider.flush();
}
}
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
if (value == null) { // root is not set
rootDataProvider = new ListDataProvider<MyNode>(new ArrayList<MyNode>());
MyCell cell = new MyCell();
return new DefaultNodeInfo<MyNode>(rootDataProvider, cell,
selectionModelCellTree, null);
} else {
MyNode myValue = (MyNode) value;
ListDataProvider<MyNode> dataProvider =
new ListDataProvider<MyNode>(myValue.childs);
MyCell cell = new MyCell();
for(MyNode currentNode : myValue.childs){
mapDataProviders.put(currentNode, dataProvider);
}
return new DefaultNodeInfo<MyNode>(dataProvider, cell,
selectionModelCellTree, null);
}
}
#Override
public boolean isLeaf(Object value) {
if (value instanceof MyNode) {
MyNode t = (MyNode) value;
if (!t.hasChildrens())
return true;
return false;
}
return false;
}
}
public class MyCell extends AbstractCell<MyNode> {
public MyCell() {
super();
}
#Override
public void render(Context context, MyNode value, SafeHtmlBuilder sb) {
if (value == null) {
return;
}
sb.appendEscaped(value.getName());
}
}
}
This is somehow a known problem with CellTree.
The reason for the refresh problem is that in the getNodeInfo() function you create a new ListDataProvider instance for each CellTree level.
The CellTree only updates/refreshes itself if you update the items in that ListDataProvider.
I believe that your removeMenu() and addSubMenu() functions add and remove items from the original list stored in your MyNode class but won't update the list in the corresponding ListDataProviders (you can try to check that in debug mode).
The reason why the CellTree is refreshed when you close and re
-open the nodes is because when you re-open the nodes the getNodeInfo() is called again and the whole CellTree structure will be constructed again (including the new menu or without the removed one respectively).
There are two possible solutions:
Keep a reference for each of the ListDataProviders somewhere and call remove/add on that list (although you do that I assume that the items are not really added/removed there).
Programatically close all nodes and re-open it.
Both are somehow a PITA to implement. Unfortunately there is no easy way around it.
I just clear the array of objects maintained in my data provider. I do this in onRangeChanged(final HasData<?> display). I guess I don't use a ListDataProvider here, I use something extending AbstractDataProvider<T> instead.
To add the node add it to your list within the onRangeChanged() method and then call updateRowData(). You can do this for a delete too.
I think I may have licked the problem...
Essentially I've extended and subclasses many parts of CellTree and have obtained an almost perfect working example. Too complex to document here, but suffice to say the solution involved using a node class where I stored the data provider within each node.
https://code.google.com/p/updatable-cell-tree/