-1

I want to write some code that receives input from two JSpinners. I want it so that I can change the values of the JSpinners and get the string value from whats shown in the Spinners. I did this by adding a ChangeListener. However in the actual application I can't change the values on the spinner, or in other words, I can't move the Spinner up or down

import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;


  public class SalesApplication extends JFrame {

    SpinnerModel model1;
   JSpinner spinner1;
   SpinnerModel model2;
   JSpinner spinner2;

   public SalesApplication(){

        model1 = new SpinnerDateModel();
           spinner1 = new JSpinner(model1);


 //Sub any date you want
           Date firstDate1 = null;
           model1 = new SpinnerDateModel(firstDate1, null, null, Calendar.DAY_OF_MONTH);


            class SpinnerListener1 implements ChangeListener {
             public void stateChanged(ChangeEvent e) {
             JSpinner spinner = (JSpinner) e.getSource();
             initialDate = (String) spinner.getValue();
      }
         }; 
          spinner1.addChangeListener(new SpinnerListener1());


           model2 = new SpinnerDateModel();
           spinner2 = new JSpinner(model2);
           Date firstDate2 = null ;
           model2 = new SpinnerDateModel(firstDate2, null, null, Calendar.DAY_OF_MONTH);

            class SpinnerListener2 implements ChangeListener {
           public void stateChanged(ChangeEvent e) {
             JSpinner spinner = (JSpinner) e.getSource();
             endDate = (String) spinner.getValue();
      }
         };
    spinner2.addChangeListener(new SpinnerListener2());
       JPanel rightPanel = new JPanel();
       rightPanel.add(spinner1);
       rightPanel.add(spinner2);
       add(rightPanel, java.awt.BorderLayout.EAST);
 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       setSize(600, 300);                       
       setVisible(true);
David
  • 1
  • 1
  • You're changing the object held by model1 **after** using the original object which makes no sense. The new object will be ignored and discarded. If you want the new model in your Spinner, then set the model1 variable to it **before** passing the variable into the JSpinner constructor. – DontKnowMuchBut Getting Better Apr 30 '19 at 23:14
  • Same for model2, suggesting that you will want to review the difference between an object and a variable. Changing the object that the variable refers to will not magically change the object that it originally referred to. – DontKnowMuchBut Getting Better Apr 30 '19 at 23:17
  • So I just made the change that you suggested by putting model1 before passing it to the Spinner constructor but Im still getting the same issue. I still can't change the dates on my JSpinner. I even removed the original model1 with the empty constructor and I still get the same issue – David Apr 30 '19 at 23:27
  • 1
    Then create a valid [mcve] as @AndrewThompson suggested, and post it in your question, code that we can compile and run without needing to modify it, code that reproduces your problem, and code that is small enough to post in your question in its entirety. Note that he is not asking for your entire program, but rather a new and small program, one created specifically to debug your problem. – DontKnowMuchBut Getting Better Apr 30 '19 at 23:30
  • Ok I added more code, hopefully it can help – David Apr 30 '19 at 23:38
  • 1
    Thank you for the attempt, but 1) it's not yet complete -- missing a main method, missing some closing parenthesis and 2) even if it were complete it throws exceptions immediately as you're passing null values into your spinner models, something that is not allowed (and Java is telling you this, so you should already know this). – DontKnowMuchBut Getting Better Apr 30 '19 at 23:43
  • 1
    Also your JSpinner holds Date objects, and so this: `initialDate = (String) spinner.getValue();` doesn't look right, since you're trying to cast a Date object to a String. – DontKnowMuchBut Getting Better Apr 30 '19 at 23:54

2 Answers2

2

You're creating two SpinnerDateModel's with this code:

model1 = new SpinnerDateModel(); // SpinnerDateModel (1)
spinner1 = new JSpinner(model1);  // holds the first model
Date firstDate1 = dateObj[4];
model1 = new SpinnerDateModel(firstDate1, null, null, Calendar.DAY_OF_MONTH); // SpinnerDateModel (2)

The spinner1 JSpinner only holds the first SpinnerDateModel object, and no JSpinner holds the second one, and so that object is simply ignored and is wasted. If you need to use the 2nd model, then don't even create the first one:

// model1 = new SpinnerDateModel(); // SpinnerDateModel (1)
// spinner1 = new JSpinner(model1);
Date firstDate1 = dateObj[4];
model1 = new SpinnerDateModel(firstDate1, null, null, Calendar.DAY_OF_MONTH); // SpinnerDateModel (2)
spinner1 = new JSpinner(model1); // now holds the second model

You've the exact same problem for the model2 variable.

The key issue above is that you seem to be equating variable with the object it holds. Once you pass the SpinnerDateModel into the JSpinner, then changing the variable that your model1 SpinnerDateModel holds will have no effect on the model object held by the JSpinner itself.

  • I appreciate the advice. I did this but for some reason Im still getting the same issue. Should I include more code or is this enough to diagnose the problem? – David May 01 '19 at 00:08
  • 1
    *"Should I include more code.."* include code that when copy/paste to a **new project** compiles without any changes and runs to demonstrate the problem. I .. don't know how to explain that more simply. – Andrew Thompson May 01 '19 at 00:10
1

You seem to be guessing at how to create SpinnerDateModel objects and use them within a JSpinner. Simply, the model needs a start Date, end Date, and a value, or date to display. For example, something like so:

// current value will be *today*
private Date value = new Date();  // today

// start will be the first of the year
private Date start = new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime();

// end will be the last of the year
private Date end = new GregorianCalendar(2019, Calendar.DECEMBER, 31).getTime();

// create date model using the above values
private SpinnerDateModel dateModel1 = new SpinnerDateModel(value, start, end, Calendar.DAY_OF_MONTH);

// put into JSpinner
private JSpinner spinner1 = new JSpinner(dateModel1);    

Then in the ChangeListener, you extract a Date object from the Spinner since that is what it holds. You seem to be trying to extract a String which won't work. For example:

spinner1.addChangeListener(evt -> {
    Date currentDate = (Date) spinner1.getValue(); // holds date values
    String dateText = format.format(currentDate); // if we want to extract a String from it
    System.out.println("Current Date: " + dateText);  // display it
});

A working example could look like:

import java.awt.Dimension;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.swing.*;

@SuppressWarnings("serial")
public class SpinnerTester extends JPanel {
    // current value will be *today*
    private Date value = new Date();  // today

    // start will be the first of the year
    private Date start = new GregorianCalendar(2019, Calendar.JANUARY, 1).getTime();

    // end will be the last of the year
    private Date end = new GregorianCalendar(2019, Calendar.DECEMBER, 31).getTime();

    // create date model using the above values
    private SpinnerDateModel dateModel1 = new SpinnerDateModel(value, start, end, Calendar.DAY_OF_MONTH);

    // put into JSpinner
    private JSpinner spinner1 = new JSpinner(dateModel1);

    public SpinnerTester() {
        // get the format from the spinner's editor
        SimpleDateFormat format = ((JSpinner.DateEditor) spinner1.getEditor()).getFormat();

        // have our spinner show the date only, and not the time
        format.applyPattern("MM/dd/yyyy");

        // add to GUI
        add(spinner1);
        setPreferredSize(new Dimension(400, 200));

        spinner1.addChangeListener(evt -> {
            Date currentDate = (Date) spinner1.getValue(); // holds date values
            String dateText = format.format(currentDate); // if we want to extract a String from it
            System.out.println("Current Date: " + dateText);  // display it
        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            SpinnerTester mainPanel = new SpinnerTester();
            JFrame frame = new JFrame("Spinner Tester");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        });
    }
}

Thanks to mKorbel's answer for showing how to format the date rendered within the JSpinner.

  • Wow, I really appreciate it! Thank you for showing me this. Once I did a date format in my ChangeListener, I was able to change the dates in the Spinner while not making the mistake of changing the date to a string. This was really helpful, thank you. – David May 01 '19 at 00:35