JFace: ColumnLabelProvider override CellEditorLabelProvider - jface

I am implementing a JFace TableViewer where some of the columns are ComboBoxViewerCellEditor.
I am setting ColumnLabelProvider to each column and on addition to the columns with the combo box I am also setting EditingSupport.
The EditingSupport contain encapsulate also a LabelProvider within the ComboBoxViewerCellEditor.
All implementation is based on JFace MVC – i.e. viewers and providers without implementing event listeners.
The behavior is a s follow:
launching the table the values displayed OK – i.e. column label provider provide the right data.
launching the combo box within a column the values in the dropdown list shown OK, and selecting value works fine – i.e. combo box shows new value and data model change to new value
when leaving the combo box the value (label) shown in the combo box is back the one provided by the column label provider (in #1).
it seems that either I should not use both label providers or somehow refresh the data in the column label provider.
I am attaching my code, please look into columnViewer columnViewerTargetObjectModelAttr which has both ColumnLabelProvider and EditingSupport.
I'll be grateful for any advice,
thanks.
Yaron.
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ComboBoxViewerCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import myPackage.DataObjectAssociation;
import myPackage.DataObjectAssociations;
import myPackage.DataObjectAttribute;
import myPackage.DataObjectAttributeUI;
import myPackage.DataObjectUI;
public class ObjectModelAssociationPageMVC extends
ObjectModaelGenerationWizardPage {
private TableViewer omTableViewer;
private TableViewer assocTableViewer;
private Composite container;
public ObjectModelAssociationPageMVC(ISelection selection,
HanaServicesAdapter hanaServicesAdapter) {
super("wizardPage", selection, hanaServicesAdapter);
setTitle("Generate Object Model");
setDescription("This wizard generates object models based on selected tables and views");
this.hanaServicesAdapter = hanaServicesAdapter;
}
#Override
public void createControl(Composite parent) {
// main container
this.container = new Composite(parent, SWT.NULL);
GridLayout layout = new GridLayout(1, true);
container.setLayout(layout);
// om container
Composite omContainer = new Composite(container, SWT.NULL);
omContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false,
1, 1));
GridLayout omLayout = new GridLayout(1, true);
omContainer.setLayout(omLayout);
// ----- Objects List Label ------
Label objectModelLabel = new Label(omContainer, SWT.NULL);
objectModelLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
false, 1, 1));
objectModelLabel.setText("Create Object Models Association:");
// ----- Objects List ------
omTableViewer = new TableViewer(omContainer, SWT.BORDER | SWT.SELECTED);
omTableViewer.setContentProvider(new ArrayContentProvider());
omTableViewer
.addSelectionChangedListener(new ObjectModelTableViewerSelectionListener());
Table omTable = omTableViewer.getTable();
omTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1,
1));
omTable.setLinesVisible(true);
omTable.setHeaderVisible(true);
GridData omTableGridData = new GridData(SWT.FILL, SWT.FILL, true,
false, 1, 1);
omTableGridData.heightHint = omTable.getItemHeight() * 10
+ omTable.getHeaderHeight();
omTable.setLayoutData(omTableGridData);
// Column Object Name
TableViewerColumn col = new TableViewerColumn(omTableViewer, SWT.NONE);
col.getColumn().setText("Object Model Name");
col.getColumn().setWidth(200);
col.setLabelProvider(new ObjectModelNameColumnLabelProvider());
// Associations List Container
Composite assocContainer = new Composite(container, SWT.NULL);
assocContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
false, 1, 1));
GridLayout assocLayout = new GridLayout(2, false);
assocContainer.setLayout(assocLayout);
// ----- Associations List Label ------
Label assocLabel = new Label(assocContainer, SWT.NULL);
assocLabel.setText("Associations:");
assocLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false,
2, 1));
// Associations Table Container
Composite assocTableContainer = new Composite(assocContainer, SWT.NULL);
assocTableContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
true, false, 1, 1));
GridLayout assocTableLayout = new GridLayout(1, true);
assocTableContainer.setLayout(assocTableLayout);
// Associations add/remove buttons container
Composite assocButtonsContainer = new Composite(assocContainer,
SWT.NULL);
assocButtonsContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
true, false, 1, 1));
GridLayout assocButtonsLayout = new GridLayout(1, true);
assocButtonsContainer.setLayout(assocButtonsLayout);
// ----- Associations List ------
assocTableViewer = new TableViewer(assocTableContainer, SWT.BORDER
| SWT.MULTI | SWT.FULL_SELECTION);
assocTableViewer.setContentProvider(new ArrayContentProvider());
Table assocTable = assocTableViewer.getTable();
GridData assocTableGridData = new GridData(SWT.FILL, SWT.FILL, true,
false, 1, 1);
assocTableGridData.heightHint = assocTable.getItemHeight() * 10
+ assocTable.getHeaderHeight();
assocTable.setLayoutData(assocTableGridData);
assocTable.setLinesVisible(false);
assocTable.setHeaderVisible(true);
TableViewerColumn columnViewerAssocName = new TableViewerColumn(
assocTableViewer, SWT.NONE);
columnViewerAssocName.getColumn().setText("Association Name");
columnViewerAssocName
.setLabelProvider(new AssociationNameColumnLabelProvider());
columnViewerAssocName.getColumn().pack();
TableViewerColumn columnViewerSourceObjectModelAttr = new TableViewerColumn(
assocTableViewer, SWT.NONE);
columnViewerSourceObjectModelAttr.getColumn().setText(
"Source Object Model Attribute");
columnViewerSourceObjectModelAttr
.setLabelProvider(new SourceObjectModelAttributeNameColumnLabelProvider());
columnViewerSourceObjectModelAttr.getColumn().pack();
TableViewerColumn columnViewerTargetObjectModel = new TableViewerColumn(
assocTableViewer, SWT.NONE);
columnViewerTargetObjectModel.getColumn()
.setText("Target Object Model");
columnViewerTargetObjectModel
.setLabelProvider(new TargetObjectModelNameColumnLabelProvider());
EditingSupport targetObjectModelColumnEditingSupport = new TargetObjectModelColumnEditingSupport(
columnViewerTargetObjectModel.getViewer());
columnViewerTargetObjectModel
.setEditingSupport(targetObjectModelColumnEditingSupport);
columnViewerTargetObjectModel.getColumn().pack();
TableViewerColumn columnViewerTargetObjectModelAttr = new TableViewerColumn(
assocTableViewer, SWT.NONE);
columnViewerTargetObjectModelAttr.getColumn().setText(
"Target Object Model Attribute");
columnViewerTargetObjectModelAttr
.setLabelProvider(new TargetObjectModelAttributeNameColumnLabelProvider());
EditingSupport targetObjectModelAttributeColumnEditingSupport = new TargetObjectModelAttributeColumnEditingSupport(
columnViewerTargetObjectModel.getViewer());
columnViewerTargetObjectModelAttr
.setEditingSupport(targetObjectModelAttributeColumnEditingSupport);
columnViewerTargetObjectModelAttr.getColumn().pack();
TableViewerColumn columnViewerAssocCardinality = new TableViewerColumn(
assocTableViewer, SWT.NONE);
columnViewerAssocCardinality.getColumn().setText("Cardinality");
columnViewerAssocCardinality
.setLabelProvider(new CardinalityColumnLabelProvider());
columnViewerAssocCardinality.getColumn().pack();
assocTable.pack();
// ----- Associations List Buttons ------
Button addAssocButton = new Button(assocButtonsContainer, SWT.PUSH);
addAssocButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
false, 1, 1));
addAssocButton.setText("Add");
Button removeAssocButton = new Button(assocButtonsContainer, SWT.PUSH);
removeAssocButton.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
false, 1, 1));
removeAssocButton.setText("Remove");
// ------------ Create Objects ------------------
setControl(container);
}
class ObjectModelTableViewerSelectionListener implements
ISelectionChangedListener {
#Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection;
DataObjectUI dataObjectUI;
DataObjectAssociations dataObjectAssociations;
DataObjectAssociation[] dataObjectAssociation = null;
selection = (IStructuredSelection) omTableViewer.getSelection();
dataObjectUI = (DataObjectUI) selection.getFirstElement();
dataObjectAssociations = dataObjectUI.getAssociations();
if (dataObjectAssociations != null) {
List<DataObjectAssociation> list = dataObjectAssociations
.getAssociation();
dataObjectAssociation = list
.toArray(new DataObjectAssociation[list.size()]);
}
assocTableViewer.setInput(dataObjectAssociation);
// cellEditor.setInput(hanaServicesAdapter.getSelectedTablesViews()
// .toArray());
}
}
#Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
omTableViewer.setContentProvider(new ArrayContentProvider());
omTableViewer.setInput(hanaServicesAdapter.getSelectedTablesViews()
.toArray());
}
}
class ObjectModelNameColumnLabelProvider extends ColumnLabelProvider {
#Override
public String getText(Object element) {
DataObjectUI dataObjectUI = (DataObjectUI) element;
return dataObjectUI.getFileName();
}
}
class AssociationNameColumnLabelProvider extends ColumnLabelProvider {
#Override
public String getText(Object element) {
DataObjectAssociation dataObjectAssociation = (DataObjectAssociation) element;
return dataObjectAssociation.getName();
}
}
class TargetObjectModelNameColumnLabelProvider extends ColumnLabelProvider {
#Override
public String getText(Object element) {
DataObjectAssociation dataObjectAssociation = (DataObjectAssociation) element;
return dataObjectAssociation.getTarget();
}
}
class TargetObjectModelAttributeNameColumnLabelProvider extends
ColumnLabelProvider {
#Override
public String getText(Object element) {
DataObjectAssociation dataObjectAssociation = (DataObjectAssociation) element;
return dataObjectAssociation.getTargetAttribute();
}
}
class SourceObjectModelAttributeNameColumnLabelProvider extends
ColumnLabelProvider {
#Override
public String getText(Object element) {
DataObjectAssociation dataObjectAssociation = (DataObjectAssociation) element;
return dataObjectAssociation.getSourceAttribute();
}
}
class CardinalityColumnLabelProvider extends ColumnLabelProvider {
#Override
public String getText(Object element) {
DataObjectAssociation dataObjectAssociation = (DataObjectAssociation) element;
return dataObjectAssociation.getCardinality().toString();
}
}
public final class TargetObjectModelColumnEditingSupport extends
EditingSupport {
private ComboBoxViewerCellEditor cellEditor;
private TargetObjectModelColumnEditingSupport(ColumnViewer viewer) {
super(viewer);
}
#Override
protected CellEditor getCellEditor(Object element) {
cellEditor = new ComboBoxViewerCellEditor((Composite) getViewer()
.getControl(), SWT.READ_ONLY);
cellEditor.setLabelProvider(new LabelProvider() {
public String getText(Object element) {
return ((DataObjectUI) element).getFileName();
}
});
cellEditor.setContentProvider(new ArrayContentProvider());
String target = ((DataObjectAssociation) element).getTarget();
CCombo combo = cellEditor.getViewer().getCCombo();
// combo.select(combo.indexOf(target));
combo.setText(target);
cellEditor.setInput(hanaServicesAdapter.getSelectedTablesViews()
.toArray());
return cellEditor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
if (element instanceof DataObjectAssociation) {
DataObjectAssociation data = (DataObjectAssociation) element;
return data.getTarget();
}
return null;
}
#Override
protected void setValue(Object element, Object value) {
if (element instanceof DataObjectAssociation
&& value instanceof DataObjectUI) {
DataObjectAssociation data = (DataObjectAssociation) element;
String newValue = ((DataObjectUI) value).getFileName();
/* only set new value if it differs from old one */
if (!data.getTarget().equals(newValue)) {
data.setTarget(newValue);
}
}
}
}
public final class TargetObjectModelAttributeColumnEditingSupport extends
EditingSupport {
private ComboBoxViewerCellEditor cellEditor;
private TargetObjectModelAttributeColumnEditingSupport(
ColumnViewer viewer) {
super(viewer);
}
#Override
protected CellEditor getCellEditor(Object element) {
cellEditor = new ComboBoxViewerCellEditor((Composite) getViewer()
.getControl(), SWT.READ_ONLY);
cellEditor.setLabelProvider(new LabelProvider() {
public String getText(Object element) {
return ((DataObjectAttributeUI) element).getName();
}
});
cellEditor.setContentProvider(new ArrayContentProvider());
CCombo combo = cellEditor.getViewer().getCCombo();
// String targetObjectModel = targetObjectCombo.getText();
DataObjectUI dataObjectUI = hanaServicesAdapter
.getDataObjectUI(((DataObjectAssociation) element)
.getTarget());
cellEditor.setInput(dataObjectUI.getSelectedAttributesUI()
.toArray());
String attribute = ((DataObjectAssociation) element)
.getTargetAttribute();
combo.setText(attribute);
return cellEditor;
}
#Override
protected boolean canEdit(Object element) {
return true;
}
#Override
protected Object getValue(Object element) {
if (element instanceof DataObjectAssociation) {
DataObjectAssociation data = (DataObjectAssociation) element;
return data.getTargetAttribute();
}
return null;
}
#Override
protected void setValue(Object element, Object value) {
if (element instanceof DataObjectAssociation
&& value instanceof DataObjectAttributeUI) {
DataObjectAssociation data = (DataObjectAssociation) element;
String newValue = ((DataObjectAttributeUI) value).getName();
/* only set new value if it differs from old one */
if (!data.getTargetAttribute().equals(newValue)) {
data.setTargetAttribute(newValue);
}
}
}
}
}

you might want to try an update on setValue().
if (!data.getTargetAttribute().equals(newValue)) {
data.setTargetAttribute(newValue);
update(element, null);
}

Related

TornadoFX TableView. Scrolling the large amount of rows leads to UI freezing

I have a windows desktop application on Kotlin and I'm using JDK Zulu11 with JavaFX and TornadoFX 2.0.0.
I faced the problem with scrolling of large amount of rows (~4mln) in the TableView.
I have something like a player and when it starts I just need to do autoscroll to the row corresponding to the player current position. So to make playing smooth I do it by calling scrollTo method every 50 milliseconds, 20 times per second.
I observed that approximately at 300000 UI starts freezing and at 500000 it is almost dead.
When I increase the delay from 50ms to 200ms or 500ms the situation is the same, UI gets freeze.
When I used JDK Zulu1.8 with JavaFX and TornadoFX 1.7.2 just for check all was perfect, all is playing very smooth and fast enough. With Oracle JDK 1.8 all is ok also.
But I need to migrate to JDK 11 because I have some important dependencies.
So the question is what is wrong with JDK 11(JavaFX) and TornadoFX 2.0.0 and how it can be fixed?
Thanks a lot for any help.
PS: Here is the minimal reproducible example, I just found some TableView example on javacodegeeks and modified it, so please chek with JDK1.8 and with OpenJDK11, I used Azul Zulu 11.
Also here is the video with demonstration.
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.paint.Color;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.TableColumn;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
public class FxTableViewExample1 extends Application {
public static class Book {
private SimpleIntegerProperty index;
private SimpleStringProperty title;
private SimpleStringProperty author;
public Book () {
}
public Book (Integer i, String s1, String s2) {
index = new SimpleIntegerProperty(i);
title = new SimpleStringProperty(s1);
author = new SimpleStringProperty(s2);
}
public int getIndex() {
return index.get();
}
public void setIndex(int index) {
this.index.set(index);
}
public String getTitle() {
return title.get();
}
public void setTitle(String s) {
title.set(s);
}
public String getAuthor() {
return author.get();
}
public void setAuthor(String s) {
author.set(s);
}
#Override
public String toString() {
return (index.get() + ": " + title.get() + ", by " + author.get());
}
}
private static final Integer COUNT = 10000000;
private static final Integer DELTA = 5000;
private static final Integer PERIOD = 50;
public static final EventType<Event> ScrollEventType = new EventType<>("ScrollEvent");
public static final EventType<Event> StopEventType = new EventType<>("StopEvent");
public static class ScrollEvent extends Event {
public Integer position = 0;
public ScrollEvent(Integer position) {
super(ScrollEventType);
this.position = position;
}
}
public static class StopEvent extends Event {
public StopEvent() {
super(StopEventType);
}
}
private TableView<Book> table;
private ObservableList<Book> data;
private Text actionStatus;
private Button startButton;
private Button stopButton;
private Integer count = 0;
private SimpleIntegerProperty currentPositionProperty = new SimpleIntegerProperty(0);
private Timer timer = null;
public static void main(String [] args) {
Application.launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Table View Example 1");
// Books label
Label label = new Label("Books");
label.setTextFill(Color.DARKBLUE);
label.setFont(Font.font("Calibri", FontWeight.BOLD, 36));
HBox labelHb = new HBox();
labelHb.setAlignment(Pos.CENTER);
labelHb.getChildren().add(label);
// Table view, data, columns and properties
table = new TableView<>();
data = getInitialTableData();
table.setItems(data);
TableColumn<Book, Integer> indexCol = new TableColumn<>("Index");
indexCol.setCellValueFactory(new PropertyValueFactory<Book, Integer>("index"));
TableColumn<Book, String> titleCol = new TableColumn<Book, String>("Title");
titleCol.setCellValueFactory(new PropertyValueFactory<Book, String>("title"));
TableColumn<Book, String> authorCol = new TableColumn<Book, String>("Author");
authorCol.setCellValueFactory(new PropertyValueFactory<Book, String>("author"));
table.getColumns().setAll(indexCol, titleCol, authorCol);
table.setPrefWidth(450);
table.setPrefHeight(300);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.getSelectionModel().selectedIndexProperty().addListener(
new RowSelectChangeListener());
// Status message text
actionStatus = new Text();
actionStatus.setFill(Color.FIREBRICK);
startButton = new Button("Play");
stopButton = new Button("Stop");
stopButton.setDisable(true);
currentPositionProperty.addListener(new ChangeListener<Number>() {
#Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
Platform.runLater(new Runnable() {
#Override
public void run() {
table.scrollTo(newValue.intValue());
table.getSelectionModel().select(newValue.intValue());
}
});
}
});
primaryStage.addEventHandler(ScrollEventType, new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (event.getEventType() == ScrollEventType) {
currentPositionProperty.set(((ScrollEvent)event).position);
}
}
});
primaryStage.addEventHandler(StopEventType, new EventHandler<Event>() {
#Override
public void handle(Event event) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
});
startButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
count = 0;
startButton.setDisable(true);
stopButton.setDisable(false);
if (timer == null) {
timer = new Timer(true);
timer.schedule(new TimerTask() {
#Override
public void run() {
count++;
int position = count * DELTA;
if (position >= COUNT) {
Event.fireEvent(primaryStage, new ScrollEvent(COUNT));
Event.fireEvent(primaryStage, new StopEvent());
} else {
Event.fireEvent(primaryStage, new ScrollEvent(position));
}
}
}, 0, PERIOD);
}
}
});
stopButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
startButton.setDisable(false);
stopButton.setDisable(true);
if (timer != null) {
timer.cancel();
timer = null;
}
}
});
HBox hbox = new HBox(20);
hbox.setPadding(new Insets(25, 25, 25, 25));
hbox.getChildren().addAll(startButton, stopButton);
// Vbox
VBox vbox = new VBox(20);
vbox.setPadding(new Insets(25, 25, 25, 25));
vbox.getChildren().addAll(labelHb, table, actionStatus, hbox);
// Scene
Scene scene = new Scene(vbox, 500, 475); // w x h
primaryStage.setScene(scene);
primaryStage.show();
// Select the first row
table.getSelectionModel().select(0);
Book book = table.getSelectionModel().getSelectedItem();
actionStatus.setText(book.toString());
} // start()
private class RowSelectChangeListener implements ChangeListener<Number> {
#Override
public void changed(ObservableValue<? extends Number> ov,
Number oldVal, Number newVal) {
int ix = newVal.intValue();
if ((ix < 0) || (ix >= data.size())) {
return; // invalid data
}
Book book = data.get(ix);
actionStatus.setText(book.toString());
}
}
private ObservableList<Book> getInitialTableData() {
List<Book> list = new ArrayList<>();
int i = 0;
while (i < COUNT) {
list.add(new Book(i++, "The Thief", "Fuminori Nakamura"));
list.add(new Book(i++, "Of Human Bondage", "Somerset Maugham"));
list.add(new Book(i++, "The Bluest Eye", "Toni Morrison"));
list.add(new Book(i++, "I Am Ok You Are Ok", "Thomas Harris"));
list.add(new Book(i++, "Magnificent Obsession", "Lloyd C Douglas"));
list.add(new Book(i++, "100 Years of Solitude", "Gabriel Garcia Marquez"));
list.add(new Book(i++, "What the Dog Saw", "Malcolm Gladwell"));
list.add(new Book(i++, "The Fakir", "Ruzbeh Bharucha"));
list.add(new Book(i++, "The Hobbit", "J.R.R. Tolkien"));
list.add(new Book(i++, "Strange Life of Ivan Osokin", "P.D. Ouspensky"));
list.add(new Book(i++, "The Hunt for Red October", "Tom Clancy"));
list.add(new Book(i++, "Coma", "Robin Cook"));
}
return FXCollections.observableList(list);
}
}
The problem was resolved by using OpenJDK11 and separate OpenJFX15 instead of Zulu JDK11+JFX.

JTable for JPanel with multiple type JComponent (Swing)

This is a long question, but all code is needed (I was thinking a basic question, with not common components).
I need to build a JTable with multiple Columns with multiple type Custom JPanel (with JSlider + JComboBox + JTextField) in only one Column.
I was reading: http://pekalicious.com/blog/custom-jpanel-cell-with-jbuttons-in-jtable/
In this question, I will use one Column with only one Customized JPanel with name PanelSpinnerRadioButton.
The Custom Panel:PanelSpinnerRadioButton.java
public class PanelSpinnerRadioButton extends JPanel {
private final JRadioButton jrbOption01= new JRadioButton("01");
private final JRadioButton jrbOption02 = new JRadioButton("12");
private final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
private final JPanel jpPanelSpinnerRadioButton = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
jpPanelSpinnerRadioButton.setLayout(new BoxLayout(jpPanelSpinnerRadioButton, BoxLayout.LINE_AXIS));
jpPanelSpinnerRadioButton.add(jrbOption01);
jpPanelSpinnerRadioButton.add(jrbOption02);
jpPanelSpinnerRadioButton.add(Box.createRigidArea(new Dimension(5,0)));
jpPanelSpinnerRadioButton.add(new JSeparator(JSeparator.VERTICAL));
jpPanelSpinnerRadioButton.add(Box.createRigidArea(new Dimension(5,0)));
jpPanelSpinnerRadioButton.add(jspnValues);
//Change States of RadioButtons (will be readOnly, ButtonGroup is not needed)
jrbOption02.setSelected(data.getOption());
jrbOption01.setSelected(!data.getOption());
//Change States of Spinner
((SpinnerNumberModel)jspnValues.getModel()).setValue(data.getFrom());
((SpinnerNumberModel)jspnValues.getModel()).setMaximum(data.getSize());
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpPanelSpinnerRadioButton);
}
// Used in PSRBTableCellEditor.getCellEditorValue()
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer)((SpinnerNumberModel)jspnValues.getModel()).getValue(),
(Integer)((SpinnerNumberModel)jspnValues.getModel()).getMaximum()
);
}
}
Here the Image Result of before Custom JPanel
Data Type for Custom Panel:PanelSpinnerRadioButtonData.java
public class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() { return opt02; }
public Integer getFrom() { return from; }
public Integer getSize() { return size; }
}
Now the coded to handle my Custom JPanel (with inner JComponents)
the Table Model:PSRBTableModel.java
public class PSRBTableModel extends AbstractTableModel {
private final Object[][] data;
private final Object[] columns;
public PSRBTableModel(Object[][] data, Object[] columns) {
// super();
this.data = data;
this.columns = columns;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[rowIndex][columnIndex] instanceof PanelSpinnerRadioButton) {
return (PanelSpinnerRadioButton)data[rowIndex][columnIndex];
}
return data[rowIndex][columnIndex];
}
}
return null;
}
public int getColumnCount() {
return ((columns == null) ? 0: columns.length);
}
public int getRowCount() {
return ((data == null) ? 0: data.length);
}
public Class getColumnClass(int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
return PanelSpinnerRadioButton.class;
}
return data[0][columnIndex].getClass();
}
}
return null;
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if (data != null) {
if (data.length > 0) {
if (data[0][columnIndex] instanceof PanelSpinnerRadioButton) {
//PanelSpinnerRadioButton Is not Editable
return false;
}
}
}
return true;
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
public String getColumnName(int columnIndex) {
return (String)columns[columnIndex];
}
}
Now the Renderer:PSRBTableCellRenderer.java
public class PSRBTableCellRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Object output = null;
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
}
return (Component)output;
}
}
And the EditorCell:PSRBTableCellEditor.java
public class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
protected Object output;
PSRBTableCellEditor() {
}
public Object getCellEditorValue() {
//Returns the value contained in the editor.
if (output instanceof PanelSpinnerRadioButton) {
return ((PanelSpinnerRadioButton)output).getData();
}
return null;
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//Sets an initial value for the editor.
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
return (PanelSpinnerRadioButton)output;
}
return null;
}
}
Test the Before Code (I'm working with JFrame)
String[] hdrsObjects = new String[]{"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][hdrsObjects.length];
objectMatrix[0][0] = new PanelSpinnerRadioButton();
objectMatrix[1][0] = new PanelSpinnerRadioButton();
objectMatrix[2][0] = new PanelSpinnerRadioButton();
JTable jtbl = new JTable(new PSRBTableModel(objectMatrix, hdrsObjects));
//jtbl.setDefaultRenderer(PanelSpinnerRadioButton.class, new PSRBTableCellRenderer());
//jtbl.setDefaultEditor(PanelSpinnerRadioButton.class, new PSRBTableCellEditor());
jtbl.getColumn("PanelSpinnerRadioButton Class Column").setCellRenderer(new PSRBTableCellRenderer());
jtbl.getColumn("PanelSpinnerRadioButton Class Column").setCellEditor(new PSRBTableCellEditor());
add(new JScrollPane(jtbl));
But I can't see the JTable with (3 rows with Custom JPanel 'PanelSpinnerRadioButton')
I have this exception...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.plaf.synth.SynthTableUI.paintCell(SynthTableUI.java:684)
at javax.swing.plaf.synth.SynthTableUI.paintCells(SynthTableUI.java:580)
at javax.swing.plaf.synth.SynthTableUI.paint(SynthTableUI.java:364)
at javax.swing.plaf.synth.SynthTableUI.update(SynthTableUI.java:275)
at javax.swing.JComponent.paintComponent(JComponent.java:780)
at javax.swing.JComponent.paint(JComponent.java:1056)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JViewport.paint(JViewport.java:728)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:306)
at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
at javax.swing.JComponent.paint(JComponent.java:1042)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
at java.awt.Container.paint(Container.java:1975)
at java.awt.Window.paint(Window.java:3912)
at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
QUESTION
What's wrong?
Why I can't see the JTable with 3 PanelSpinnerRadioButton?
EDITION
Please consider this scenario (Another Custom JPanel handled by the same TableCellRenderer PSRBTableCellRenderer and TableCellEditor PSRBTableCellEditor)
class PanelButton extends JPanel {
private final JPanel jpPanelButton = new JPanel();
// the ActionListener does not matter now
JButton jbtAction = new JButton("Action");
PanelButton() {
this(new PanelButtonEmpty());
}
PanelButton(PanelButtonEmpty data) {
super();
jpPanelButton.setLayout(new BoxLayout(jpPanelButton, BoxLayout.LINE_AXIS));
jpPanelButton.add(jbtAction);
/*Overridable method call in constructor*/
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0/*64*/));
add(jpPanelButton);
}
public PanelButtonEmpty getData() {
return new PanelButtonEmpty();
}
public void setData(PanelButtonEmpty data) {
}
}
I was thinking in a totally empty class (to cast the value in TableCellRenderer PSRBTableCellEditor)
class PanelButtonEmpty {
PanelButtonEmpty() { }
//public boolean getLazy() { return true; }
//public void setLazy(boolean b) {}
}
In this case I have two types of Custom JPanel for this reason I have
for TableCellEditor
public class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private Object output;
#Override public Object getCellEditorValue() {
if (output instanceof PanelSpinnerRadioButton) {
return ((PanelSpinnerRadioButton)output).getData();
}
if (output instanceof PanelButton) {
return ((PanelButton)output).getData();
}
return null;
}
#Override public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
return (PanelSpinnerRadioButton)output;
}
if (value instanceof PanelButtonEmpty) {
output = new PanelButton((PanelButtonEmpty)value);
return (PanelButton)output;
}
return null;
}
}
for TableCellRenderer
public class PSRBTableCellRenderer implements TableCellRenderer {
private Object output = null;
#Override public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
}
if (value instanceof PanelButtonEmpty) {
output = new PanelButton((PanelButtonEmpty)value);
}
return (Component)output;
}
}
QUESTIONS
How to avoid your Second Warning (in the new scenario)?
It is a waste to create each time a component in the TableCellRenderer#getTableCellRendererComponent(...).
How to handle with Objects different to here described?
PD:
I'm not sure to put this second part question in another post with the same source code...
objectMatrix[0][0] = new PanelSpinnerRadioButton();
Should be set PanelSpinnerRadioButtonData to the TableModel, rather than a component such as PanelSpinnerRadioButton.
output = new PanelSpinnerRadioButton((PanelSpinnerRadioButtonData)value);
It is a waste to create each time a component in the TableCellRenderer#getTableCellRendererComponent(...).
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableTest {
public JComponent makeUI() {
String[] hdrsObjects = {"PanelSpinnerRadioButton Class Column"};
Object[][] objectMatrix = new Object[3][hdrsObjects.length];
objectMatrix[0][0] = new PanelSpinnerRadioButtonData(false, 10, 40);
objectMatrix[1][0] = new PanelSpinnerRadioButtonData(true, 20, 40);
objectMatrix[2][0] = new PanelSpinnerRadioButtonData(false, 30, 40);
JTable table = new JTable(new DefaultTableModel(objectMatrix, hdrsObjects));
table.setRowHeight(30);
TableColumn tc = table.getColumn("PanelSpinnerRadioButton Class Column");
tc.setCellRenderer(new PSRBTableCellRenderer());
tc.setCellEditor(new PSRBTableCellEditor());
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
try {
for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TableTest().makeUI());
f.setSize(240, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class PanelSpinnerRadioButtonData {
private boolean opt02 = false;
private Integer from = 0;
private Integer size = 1;
PanelSpinnerRadioButtonData() {
this(false, 5, 10);
}
PanelSpinnerRadioButtonData(boolean opt02, Integer from, Integer size) {
this.opt02 = opt02;
this.from = from;
this.size = size;
}
public boolean getOption() {
return opt02;
}
public Integer getFrom() {
return from;
}
public Integer getSize() {
return size;
}
}
class PanelSpinnerRadioButton extends JPanel {
public final JRadioButton jrbOption01 = new JRadioButton("01");
public final JRadioButton jrbOption02 = new JRadioButton("12");
public final JSpinner jspnValues = new JSpinner(new SpinnerNumberModel(5, 0, 10, 1));
private final JPanel panel = new JPanel();
PanelSpinnerRadioButton() {
this(new PanelSpinnerRadioButtonData(false, 20, 40));
}
PanelSpinnerRadioButton(PanelSpinnerRadioButtonData data) {
super();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(jrbOption01);
panel.add(jrbOption02);
panel.add(Box.createRigidArea(new Dimension(5, 0)));
panel.add(new JSeparator(JSeparator.VERTICAL));
panel.add(Box.createRigidArea(new Dimension(5, 0)));
panel.add(jspnValues);
ButtonGroup bg = new ButtonGroup();
bg.add(jrbOption01);
bg.add(jrbOption02);
((SpinnerNumberModel) jspnValues.getModel()).setMaximum(data.getSize());
setData(data);
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
setBackground(new Color(0, 0, 0, 0));
add(panel);
}
public void setData(PanelSpinnerRadioButtonData data) {
if (data.getOption()) {
jrbOption02.setSelected(true);
} else {
jrbOption01.setSelected(true);
}
((SpinnerNumberModel) jspnValues.getModel()).setValue(data.getFrom());
}
// Used in PSRBTableCellEditor.getCellEditorValue()
public PanelSpinnerRadioButtonData getData() {
return new PanelSpinnerRadioButtonData(
jrbOption02.isSelected(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getValue(),
(Integer) ((SpinnerNumberModel) jspnValues.getModel()).getMaximum());
}
}
class PSRBTableCellRenderer implements TableCellRenderer {
private final PanelSpinnerRadioButton renderer = new PanelSpinnerRadioButton();
#Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
renderer.setData((PanelSpinnerRadioButtonData) value);
}
return renderer;
}
}
class PSRBTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private final PanelSpinnerRadioButton editor = new PanelSpinnerRadioButton();
#Override public Object getCellEditorValue() {
return editor.getData();
}
#Override public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
if (value instanceof PanelSpinnerRadioButtonData) {
editor.setData((PanelSpinnerRadioButtonData) value);
}
return editor;
}
}

ChoiceBox with custom Item in a TableView

I have a
private TableView<Indicators> tableviewIndicators;
with column
private TableColumn<Indicators, WindowsItem> tablecolumnFrame;
public static class WindowsItem {
CustomInternalWindow chrt;
private WindowsItem(CustomInternalWindow _chrt) {
chrt = _chrt;
}
public String toString() {
return chrt.getTitle();
}
}
private Indicators(String tl, WindowsItem chrt, String pne, Boolean sel) {
this.tool_col = new SimpleStringProperty(tl);
if (chrt == null) {
this.chart_col = new SimpleStringProperty("");
} else {
this.chart_col = new SimpleStringProperty(chrt.toString());
}
this.pane_col = new SimpleStringProperty(pne);
this.on_col = new SimpleBooleanProperty(sel);
this.chrt = chrt;
}
public String getTool() {
return tool_col.get();
}
public void setTool(String tl) {
tool_col.set(tl);
}
public WindowsItem getChart() {
return chrt;
}
public void setChart(WindowsItem _chrt) {
System.out.println("Indicators::setChart "+chrt.toString());
chrt = _chrt;
}
public String getPane() {
return pane_col.get();
}
public void setPane(String pne) {
pane_col.set(pne);
}
public Boolean getOn() {
return on_col.get();
}
public void setOn(boolean sel) {
on_col.set(sel);
}
public SimpleBooleanProperty onProperty() {
return on_col;
}
public SimpleStringProperty toolProperty() {
return tool_col;
}
public SimpleStringProperty chartProperty() {
return chart_col;
}
public SimpleStringProperty paneProperty() {
return pane_col;
}
}
tablecolumnFrame.setCellValueFactory(new PropertyValueFactory<Indicators, WindowsItem>("chart"));
How can I add a combobox or choicebox in tablecolumnFrame?
The following code
tablecolumnFrame.setCellFactory(new Callback<TableColumn<Indicators, WindowsItem>, TableCell<Indicators, WindowsItem>>() {
#Override
public TableCell<Indicators, WindowsItem> call(TableColumn<Indicators, WindowsItem> param) {
TableCell<Indicators, WindowsItem> cell = new TableCell<Indicators, WindowsItem>() {
#Override
public void updateItem(WindowsItem item, boolean empty) {
super.updateItem(item, empty);
if(empty){
return;
}
if (item != null) {
//final ChoiceBox<WindowsItem> choice = new ChoiceBox<>();
final ComboBox<WindowsItem> choice = new ComboBox<>();
int itemsInTab = chartsInTab.getChildren().size();// dimensione del contenuto del tab, compreso il pane
CustomInternalWindow winItem;
//
for (int i = 0; i < itemsInTab; i++) {
if (chartsInTab.getChildren().get(i) instanceof CustomInternalWindow) {
winItem = (CustomInternalWindow) chartsInTab.getChildren().get(i);
choice.getItems().add(new WindowsItem(winItem));
//choice.getItems().add(winItem.toString());
System.out.println("winItem.toString() "+winItem.toString());
}
}
return this error
SEVERE: javafx.scene.control.Control loadSkinClass Failed to load skin 'StringProperty [bean: TableRow[id=null, styleClass=cell indexed-cell table-row-cell], name: skinClassName, value: com.sun.javafx.scene.control.skin.TableRowSkin]' for control TableRow[id=null, styleClass=cell indexed-cell table-row-cell]
Why do you need special property? You can create ListView with ComboBox quite easily:
ObservableList<WindowsItem> windowsItems = FXCollections.observableArrayList();
ObservableList<WindowsItem> data = FXCollections.observableArrayList();
final ListView<WindowsItem> listView = new ListView<>(data);
listView.setEditable(true);
listView.setItems(data);
listView.setCellFactory(ComboBoxListCell.forListView(windowsItems));

resizing component in jtable cell

I am trying to resize a slider inside a jtable cell. But when resizing the column header, I do pass in the concerned code (method getTableCellRendererComponent for column one), but nothing happens (the slider is not resized??).
below is the code of my renderer :
public class NavigationDataModelRenderer extends JLabel implements TableCellRenderer {
private JSlider slider = null;
public NavigationDataModelRenderer()
{
super();
}
public NavigationDataModelRenderer(int tolerance)
{
super();
slider = new JSlider(tolerance * -3,tolerance *3);
slider.setPaintTicks(true);
slider.setMajorTickSpacing(tolerance);
slider.setUI(new SpreadSliderUI(slider));
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column)
{
Component comp = null;
if (table.getModel()!= null && table.getModel() instanceof NavigationDataModel)
{
NavigationDataModel model = (NavigationDataModel) table.getModel();
Object o = table.getModel().getValueAt(row, column);
this.setText(o.toString());
if (column == 1)
{//slider
if (model.getList() != null && model.getList().get(0)!= null && model.getList().get(row) != null)
{
slider.setValue((Integer)o);
}
comp = slider;
slider.setSize(table.getCellRect(row, column, false).getSize());
}
else if (column == 2)
{
if (((Integer)o) == Integer.MAX_VALUE)
{
this.setText("Invalid");
}
}
else
{
comp = this;
}
}
return comp;
}
}
thanks for your help.
I encounter this problem because I use a BasicSliderUI for my slider. Now in my renderer, I set a new BasicSliderUI for my slider each time I enter getTableCellRendererComponent(...) and the slider is resized.
public class GrowingCellRenderer extends DefaultTableCellRenderer
{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column)
{
Component renderer = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
//renderer.setBackground(Color.red);
renderer.setSize(getMinimumSize());
table.setRowHeight(row, renderer.getHeight());
return renderer;
}
}
public static void main(String[] args)
{
GrowingCellRenderer testInstance = new GrowingCellRenderer();
final Date dateProjectStart = new Date(); //Start the "project" today
final JTable jtab = new JTable(TableTools.createTestData(dateProjectStart));
jtab.setDefaultRenderer(String.class, testInstance);
}

How to build a custom draw2d layoutmanager?

I would like to have a layout manager that can arrange two elements as follows:
one main element ABCDEF centered
one "postscript" element XYZ, positioned on the top right corner of the encapsulating figure
For example:
***********XYZ*
* ABCDEF *
***************
Can I use an existing layoutmanager for this? How do I build a custom layout manager that supports it?
Many thanks for your advice.
You can do that by using XYLayout.
There is a sample you can build on:
import org.eclipse.draw2d.AbstractLayout;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LayoutManager;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.Panel;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class HHH {
public static void main(String[] args) {
Display d = new Display();
Shell s = new Shell();
s.setLayout(new FillLayout());
FigureCanvas canvas = new FigureCanvas(s);
Figure content = new Figure();
content.setLayoutManager(new XYLayout());
PostScriptedFigure figure = new PostScriptedFigure();
content.add(figure, new Rectangle(100, 100, -1, -1));
figure.setMainFigure(new Label("The Main figure"));
figure.setPostScriptFigure(new Label("ps"));
figure.setBorder(new LineBorder());
canvas.setContents(content);
s.setSize(600, 500);
s.open();
while (!s.isDisposed()) {
if (!d.readAndDispatch()) {
d.sleep();
}
}
}
}
class PostScriptedFigure extends Panel {
private IFigure mainFigure, postScriptFigure;
private class PostScriptedLayoutManager extends AbstractLayout {
#Override
public void layout(IFigure container) {
final Rectangle clientArea = container.getClientArea();
final IFigure mainFigure = getMainFigure();
final IFigure postScriptFigure = getPostScriptFigure();
if (mainFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(mainFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
final Rectangle mainClientArea = clientArea.getCopy();
if (postScriptFigure != null) {
mainClientArea.shrink(new Insets(postScriptFigure.getPreferredSize().height(), 0, 0, 0));
}
bounds.translate(mainClientArea.getCenter().getTranslated(bounds.getSize().getScaled(0.5f).getNegated()));
mainFigure.setBounds(bounds);
}
if (postScriptFigure != null) {
final Rectangle bounds = new PrecisionRectangle();
bounds.setSize(postScriptFigure.getPreferredSize(SWT.DEFAULT, SWT.DEFAULT));
bounds.translate(clientArea.getTopRight().getTranslated(bounds.getSize().getNegated().width(), 0));
postScriptFigure.setBounds(bounds);
}
// note that other potentionally added figures are ignored
}
#Override
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
final Rectangle rect = new PrecisionRectangle();
final IFigure mainFigure = getMainFigure();
if (mainFigure != null) {
rect.setSize(mainFigure.getPreferredSize());
}
final IFigure postScriptFigure = getPostScriptFigure();
if (postScriptFigure != null) {
rect.resize(mainFigure != null ? 0 : postScriptFigure.getPreferredSize().width() , postScriptFigure.getPreferredSize().height());
}
// note that other potentionally added figures are ignored
final Dimension d = rect.getSize();
final Insets insets = container.getInsets();
return new Dimension(d.width + insets.getWidth(), d.height + insets.getHeight()).union(getBorderPreferredSize(container));
}
}
public PostScriptedFigure() {
super.setLayoutManager(new PostScriptedLayoutManager());
}
#Override
public void setLayoutManager(LayoutManager manager) {
// prevent from setting wrong layout manager
}
public IFigure getMainFigure() {
return mainFigure;
}
public void setMainFigure(IFigure mainFigure) {
if (getMainFigure() != null) {
remove(getMainFigure());
}
this.mainFigure = mainFigure;
add(mainFigure);
}
public IFigure getPostScriptFigure() {
return postScriptFigure;
}
public void setPostScriptFigure(IFigure postScriptFigure) {
if (getPostScriptFigure() != null) {
remove(getPostScriptFigure());
}
this.postScriptFigure = postScriptFigure;
add(postScriptFigure);
}
}