jgoodies binding: using a JTextField with a formatted number? - swing

I am trying to bind a JTextField to a bean's field that is a double using JGoodies Binding:
JTextField myJTextField = ...
BeanAdapter adapter = ...
Bindings.bind(myJTextField,
ConverterFactory.createStringConverter(adapter.getValueModel("amplitude"),
new DecimalFormat("0.00000")));
This works, at least in the bean → JTextField direction. In the JTextField → bean direction, it has one hitch: if I start typing in the JTextField it takes my update immediately after the first digit after the decimal point, messes up the JTextField focus, and tweaks my JTextField value.
(the problem seems to come from trying to adapt a GUI's String to a model's double)
How do I fix this????
sample program that demonstrates this:
package com.example.test.gui;
import java.awt.GridLayout;
import java.beans.PropertyChangeListener;
import java.text.DecimalFormat;
import java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.adapter.BoundedRangeAdapter;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.beans.ExtendedPropertyChangeSupport;
import com.jgoodies.binding.value.ConverterFactory;
public class FloatPointBinding {
public static class MyModel {
private int x;
final private ExtendedPropertyChangeSupport changeSupport =
new ExtendedPropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener x) {
this.changeSupport.addPropertyChangeListener(x);
}
public void removePropertyChangeListener(PropertyChangeListener x) {
this.changeSupport.removePropertyChangeListener(x);
}
static private int clip(int a)
{
return Math.min(Math.max(a, -32768), 32767);
}
static private int d2i(double a) {
return clip((int) Math.floor(a*32768 + 0.5));
}
static private double i2d(int a) {
return (clip(a)/32768.0);
}
public void setXCount(int x) {
int oldX = this.x;
int newX = x;
this.x=newX;
this.changeSupport.firePropertyChange("x", i2d(oldX), i2d(newX));
this.changeSupport.firePropertyChange("XCount", oldX, newX);
}
public void setX(double x) { setXCount(d2i(x)); }
public double getX() { return i2d(this.x); }
public int getXCount() { return this.x; }
}
public static class MyView extends JFrame
{
public MyView(MyModel model, String title)
{
super(title);
JTextField jtf = new JTextField();
JSlider jsl = new JSlider();
jsl.setMinimum(-32768);
jsl.setMaximum(32767);
jsl.setMajorTickSpacing(4096);
jsl.setPaintTicks(true);
Hashtable labelTable = new Hashtable();
labelTable.put( new Integer( -32768 ), new JLabel("-1") );
labelTable.put( new Integer( 0 ), new JLabel("0") );
labelTable.put( new Integer( 32767 ), new JLabel("1") );
jsl.setLabelTable( labelTable );
jsl.setPaintLabels(true);
setLayout(new GridLayout());
add(jsl);
add(jtf);
BeanAdapter adapter = new BeanAdapter(model, true);
Bindings.bind(jtf,
ConverterFactory.createStringConverter(adapter.getValueModel("x"),
new DecimalFormat("0.#####")));
jsl.setModel(new BoundedRangeAdapter(adapter.getValueModel("XCount"), 0, -32768, 32767));
}
}
public static void main(String[] args)
{
MyModel model = new MyModel();
MyView view = new MyView(model, "FloatPointBinding");
view.pack();
view.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
view.setVisible(true);
}
}

I am not sure if this is what you are trying to solve, but if you change the binding to only commit on focus lost you shouldn't have that issue anymore. Just specify true as the third argument to the bind method below:
Bindings.bind(jtf,
ConverterFactory.createStringConverter(adapter.getValueModel("x"),
new DecimalFormat("0.#####")),
true);

Related

How to display a "result" inside a jTextField after clicking a jButton? [duplicate]

I'm in NetBeans 8.2 and I've constructed a nice jFrame GUI for a Binary-to-Decimal converter, I think I have the code in my two text fields correct but I can't figure out how to access the variables for my Button to perform operations on.
I have 3 method operations called parseBinary, isBinary, and illegal that I want to use to perform operations on my two text fields.
In NetBeans when you code a button the method is locked to private so that's my issue.
I will post all my of code and highlight where my issue is (near the bottom):
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Scanner;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Assignment2_gui extends javax.swing.JFrame
{
public static int parseBinary(String binary) throws NumberFormatException
{
if (!isBinary(binary))
{
throw new NumberFormatException("Invalid Format for a Binary String - Illegal character: " + illegal(binary));
}
int power = 0;
int decimal = 0;
for (int i = binary.length() - 1; i >= 0; i--)
{
if (binary.charAt(i) == '1')
{
decimal += Math.pow(2, power);
}
power++;
}
return decimal;
}
public static boolean isBinary(String binary)
{
for (char ch : binary.toCharArray())
{
if (ch != '1' && ch != '0')
{
return false;
}
}
return true;
}
public static char illegal(String iChar)
{
char test = 0;
char arr[] = iChar.toCharArray();
for(char cha : arr)
{
if (cha != '1' && cha != '0')
{
test = cha;
}
}
return test;
}
/**
* Creates new form Assignment2_gui
*/
public Assignment2_gui()
{
initComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
///////// the issue is with this jButton method and the two jTextField methods /////////
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
}
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
JTextField test1 = new JTextField("");
test1.setText(test1.getText());
}
private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {
JTextField test2 = new JTextField("");
test2.setText(test2.getText());
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Assignment2_gui().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JTextField jTextField1;
private javax.swing.JTextField jTextField2;
// End of variables declaration
}

How to make nearly 1,70,000 marker dots on JMapViewer? [duplicate]

I've got a slight problem, I'm writing a gps tracking app to track several objects at once. The data comes in over a serial interface, this is coming in fine from what I can tell. The issue is that I need to continually update the JPanel where the map is created and displayed.
public JPanel mapDisplay(){
JPanel mapPanel = new JPanel();
mapPanel.setSize(560, 540);
Coordinate start = new Coordinate (-34.9286, 138.6);
trackMap.addMapMarker(new MapMarkerDot(1Lat, 1Lon));
trackMap.setDisplayPosition(start,8);
System.out.println(1Lat);
mapPanel.add(trackMap);
mapPanel.setVisible(true);
return mapPanel;
}
This is what I have and it's happy to display the point once but won't update. If I print out the 1Lat variable in the serial method it continually prints, however it only does it once here.
A lot of the answers I've found refer to setting markers by arrays, however that won't work in this case as the objects I'm tracking could be anywhere.
Any help would be greatly appreciated :)
Is it possible to use a worker thread and not use an ArrayList? I would run the risk of missing data if I do.
Not necessarily. In a SwingWorker, your implementation of the doInBackground() method can publish() results as they become available. Note in particular that "Results from multiple invocations of publish() are often accumulated for a single invocation of process()." In your process(), simply loop through the List<Coordinate>, update the route and repaint() the map.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import org.openstreetmap.gui.jmapviewer.Coordinate;
import org.openstreetmap.gui.jmapviewer.JMapViewer;
import org.openstreetmap.gui.jmapviewer.MapPolygonImpl;
/**
* #see http://stackoverflow.com/a/37193636/230513
*/
public class MapWorkerTest {
private final List<Coordinate> route = new ArrayList<>();
private void display() {
JFrame f = new JFrame("MapWorker");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMapViewer map = new JMapViewer() {
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
#Override
public String getToolTipText(MouseEvent e) {
Coordinate c = (Coordinate) getPosition(e.getX(), e.getY());
return c.getLat() + " " + c.getLon();
}
};
map.setToolTipText("");
Coordinate start = new Coordinate(-34.9286, 138.6);
route.add(start);
MapPolygonImpl poly = new MapPolygonImpl(route);
poly.setColor(Color.blue);
map.addMapPolygon(poly);
map.setDisplayPosition(start, 10);
f.add(map);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
new MapWorker(map, start).execute();
}
private class MapWorker extends SwingWorker<Void, Coordinate> {
private final JMapViewer map;
private Coordinate last;
public MapWorker(JMapViewer map, Coordinate start) {
this.map = map;
this.last = start;
}
#Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
last = new Coordinate(last.getLat() + 0.0025, last.getLon() + 0.01);
publish(last);
Thread.sleep(1000);
}
return null;
}
#Override
protected void process(List<Coordinate> chunks) {
for (Coordinate c : chunks) {
route.add(c);
}
map.repaint();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new MapWorkerTest()::display);
}
}
Multiple route management left as a exercise.

How to visualize my R plot in my JFrame with JavaGD?

I am new to JRI/rJava/JavaGD and have some problems with it. I drew a simple R plot with JRI and want to include this plot in my customized JFrame. I added the GDCanvas in which the plot should appear to my JFrame. However the plot is not displayed in the GDCanvas, but opens in a new Frame. How can I visualize my R plot in my JFrame, instead of appearing in its own frame?
For me, another possibility would be to modify the new frame in which my plot pops up. But I couldn't add or modify anything there either. Is there a special way to modify frames that appear with JavaGD()?
Can someone please help me? Many thanks in advance.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.rosuda.JRI.Rengine;
import org.rosuda.javaGD.GDCanvas;
public class RjavaGD extends JFrame implements ActionListener {
private Rengine engine;
public static GDCanvas gdc;
private JButton btn;
public RjavaGD() {
super();
super.setTitle("My R Plot");
btn = new JButton("show plot");
btn.addActionListener(this);
gdc = new GDCanvas(400, 400);
gdc.setBackground(Color.PINK);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(btn, BorderLayout.PAGE_START);
this.getContentPane().add((GDCanvas) gdc, BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
// initialize R
engine = new Rengine(new String[] { "--vanilla" }, false, null);
engine.eval("library(JavaGD)");
engine.eval("Sys.putenv('JAVAGD_CLASS_NAME'='RjavaGDInterface')");
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new RjavaGD();
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btn) {
engine.eval("JavaGD()");
engine.eval("a <- c(1,2,3,2,4)");
engine.eval("plot(a,type=\"l\")");
gdc.initRefresh();
engine.end();
this.setTitle("new random plot");
}
}
}
import org.rosuda.javaGD.GDInterface;
public class RjavaGDInterface extends GDInterface {
public void gdOpen(double w, double h)
{
c = RjavaGD.gdc;
}
}
I used Sys.setenv() instead of Sys.putenv().
I also found a way to integrate the plot into my own customized frame, so that I can add buttons and other stuff directly below the plot, which was not possible with the standard frame that opens automatically.
This code worked fine for me:
import org.rosuda.JRI.Rengine;
import org.rosuda.javaGD.GDCanvas;
public class RjavaGD extends JFrame implements ActionListener {
private Rengine engine;
private JButton btn;
public RjavaGD() {
super();
super.setTitle("My R Plot");
btn = new JButton("show plot");
btn.addActionListener(this);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(btn, BorderLayout.PAGE_START);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btn) {
// initialize R
engine = new Rengine(new String[] { "--vanilla" }, false, null);
engine.eval("Sys.setenv('JAVAGD_CLASS_NAME'='RjavaGDInterface')");
engine.eval("library(JavaGD)");
engine.eval("JavaGD()");
engine.eval("a <- c(1,2,3,2,4)");
engine.eval("plot(a,type=\"l\")");
engine.end();
}
}
}
import org.rosuda.javaGD.GDInterface;
public class RjavaGDInterface extends GDInterface {
JFrame f;
#Override
public void gdOpen(double w, double h) {
super.gdOpen(w,h);
f = new JFrame();
f.setLayout(new BorderLayout());
c = new GDCanvas(w, h);
f.setTitle("New Plot");
f.getContentPane().add((GDCanvas) c, BorderLayout.CENTER);
f.getContentPane().add(buttonPanel(), BorderLayout.NORTH);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
private JPanel buttonPanel(){
JPanel p = new JPanel();
p.setBackground(Color.pink);
p.add(new JLabel("Options“));
p.add(new JButton("option1“))
return p;
}
}
I hope this will help other people with the same problem :)

Rendering/Refreshing a JTable after DnD operation?

I've to JTables. I drag a row from the first table and drop it to the second.
The DnD operation works fine so far, but how can easily refresh the second table after
dropping operation? I've implemented a TableModelListener, but it works only when I
double click on a line of a table.
My question: which event listener do I need to solve my problem? Any solutions or examples?
btw: the DnD operation is performing with the tranferHandler
ok here's some code:
TableExample for creating the to tables
ListHandler1 for DnD operations
SearchRenderer for updating row heights after DnD or table changings
please keep in mind that i wrote quickly. ..
Thanks and regards!
TableExample:
package GUI_Examples;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class TableExample implements TableModelListener{
String [] title = new String [] {"Title A", "Title B"};
String [] title2 = new String [] {"Title C", "Title D"};
Object [][] data = new String [][] {{"aaaaaaaaaaaa aaaaaa aaaaaaa", "bbbbbbbb bbbb bbbbbb bbbbbb"},
{"cccccccccc cccccccc ccccccc", "ddddddd ddd dddddddd dddddd"},
{"eeeeeeeeee eeeeeeee eeeeeee", "fffffff ffff ffffff fffffff"}};
Object [][] data2 = new String [][] {{"",""}};
private JTable table;
private JTable table2;
private JFrame frame;
private DefaultTableModel model;
private DefaultTableModel model2;
private JScrollPane pane1;
private JScrollPane pane2;
private SearchRenderer1 myRenderer;
private SearchRenderer1 myRenderer2;
TableExample() {} //constructor
public JPanel createTable() {
JPanel panel = new JPanel();
//creating tables and table models
model = new DefaultTableModel(data, title);
model2 = new DefaultTableModel(data2, title2);
table = new JTable(model);
table2 = new JTable(model2);
//setting renderers
myRenderer = new SearchRenderer1();
table.setDefaultRenderer(String.class, myRenderer);
table.getColumnModel().getColumn(0).setCellRenderer(myRenderer);
table.getColumnModel().getColumn(1).setCellRenderer(myRenderer);
myRenderer2 = new SearchRenderer1();
table2.setDefaultRenderer(String.class, myRenderer2);
table2.getColumnModel().getColumn(0).setCellRenderer(myRenderer2);
table2.getColumnModel().getColumn(1).setCellRenderer(myRenderer2);
//setting sizes
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getColumnModel().getColumn(0).setPreferredWidth(60);
table.getColumnModel().getColumn(1).setPreferredWidth(60);
table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table2.getColumnModel().getColumn(0).setPreferredWidth(60);
table2.getColumnModel().getColumn(1).setPreferredWidth(60);
//Drag&Drop operations
table.setDragEnabled(true);
table2.setDropMode(DropMode.INSERT);
table2.setTransferHandler(new ListHandler1(model2));
pane1 = new JScrollPane(table);
pane2 = new JScrollPane(table2);
pane1.setPreferredSize(new Dimension(150,300));
pane2.setPreferredSize(new Dimension(150,300));
updateRowHeights();
updateRowHeights2();
panel.add(pane1);
panel.add(pane2);
return panel;
}
void showTable() {
//create and show frame
JPanel testPanel = createTable();
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(testPanel);
frame.pack();
frame.setVisible(true);
}//showTable
void updateRowHeights() {
for (int row = 0; row < table.getRowCount(); row++) {
int rowHeight = table.getRowHeight();
Component comp = table.prepareRenderer(table.getCellRenderer(row, 1), row, 1);
rowHeight = Math.max(rowHeight, comp.getPreferredSize().height);
table.setRowHeight(row, rowHeight);
}
}
void updateRowHeights2() {
for (int row = 0; row < table2.getRowCount(); row++) {
int rowHeight = table2.getRowHeight();
Component comp2 = table2.prepareRenderer(table2.getCellRenderer(row, 1), row, 1);
rowHeight = Math.max(rowHeight, comp2.getPreferredSize().height);
table2.setRowHeight(row, rowHeight);
}
}
public static void main(String[] args) {
TableExample example = new TableExample();
example.showTable();
}//main
#Override
public void tableChanged(TableModelEvent e) {
updateRowHeights();
updateRowHeights2();
}
}//TableExample
ListHandler
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import javax.swing.TransferHandler;
import javax.swing.table.DefaultTableModel;
public class ListHandler1 extends TransferHandler {
DefaultTableModel model = new DefaultTableModel();
ListHandler1(DefaultTableModel tableModel) {
this.model=tableModel;
} //constructor
/**
*
*/
private static final long serialVersionUID = 1L;
/* canImport: This method tests suitability of a drop operation. Here we filter out the clipboard paste operations
* and allow only String drop operations. If the method returns false, the drop operation is cancelled.(non-Javadoc)
* #see javax.swing.TransferHandler#canImport(javax.swing.TransferHandler.TransferSupport)
*/
public boolean canImport(TransferSupport support) {
if (!support.isDrop()) {
return false;
}
return support.isDataFlavorSupported(DataFlavor.stringFlavor);
}
/*The importData() method transfers the data from the clipboard or from the drag and drop operation to the drop location.
* (non-Javadoc)
* #see javax.swing.TransferHandler#importData(javax.swing.TransferHandler.TransferSupport)
*/
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
Transferable transferable = support.getTransferable(); //The Transferable is the class, where the data is bundled.
String line;
try {
line = (String) transferable.getTransferData(DataFlavor.stringFlavor); //We retrieve our data.
} catch (Exception e) {
return false;
}
String item [] = line.split("\t");
model.addRow(new Object[]{item[0],item[1]});
return true;
}
}
SearchRenderer:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class SearchRenderer1 extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
public SearchRenderer1() {
setLineWrap(true);
setWrapStyleWord(true);
} //constructor
public Component getTableCellRendererComponent (JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column ) {
this.setText((String)value);
//for update row height
this.setSize(table.getColumnModel().getColumn(column).getWidth(),Short.MAX_VALUE);
if (isSelected) {
this.setBackground(new java.awt.Color(255, 240, 200));
}
else {
this.setBackground(new java.awt.Color(255, 255, 255));
}
return this;
}//getTableCellRendererComponent
}

Swing JTextfield DnD replace the existing text with the imported text

I have two text fields and I can drag and drop the text between them. What I want is that every time I drag the text it will replace the existing text data with the text which was dragged and dropped.
import java.awt.Container;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class DragDropText extends JFrame {
public static void main(String[] args) {
new DragDropText().setVisible(true);
}
public DragDropText() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField field1 = new JTextField("Life's a drag", 20);
JTextField field2 = new JTextField("and then you drop", 20);
field1.setDragEnabled(true);
field2.setDragEnabled(true);
Container content = getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
content.add(field1);
content.add(field2);
pack();
}
}
You can achieve the effect by creating and setting a subclass of TransferHandler.
This is an example that will work for any subclass of JTextComponent. You'll have to add the appropriate checks to make it robust.
You can find more info here: http://download.oracle.com/javase/tutorial/uiswing/dnd/transferhandler.html.
import java.io.*;
import java.awt.*;
import java.awt.datatransfer.*;
import javax.swing.*;
import javax.swing.text.*;
public class DragDropText extends JFrame {
public static void main(String[] args) {
new DragDropText().setVisible(true);
}
public DragDropText() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField field1 = new JTextField("Life's a drag", 20);
JTextField field2 = new JTextField("and then you drop", 20);
field1.setDragEnabled(true);
field2.setDragEnabled(true);
field1.setTransferHandler(new CustomTransferHandler());
field2.setTransferHandler(new CustomTransferHandler());
Container content = getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
content.add(field1);
content.add(field2);
pack();
}
}
class CustomTransferHandler extends TransferHandler {
public int getSourceActions(JComponent c) {
return COPY_OR_MOVE;
}
public Transferable createTransferable(JComponent c) {
return new StringSelection(((JTextComponent) c).getSelectedText());
}
public void exportDone(JComponent c, Transferable t, int action) {
if(action == MOVE)
((JTextComponent) c).replaceSelection("");
}
public boolean canImport(TransferSupport ts) {
return ts.getComponent() instanceof JTextComponent;
}
public boolean importData(TransferSupport ts) {
try {
((JTextComponent) ts.getComponent())
.setText((String) ts
.getTransferable()
.getTransferData(DataFlavor.stringFlavor));
return true;
} catch(UnsupportedFlavorException e) {
return false;
} catch(IOException e) {
return false;
}
}
}