Read-only JSpinner?

This may seem a little weird, but bear with me; I think the use case is valid.

I am writing an abstract java.beans.Customizer that makes use of the JGoodies Binding framework, specifically the PresentationModel class. You need not know any details about this class except that it makes working with Java Beans properties very simple and allows many views to reflect changes in a common underlying model (the bean itself).

Users of this Customizer who subclass it typically need to create some kind of Swing widget and bind it to a bean property, like so:

this.bind(this.ageSpinner,"age");

As I hope is clear this means bind the Customizer's bean property "age" to the ageSpinner component, which, for the sake of this question, let's assume is a JSpinner.

Now, it just so happens that getAge() happens to be a computed property (that is, there is no setter).

I would like it to be the case that if someone decides to bind a JSpinner to a read-only property that the spinner would not permit edits of any kind.

I would also like it to be the case, however, that the user could, if they so desired, select text in the JSpinner's editor. This means that jSpinner.setEnabled(false) doesn't cut it.

JSpinner does not support an "editable" property, and its editor already has a read-only JFormatted text field. What I need to do is disable any effect the spinner's buttons may have on its associated JFormattedTextField. What's the best way of doing this?

Thanks,

Laird

[1563 byte] By [ljnelsona] at [2007-11-26 17:50:35]
# 1
I actually don't have a solution for you, but I have a question. What happens if a JSpinner is used and the bean doesn't have a setter? Are you going to get an exception or will the value not get set? If it's the latter, won't the JSpinner value revert as soon as it loses focus?
Jasprea at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...
# 2
If you have control over the JSpinner, you can set the model to a custom SpinnerModel that ignores calls to setValue.
Jasprea at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...
# 3
> JSpinner does not support an "editable" property,((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().setEditable(false);
Michael_Dunna at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...
# 4

Hi, Michael; try your solution. The buttons still work, and the value still gets set. Thanks anyhow for your time.

What's really needed is a way to disable the buttons, but the buttons are UI-delegate specific. I'm inclined to go with a previous poster's suggestion of a custom model whose setValue() does nothing. This seems kind of icky to me, but should accomplish what I want.

ljnelsona at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...
# 5

not sure what you're trying to do - seems like you don't want to disable the

spinner, just the buttons

if so, this seems to work OK (1.4.0_01)

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

class Testing

{

public void buildGUI()

{

JPanel p = new JPanel();

JSpinner spinner = new JSpinner(new SpinnerNumberModel(50, 0, 100, 5));

spinner.setUI(new MyUI());

p.add(spinner);

JFrame f = new JFrame();

f.getContentPane().add(p);

f.pack();

f.setLocationRelativeTo(null);

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.setVisible(true);

}

public static void main(String[] args)

{

SwingUtilities.invokeLater(new Runnable(){

public void run(){

new Testing().buildGUI();

}

});

}

}

class MyUI extends javax.swing.plaf.basic.BasicSpinnerUI

{

protected Component createNextButton()

{

return new javax.swing.plaf.basic.BasicArrowButton(SwingConstants.NORTH);

}

protected Component createPreviousButton()

{

return new javax.swing.plaf.basic.BasicArrowButton(SwingConstants.SOUTH);

}

}

Michael_Dunna at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...
# 6

i guess if you're going to have to make assumptions about the UI, you could just use a custom JSpinner:

JSpinner s = new JSpinner() {

public void updateUI() {

super.updateUI();

for (Component c : getComponents()) {

if (c instanceof AbstractButton) {

c.setEnabled(false);

}

}

}

};

Jasprea at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...
# 7

> i guess if you're going to have to make assumptions

> about the UI, you could just use a custom JSpinner:

> > JSpinner s = new JSpinner() {

> public void updateUI() {

> super.updateUI();

> for (Component c : getComponents()) {

> if (c instanceof AbstractButton) {

> c.setEnabled(false);

> }

> }

> }

> };

>

Hi, Jaspre; I like this. Thanks.

ljnelsona at 2007-7-9 5:03:06 > top of Java-index,Desktop,Core GUI APIs...