tags:

views:

107

answers:

2

I have this Swing app I'm working on that has a pair of JSliders and JTextFields that both display & control the value of two numbers. Right now I kind of hacked things together to make it work, intercepting change events and updating the display. However I'm thinking a better way would be to make a model that has the two numbers and somehow link this model to my GUI view. I know how to make a model, but am kind of lost on how I could link that to my GUI view... any suggestions?

update: my model is ready + includes firing property changes. I think I would like to use some kind of data binding approach (e.g. JGoodies Binding) but I am not sure how... JGoodies Binding doesn't support sliders.

edit: also note, when the slider changes position, the text field should change its value; when the text field changes value, the slider should change position; and when the model changes value, both text field + slider should update.

alt text

+1  A: 

You could define your model and pass it to the view in the constructor.

Have not tried the code, but it could look like that:

public class MyView extends JPanel /*JFrame, whatever*/ {
    private MyModel myModel;

    public MyView(MyModel myModel) {
        this.myModel = myModel;
        // build GUI
        // ...
        textfield1.setText(String.valueOf(myModel.getValue1()));
    }

    // this is what you do when a control changes:
    public void value1Changed(int newValue) {
        myModel.setValue1(newVvalue);
    }
}

public class MyModel {
    private int value1;

    // getters, setters
    // ...
}
Peter Lang
+1  A: 

To keep the two components synchronized, just have each one's EventListener update the other. Here's an example connecting a JSlider and JSpinner:

public class SpinSlider extends JPanel {

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("SpinSlider");
                frame.add(new SpinSlider());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public SpinSlider() {
        this.setLayout(new FlowLayout());
        final JSpinner spinner = new JSpinner();
        final JSlider slider = new JSlider();
        slider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                JSlider s = (JSlider) e.getSource();
                spinner.setValue(s.getValue());
            }
        });
        this.add(slider);
        spinner.setModel(new SpinnerNumberModel(50, 0, 100, 1));
        spinner.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                JSpinner s = (JSpinner) e.getSource();
                slider.setValue((Integer) s.getValue());
            }
        });
        this.add(spinner);
    }
}
trashgod
hmm... thanks, i'll take a look. I think the problem might have something to do with the floating point -> integer -> floating point conversion in my case.
Jason S
This may be critical. Think of each component as a limited resolution view of your model, which contains the full-resolution value. The text field might display the value using a DecimalFormat; the slider's resolution is limited to that of the screen.
trashgod