JComboBox - How to render names for time values - java

I want to display a JComboBox that shows the text values but stores the actual int values for the user to select for session timeout values.
private static final String[] SESSION_TIMEOUT_OPTION_NAMES = new String[]{
"5 Minutes",
"10 Minutes",
"15 Minutes",
...
};
private static final Integer[] SESSION_TIMEOUT_OPTION_VALUES = new Integer[]{
TimeConstants.FIVE_MINUTES,
TimeConstants.TEN_MINUTES,
TimeConstants.FIFTEEN_MINUTES,
...
};
I know this can be done with a ListCellRenderer but the only way I could see it working is with a big mapping Basically alongs the lines of:
sessionTimeoutJComboBox.setRenderer(new ListCellRenderer<Integer>()
{
private DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
#Override
public Component getListCellRendererComponent(...)
{
JLabel jlabel = (JLabel)defaultRenderer.getListCellRendererComponent(...);
for(int x=0; x<SESSION_TIMEOUT_OPTION_VALUES.length; x++)
{
if(SESSION_TIMEOUT_OPTION_VALUES[x] == value)
{
jlabel.setText(SESSION_TIMEOUT_OPTION_NAMES[x]);
return jlabel;
}
}
throw new RuntimeException("Invalid mapping");
}
});
Is there a better way to do this?
Btw the reason I want to do this is so that I can just do
(int)sessionTimeoutJComboBox.getSelectedItem();
and not have to care more than that.

You could use enums:
private enum TimeConstants {
FIVE_MINUTES("5 Minutes", 5),
TEN_MINUTES("10 Minutes", 10);
private final String text;
private final int value;
private TimeConstants( String text, int value ) {
this.text = text;
this.value = value;
}
public int getValue() {
return this.value;
}
#Override
public String toString() {
return this.text;
}
}
And heres how to use them with JComboBox:
TimeConstants[] constants = {TimeConstants.FIVE_MINUTES, TimeConstants.TEN_MINUTES};
JComboBox<TimeConstants> combo = new JComboBox<TimeConstants>(constants);
System.out.println( "Selected value: " + ((TimeConstants)combo.getSelectedItem()).getValue());

You could use a Map instead of doing the mappings manually. i.e.:
Map<Integer, String> timeoutOptions = new HashMap<>();
timeoutOptions.put( TimeConstants.FIVE_MINUTES, "5 Minutes");
...
and then in your renderer you could just do this:
sessionTimeoutJComboBox.setRenderer(new DefaultListCellRenderer<Integer>()
{
#Override
public Component getListCellRendererComponent(...)
{
JLabel label = (JLabel)super.getListCellRendererComponent( ... );
label.setText( timeoutOptions.get( value ) );
return label;
}
});

Related

Javafx: TableView get graphic node of a particular Table cell based on row column

I've a JavaFX table view component, and is dynamically loading the data with ComboBox as setGraphic for individual columns. I want to added ComboBox at cellFactory.
Now when the user select the first ComboBox, the next column ComboBox has to be set accordingly. For this purpose I've used a selection listener, but how can I get ComboBox of other TableColumn?
Please find the snapshot, of what I need:
Here is the Snippet of TableView:
TableColumn< ModelInput, String > colCalibration = new TableColumn<>( "Calibration" );
TableColumn< ModelInput, String > colSamplingX = new TableColumn<>( "Sampling point X" );
TableColumn< ModelInput, String > colSamplingY = new TableColumn<>( "Sampling point Y" );
List< TableColumn< ModelInput, String > > tableColList =
Stream.of( colCalibration, colSamplingX, colSamplingY )
.collect( Collectors.toList() );
tableviewCalibMatching.getColumns().addAll( tableColList );
//initialize
colCalibration.setCellFactory( param -> new TableCell< ModelInput, String >() {
#Override
public void updateItem( String item, boolean empty ) {
super.updateItem( item, empty );
if( empty ) {
setText( null );
} else {
ComboBox< String > comboBoxCalibMatchingNames = new ComboBox<>( listCalibNames );
comboBoxCalibMatchingNames.setPrefWidth( splitWidth );
comboBoxCalibMatchingNames.getSelectionModel().selectedItemProperty()
.addListener( (ChangeListener< String >)( observable, oldValue,
newValue ) -> {
//TODO
//How can I get ComboBox of other TableColumn, need to set according to current //selection
} );
setGraphic( comboBoxCalibMatchingNames );
setContentDisplay( ContentDisplay.GRAPHIC_ONLY );
}
}
} );
colSamplingX.setCellFactory( param -> new TableCell< ModelInput, String >() {
#Override
public void updateItem( String item, boolean empty ) {
super.updateItem( item, empty );
if( empty ) {
setText( null );
} else {
final ComboBox< String > comboBox = new ComboBox<>();
setGraphic( comboBox );
setContentDisplay( ContentDisplay.GRAPHIC_ONLY );
}
}
} );
colSamplingY.setCellFactory( param -> new TableCell< ModelInput, String >() {
#Override
public void updateItem( String item, boolean empty ) {
super.updateItem( item, empty );
if( empty ) {
setText( null );
} else {
final ComboBox< String > comboBox = new ComboBox<>();
setGraphic( comboBox );
setContentDisplay( ContentDisplay.GRAPHIC_ONLY );
}
}
} );
Try this:
public class Test
{
private final TableView<ModelInput> tableviewCalibMatching = new TableView<>();
private final TableColumn<ModelInput, String> colCalibration = new TableColumn<>("Calibration");
private final TableColumn<ModelInput, String> colSamplingX = new TableColumn<>("Sampling Point X");
private final TableColumn<ModelInput, String> colSamplingY = new TableColumn<>("Sampling Point Y");
private final ObservableList<String> listCalibNames = FXCollections.observableArrayList();
private final ObservableList<String> listSamplingXNames = FXCollections.observableArrayList();
private final ObservableList<String> listSamplingYNames = FXCollections.observableArrayList();
private final ObservableList<ModelInput> items = FXCollections.observableArrayList();
public Test()
{
tableviewCalibMatching.setItems(items);
tableviewCalibMatching.getColumns().addAll(colCalibration, colSamplingX, colSamplingY);
colCalibration.setCellFactory(ComboBoxTableCell.forTableColumn(listCalibNames));
colSamplingX.setCellFactory(ComboBoxTableCell.forTableColumn(listSamplingXNames));
colSamplingY.setCellFactory(ComboBoxTableCell.forTableColumn(listSamplingYNames));
colCalibration.setCellValueFactory(new PropertyValueFactory<>("calibration"));
colSamplingX.setCellValueFactory(new PropertyValueFactory<>("samplingX"));
colSamplingY.setCellValueFactory(new PropertyValueFactory<>("samplingY"));
colCalibration.setOnEditCommit(event ->
{
final String newCalibrationValue = event.getNewValue();
event.getRowValue().setCalibration(newCalibrationValue);
// You can change the logic here based on what you need
event.getRowValue().setSamplingX(listSamplingXNames.get(1));
event.getRowValue().setSamplingY(listSamplingXNames.get(1));
});
colSamplingX.setOnEditCommit(event ->
{
final String newSamplingXValue = event.getNewValue();
event.getRowValue().setSamplingX(newSamplingXValue);
});
colSamplingY.setOnEditCommit(event ->
{
final String newSamplingYValue = event.getNewValue();
event.getRowValue().setSamplingY(newSamplingYValue);
});
}
public static class ModelInput
{
private final StringProperty calibration = new SimpleStringProperty();
private final StringProperty samplingX = new SimpleStringProperty();
private final StringProperty samplingY = new SimpleStringProperty();
public final StringProperty calibrationProperty()
{
return this.calibration;
}
public final String getCalibration()
{
return this.calibrationProperty().get();
}
public final void setCalibration(final String calibration)
{
this.calibrationProperty().set(calibration);
}
public final StringProperty samplingXProperty()
{
return this.samplingX;
}
public final String getSamplingX()
{
return this.samplingXProperty().get();
}
public final void setSamplingX(final String samplingX)
{
this.samplingXProperty().set(samplingX);
}
public final StringProperty samplingYProperty()
{
return this.samplingY;
}
public final String getSamplingY()
{
return this.samplingYProperty().get();
}
public final void setSamplingY(final String samplingY)
{
this.samplingYProperty().set(samplingY);
}
}
}
You can get current row from TableCell::getIndex().
First, update objects contained within the TableView items.
comboBoxCalibMatchingNames.setOnAction(event -> {
tableView.getItems().get(getIndex()).someProperty().set(anyValue1);
tableView.getItems().get(getIndex()).otherProperty().set(anyValue2);
});
It fires TableCell::updateItem(T, boolean) of updated columns with new value.
You must update selection of ComboBox on updateItem.
// in updteItem code on colSamplingX
final ComboBox< String > comboBox = new ComboBox<>();
comboBox.getSelectionModel().select(item); // Select updated item.
setGraphic( comboBox );
setContentDisplay( ContentDisplay.GRAPHIC_ONLY );

Using hashmap to display data in JTextField and update it

Below is code that creates items that have code number name, price and quantity respectively.
public class StockData {
private static class Item {
Item(String n, double p, int q) {
name = n;
price = p;
quantity = q;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public int getQuantity() {
return quantity;
}
private final String name;
private final double price;
private int quantity;
}
public final static Map<String, Item> stock = new HashMap();
static {
stock.put("00", new Item("Bath towel", 5.50, 10));
stock.put("11", new Item("Plebney light", 20.00, 5));
stock.put("22", new Item("Gorilla suit", 30.00, 7));
stock.put("33", new Item("Whizz games console", 50.00, 8));
stock.put("44", new Item("Oven", 200.00, 4));
}
public static Map<String, Item> getStock() {
return stock;
}
public static String getName(String key) {
Item item = stock.get(key);
if (item == null) {
return null; // null means no such item
} else {
return item.getName();
}
}
public static double getPrice(String key) {
Item item = stock.get(key);
if (item == null) {
return -1.0; // negative price means no such item
} else {
return item.getPrice();
}
}
public static int getQuantity(String key) {
Item item = stock.get(key);
if (item == null) {
return -1; // negative quantity means no such item
} else {
return item.getQuantity();
}
}
public static void update(String key, int extra) {
Item item = stock.get(key);
if (item != null) {
item.quantity += extra;
}
}
}
And here is a different class that is a part of my gui which looks like: http://imgur.com/Jhc4CAz
and my idea is you type the code of an item eg. 22 then type how many you would like to add to the stock so for example 5 you click add so it adds to the variable but immidiately updates the text in the box as you can see on the screen.
I really got myself puzzled with hashmap / list I don't think there is a point copying all the data from hashmap to list and pretty much multiplying it there must be a better way to achieve this.
public class UpdateStock extends JFrame implements ActionListener {
JTextField stockNo = new JTextField(4);
JButton addButton = new JButton("ADD");
JSpinner quantitySlider = new JSpinner();
JTextArea catalog = new JTextArea(7, 30);
List items = new ArrayList();
public UpdateStock(){
setLayout(new BorderLayout());
setBounds(100, 100, 450, 500);
setTitle("Update Stock");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel top = new JPanel();
add("North", top);
JPanel middle = new JPanel();
add("Center", middle);
top.add(stockNo);
top.add(quantitySlider);
top.add(addButton);
catalog.setLineWrap(true);
catalog.setWrapStyleWord(true);
catalog.setEditable(false);
middle.add(new JScrollPane(catalog));
for(String key : StockData.getStock().keySet()) {
catalog.append("Item: " + key +"\n");
items.add(StockData.getName(key));
catalog.append("Name: " + StockData.getName(key) +
" Price: " + StockData.getPrice(key) +
" Qty: " + StockData.getQuantity(key)+"\n");
}
setResizable(false);
setVisible(true);
}
}
your code immediately puts text in the JTextArea because you tell it to. It's right there in the constructor:
for(String key : StockData.getStock().keySet()) {
catalog.append("Item: " + key +"\n");
items.add(StockData.getName(key));
catalog.append("Name: " + StockData.getName(key) +
" Price: " + StockData.getPrice(key) +
" Qty: " + StockData.getQuantity(key)+"\n");
}
If you want to wait until the user picks an item before setting any text, then register an ActionListener on addButton using its addActionListener() method. Use that listener's actionPerformed() method to set the text. Don't forget to remove the code shown above from your constructor, too.
I see you already know about the ActionListener class, since it's implemented by UpdateStock, but it's a little weird (though totally valid!) to do it that way; I don't think I've seen many subclasses of JFrame implement it directly. The usual pattern is to use an anonymous ActionListener and just register that instead. If you really want to use UpdateStock as an ActionListener, then you'll need an actionPerformed() method defined in UpdateStock and you'll need to register this as an action listener on your button.

GWT java CELLTABLE MouseHover Buttoncell

So i have here a Cellbutton :
Column<dateiles, String> column_2 = new Column<dateiles, String>(new ButtonCell()) {
#Override
public String getValue(dateiles object) {
int s = object.comments.size();
String ss = String.valueOf(s);
return ss;
}
};
cellTable.addColumn(column_2, "Comments");
cellTable.setColumnWidth(column_2, "100px");
i want to add to my buttons for each cell column a Tooltip but how is it possible
this.addCellPreviewHandler(new Handler<Tabletype>() {
#Override
public void onCellPreview(final CellPreviewEvent<Tabletype> event) {
int columnID = event.getColumn();
}
});
}
Just replace tabletype with the object you definded when instantiating the table ( The T of CellTable<T> ) Then with the columnID you can detect the right column.

How to remove a row from the Cell Table

At first I used the Grid.
After creating a new version of the GWT, I want to replace the Grid on the CellTable.
Check out the javadoc for details. My example is like the one you'll find there (just a little extended):
public void onModuleLoad() {
final CellTable<Row> table = new CellTable<Row>();
TextColumn<Row> firstColumn = new TextColumn<Starter.Row>() {
#Override
public String getValue(Row object) {
return object.firstColumn;
}
};
table.addColumn(firstColumn, "header one");
TextColumn<Row> secondColumn = new TextColumn<Starter.Row>() {
#Override
public String getValue(Row object) {
return object.secondColumn;
}
};
table.addColumn(secondColumn, "header two");
TextColumn<Row> thirdColumn = new TextColumn<Starter.Row>() {
#Override
public String getValue(Row object) {
return object.thirdColumn;
}
};
table.addColumn(thirdColumn, "header three");
table.setRowCount(getList().size());
final ListDataProvider<Row> dataProvider = new ListDataProvider<Starter.Row>(getList());
dataProvider.addDataDisplay(table);
final SingleSelectionModel<Row> selectionModel = new SingleSelectionModel<Starter.Row>();
table.setSelectionModel(selectionModel);
Button btn = new Button("delete entry");
btn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Row selected = selectionModel.getSelectedObject();
if (selected != null) {
dataProvider.getList().remove(selected);
}
}
});
RootPanel.get().add(table);
RootPanel.get().add(btn);
}
private class Row {
private String firstColumn;
private String secondColumn;
private String thirdColumn;
public Row(String firstColumn, String secondColumn, String thirdColumn) {
this.firstColumn = firstColumn;
this.secondColumn = secondColumn;
this.thirdColumn = thirdColumn;
}
}
private LinkedList<Row> getList() {
LinkedList<Row> list = new LinkedList<Row>();
list.add(new Row("first", "entry", "foo"));
list.add(new Row("second", "entry", "foo"));
list.add(new Row("third", "entry", "foo"));
list.add(new Row("fourth", "entry", "foo"));
return list;
}
Or you can just run the cycle like that
#UiHandler("combo")
public void onChange(ChangeEvent e) {
textBoxes.clear();
searchFields.clear();
while(resultsTable.getColumnCount()!=0) {
resultsTable.removeColumn(0);
}
resultsTable.redraw();
Where resultsTable is a CellTable
CellTable as part of new DataPresentationWidgets used just to display data. So you should delete according member from list of data which CellTable using to display.

How do I know if increment/decrement on JSpinner is pressed?

I have a few JSpinners and they are numeric values starting at 10 and can be incremented until 99.
In my program the user has 15 points to disperse evenly across 6 skills. Every JSpinner has an EventListener to detect if its pressed, but more specifically I need to know which button was pressed so I know which action to take. They dont want to take a point off of strength and have it decrement the Total Points by 1, Instead if the Decrement is pressed it should Add 1.
What would be the best method to execute this?
(Also I am using NetBeans so a bit of the program is autoGenerated.)
Presumably you are somewhere inside a ChangeListener's stateChanged method - take a look at ChangeEvent#getSource()
Ok, your edit made my original answer pretty pointless.
Would creating your own SpinnerModel be a viable option?
I encountered the same problem, this is how I solved the implementation for my actions scenario:
First I collect all arrow buttons:
private static HashMap<String, BasicArrowButton> getSpinnerButtons(JSpinner spinner, String[] arrowNames) {
final Stack<String> arrows = new Stack<String>();
arrows.addAll( Arrays.asList( arrowNames ) );
final HashMap<String, BasicArrowButton> buttons = new HashMap<String, BasicArrowButton>();
while (buttons.size()<2) {
for (final Component c : spinner.getComponents()) {
if (c instanceof BasicArrowButton) {
final BasicArrowButton bab = (BasicArrowButton)c;
for (final String sName : arrows) {
if (sName.equals(bab.getName())&&!buttons.containsKey(sName)) {
buttons.put(sName,bab);
break;
}
}
}
}
}
return buttons;
}
Then I attach some listener:
final String KEY_PROP = ".DIRECTION";
final String BS = spinner.getName(), BN="Spinner.nextButton", BP="Spinner.previousButton";
final String BSKEY = BS+KEY_PROP, BNKEY = BN+KEY_PROP, BPKEY = BP+KEY_PROP;
final HashMap<String, BasicArrowButton> buttons = getSpinnerButtons(spinner, new String[]{BN,BP});
spinner.putClientProperty( BSKEY, 1000);
spinner.putClientProperty( BNKEY, buttons.get(BN).getDirection()*+10000);
spinner.putClientProperty( BPKEY, buttons.get(BP).getDirection()*-10000);
final PropertyChangeListener pcl = new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
final JSpinner spinnerRef = ((JSpinner)evt.getSource());
final String pName = evt.getPropertyName();
final short swing = Short.parseShort( String.valueOf(evt.getOldValue()) );
final short val = Short.parseShort( String.valueOf(evt.getNewValue()) );
if (Math.abs(swing)<2D)
System.out.printf("This is a DIRECTION CHANGE\nOld Direction=%s;\nNew Direction=%s;\nProp Value: %s", swing, val, spinnerRef.getClientProperty(pName) ).println();
else //arrows
System.out.printf("This is the CURRENT DIRECTION\nArrow=%s;\nDirection=%s;\nProp Value: %s", swing, val, spinnerRef.getClientProperty(pName) ).println();
System.out.println("==============");
}
};
spinner.addPropertyChangeListener(BSKEY, pcl);
spinner.addPropertyChangeListener(BNKEY, pcl);
spinner.addPropertyChangeListener(BPKEY, pcl);
final ActionListener spinnerActions = new ActionListener() {
private short oldDir=0;
#Override
public void actionPerformed(ActionEvent e) {
final BasicArrowButton bab = ((BasicArrowButton)e.getSource());
final short swingDir = (short)bab.getDirection();
final short newDir = (swingDir!=SwingConstants.NORTH&&swingDir!=SwingConstants.WEST) ? Integer.valueOf(-1).shortValue() : Integer.valueOf(+1).shortValue();
bab.getParent().firePropertyChange(bab.getName()+KEY_PROP, swingDir*1000, newDir);
bab.getParent().firePropertyChange(bab.getParent().getName()+KEY_PROP, oldDir, newDir);
this.oldDir=newDir;
}
};
buttons.get(BP).addActionListener(spinnerActions);
buttons.get(BN).addActionListener(spinnerActions);

Categories