DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Two AI Agents, One Database: Solving Concurrent Updates With Optimistic Locking
  • A Non-Expiring AKS Deployment Token Could Read Secrets Across Three Namespaces
  • Share Delta Lake Tables Between Databricks and Snowflake
  • Designing Memory Architecture for Stateful AI Agents: Short-Term Context and Long-Term Persistence

Trending

  • 5 Proven Strategies for Modernizing Legacy .NET Applications
  • Why Your Test Automation Is Always Behind the Code And the Architecture That Fixes It
  • Giving AI Agents Safe Access to Legacy Systems: Introducing legacy2mcp
  • Git Branching Strategies for Maintainable Test Automation

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Data Engineering
  3. Data
  4. A Custom Float PropertyEditor

A Custom Float PropertyEditor

By 
Alied Pérez
·
Mar. 01, 11 · Interview
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
11.8K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

Both Java SE and the NetBeans Platform have default property editors for several primitive and common data types. These are suitable for most cases and most of us almost never need to worry about it. There are, however, those few moments where the one-size-fits-all approach does not actually fit. For instance, the default float editor is a text editor:

For general-purpose cases, this should be fine. Now, what if you want to restrict the values your property can have or have other control over it? Or simply give the user a more comfortable control for data input, like a JSpinner:

Most of what I'll show was taken from the NetBeans tutorials and Javadoc, so I will not extend in details what you can find easily there.

First, lets implement the PropertyEditor and the InlineEditor (don't forget to <Shift+Ctrl+I> to fix imports):

public abstract class FloatPropertyEditor
extends PropertyEditorSupport
implements ExPropertyEditor, InplaceEditor.Factory{

protected InplaceEditor ed = null;
protected SpinnerNumberModel model;

public FloatPropertyEditor(Object source, SpinnerNumberModel model) {
super(source);
this.model = model;
}

public FloatPropertyEditor(SpinnerNumberModel model) {
this.model = model;
}

@Override
public String getAsText() {
Float d = (Float)getValue();
if (d == null) {
return "0.0";
}
return NumberFormat.getNumberInstance().format(d.floatValue());
}

@Override
public void setAsText(String s) {
try {
setValue(new Float(
NumberFormat.getNumberInstance().parse(s).floatValue()));
} catch (ParseException ex) {
setValue(Float.valueOf(0.0f));
}
}

@Override
public void attachEnv(PropertyEnv env) {
env.registerInplaceEditorFactory(this);
}

@Override
public InplaceEditor getInplaceEditor() {
if (ed == null) {
ed = new FloatInplaceEditor(model);
}
return ed;
}

protected static class FloatInplaceEditor implements InplaceEditor {

private final JSpinner spinner;
private PropertyEditor editor = null;
private PropertyModel model;

public FloatInplaceEditor(SpinnerNumberModel model) {
this.spinner = new JSpinner(model);
}

@Override
public void connect(PropertyEditor propertyEditor, PropertyEnv env) {
editor = propertyEditor;
reset();
}

@Override
public JComponent getComponent() {
return spinner;
}

@Override
public void clear() {
//avoid memory leaks:
editor = null;
model = null;
}

@Override
public Object getValue() {
return spinner.getValue();
}

@Override
public void setValue(Object object) {
try {
spinner.setValue(object);
} catch (IllegalArgumentException e) {
spinner.setValue(null);
}
}

@Override
public boolean supportsTextEntry() {
return true;
}

@Override
public void reset() {
Float d = (Float) editor.getValue();
if (d != null) {
setValue(d);
}
}

@Override
public KeyStroke[] getKeyStrokes() {
return new KeyStroke[0];
}

@Override
public PropertyEditor getPropertyEditor() {
return editor;
}

@Override
public PropertyModel getPropertyModel() {
return model;
}

@Override
public void setPropertyModel(PropertyModel propertyModel) {
this.model = propertyModel;
}

@Override
public boolean isKnownComponent(Component component) {
return component == spinner || spinner.isAncestorOf(component);
}

@Override
public void addActionListener(ActionListener actionListener) {
//do nothing - not needed for this component
}

@Override
public void removeActionListener(ActionListener actionListener) {
//do nothing - not needed for this component
}
}
}


So far, we've been closely following the tutorials. Notice that the FloatPropertyEditor class is abstract. This is because PropertyEditor classes should have a default constructor (more on this below).

Not much of a gain, maybe, but now you have a JSpinner as an editor. Now imagine you are developing a 3D "bodies in space" application. You can select an item and you can change its dimensions and coordinates at will. Coordinates can have any real value, whether negative, zero, or positive (besides the practical dimensional limits your universe might have), while dimensions must be at least be zero.

This is where the abstract plays its role. By inheriting the class above, you can decide which values our properties can have. For coordinate properties, set this class as PropertyEditor:

public class CoordinateFloatPropertyEditor extends FloatPropertyEditor {

public CoordinateFloatPropertyEditor() {
super(new SpinnerNumberModel(0.0, -100000.0, 100000.0, 0.5));
}
}

And, for dimension properties, use this one, instead:
public class DimensionFloatPropertyEditor extends FloatPropertyEditor {

public DimensionFloatPropertyEditor() {
super(new SpinnerNumberModel(0.0, 0.09999, 100000.0, 0.5));
}
}


It's up to you to decide the maximum, minimum, and step values, and tweak this sample for your needs.

I want also to add that this is part of a real application, from where I was inspired to write this article. I'll be further extending this subject in the next posts.

Thanks for you attention.
Muchas gracias por su atención.

Data Types

Opinions expressed by DZone contributors are their own.

Related

  • Two AI Agents, One Database: Solving Concurrent Updates With Optimistic Locking
  • A Non-Expiring AKS Deployment Token Could Read Secrets Across Three Namespaces
  • Share Delta Lake Tables Between Databricks and Snowflake
  • Designing Memory Architecture for Stateful AI Agents: Short-Term Context and Long-Term Persistence

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook