Forum Stats

  • 3,770,519 Users
  • 2,253,130 Discussions
  • 7,875,493 Comments

Discussions

DateSpinner spins only after an edit

Jörg
Jörg Member Posts: 1,301
edited Aug 13, 2011 5:28AM in Swing
Hello,

this spinner beeps when using the arrow keys or clicking the UP or DOWN
button. Only after modifying a cipher, one can spin as expected. Where is the error?
The behaviour is the same under jdk 1.6.26 and 1.7.
import java.awt.*;
import java.util.*;
import javax.swing.*;

public class DateSpinner extends JFrame {
  JSpinner spin;

  public DateSpinner() {
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setSize(200,100);
    setLayout(null);
    Date date= new Date();
    spin= new JSpinner(new SpinnerDateModel(
				date, date, null, Calendar.DAY_OF_MONTH));
    spin.setEditor(new JSpinner.DateEditor(spin, "dd.MM.yyyy"));
    spin.setBounds(50,20, 80,25);
    add(spin);
    setVisible(true);
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
	new DateSpinner();
      }
    });
  }
}

Best Answer

  • kleopatra-JavaNet
    kleopatra-JavaNet Member Posts: 1,105 Gold Badge
    edited Aug 11, 2011 7:24AM Accepted Answer
    The underlying problem is the different precision on start:

    - model returns min with the time fields to the second
    - the text in the field is formatted to the minute (short default) or to the day (custom format)
    - BasicSpinnerUI button increment (didn't dig into the keyboard spinning, probably similar) first commits the current text before actually doing the increment
    - for the very first value, that initial commit fails because to the formatter it appears to be before the min value

    A bit rough, but wouldn't regard it as a bug: none of the collaborators can know what your "real" minimum is except you tell them : -)

    Way out is to set the min/max of the spinner/model to the same precision as the format, something like (using SwingX utils - which aren't entirely safe, as they dont handle DST correctly)
          int spinnerField = Calendar.DAY_OF_MONTH;
          Date date= new Date();
          Calendar calendar = Calendar.getInstance();
          CalendarUtils.startOf(calendar, spinnerField);
          spin= new JSpinner(new SpinnerDateModel(
                                      date, calendar.getTime(), null, spinnerField));
          spin.setEditor(new JSpinner.DateEditor(spin, "dd.MM.yyyy"));
    Cheers
    Jeanette

    Edited by: Kleopatra on Aug 11, 2011 1:14 PM

    added a code snippet
«13

Answers

  • sabre150
    sabre150 Member Posts: 1,405
    edited Aug 11, 2011 4:20AM
    I don't understand what you mean by "Only after modifying a cipher" since it seems to have no relevance to your problem.

    To me the Javadocs for JSpinner and SpinnerDateModel are ambiguous but I think you need something along the lines of
           Date now = new Date();
            Date thisTimeYesterday = new Date(now.getTime() - 24L * 60 * 60 * 1000);
            JSpinner spin = new JSpinner(new SpinnerDateModel(now, thisTimeYesterday, null, Calendar.DAY_OF_MONTH));
            spin.setEditor(new JSpinner.DateEditor(spin, "dd.MM.yyyy"));
    but I'm not sure what this will do when there is a Leap transition within the last 24 hours.

    Edited by: sabre150 on 11-Aug-2011 01:15

    After some further thought I now think you need
           GregorianCalendar nowCalendar = new GregorianCalendar();
            Date now = nowCalendar.getTime();
            nowCalendar.add(Calendar.DAY_OF_MONTH, -1);
            Date thisTimeYesterday = nowCalendar.getTime();
            final SpinnerDateModel spinnerDateModel = new SpinnerDateModel(now, thisTimeYesterday, null, Calendar.DAY_OF_MONTH);
            JSpinner spin = new JSpinner(spinnerDateModel);
      
    which should cope with the Leap transitions though you would need to test it.
  • Jörg
    Jörg Member Posts: 1,301
    Hello Sabre,
    I don't understand what you mean by "Only after modifying a cipher"
    Example: After launching the programme the cursor is at the beginning of the
    TextField. Remove the first cipher (currently "1") and replace it by "2".
    Now you can immediately use the arrow keys or click the buttons,
    which was not possible without the edit. Of course, the modification
    must be made to a valid, meaning higher date, as today is the lower bound.

    Your code works indeed. I found out that I have to reduce the current date (initial value)
    by at least that amount of hours that the lower bound date becomes yesterday.
    So we can conclude, that the initial and the lower bound value cannot be the same.
    Quite odd.
    I had a look at the bug database, but as it is not functioning properly, I could not access all search results.

    Ah! Just read your edit. Well, basically there is no difference to me in the new code,
    as it also keeps the initial and the lower bound values apart.
    Thanks, anyway.
  • sabre150
    sabre150 Member Posts: 1,405
    Jörg wrote:
    I don't understand what you mean by "Only after modifying a cipher"
    Example: After launching the programme the cursor is at the beginning of the
    TextField. Remove the first cipher (currently "1") and replace it by "2".
    Now I'm even more confused since I still have no idea what you mean by a 'cipher' in this context and I don't see a TextField anywhere. Never mind - you seem to have solved the problem anyway so what the heck.
  • Jörg
    Jörg Member Posts: 1,301
    Sorry for confusing you. The JSpinner consists of a JTextField and two (BasicArrow)buttons, if I remember correctly.
    When I launch the programme at my site it currently displays "11.08.2011". After the edit (using the Delete key) it looks like that "21.08.2011". Is that clearer now?

    And no, the problem is not solved, but presently looks to me like a bug. But number of bug impressions turned out to be my own fault.
  • walterln
    walterln Member Posts: 2,302
    The correct English translation for 'cijfer' (at least that is the Dutch word, but I guess your german? scandinavian? equivalent similar) is 'number'. The common meaning of 'cipher' in English is "a method of transforming a text in order to conceal its meaning" (although it can mean number according to my dictionary as well, it is not the common usage afaik).
  • kleopatra-JavaNet
    kleopatra-JavaNet Member Posts: 1,105 Gold Badge
    edited Aug 11, 2011 7:24AM Accepted Answer
    The underlying problem is the different precision on start:

    - model returns min with the time fields to the second
    - the text in the field is formatted to the minute (short default) or to the day (custom format)
    - BasicSpinnerUI button increment (didn't dig into the keyboard spinning, probably similar) first commits the current text before actually doing the increment
    - for the very first value, that initial commit fails because to the formatter it appears to be before the min value

    A bit rough, but wouldn't regard it as a bug: none of the collaborators can know what your "real" minimum is except you tell them : -)

    Way out is to set the min/max of the spinner/model to the same precision as the format, something like (using SwingX utils - which aren't entirely safe, as they dont handle DST correctly)
          int spinnerField = Calendar.DAY_OF_MONTH;
          Date date= new Date();
          Calendar calendar = Calendar.getInstance();
          CalendarUtils.startOf(calendar, spinnerField);
          spin= new JSpinner(new SpinnerDateModel(
                                      date, calendar.getTime(), null, spinnerField));
          spin.setEditor(new JSpinner.DateEditor(spin, "dd.MM.yyyy"));
    Cheers
    Jeanette

    Edited by: Kleopatra on Aug 11, 2011 1:14 PM

    added a code snippet
  • sabre150
    sabre150 Member Posts: 1,405
    edited Aug 11, 2011 7:28AM
    Jörg wrote:
    Sorry for confusing you. The JSpinner consists of a JTextField and two (BasicArrow)buttons, if I remember correctly.
    When I launch the programme at my site it currently displays "11.08.2011". After the edit (using the Delete key) it looks like that "21.08.2011". Is that clearer now?
    I'm still not clear as to what you consider the problem to be. Are you saying you don't want the value displayed to be editable except though the keyboard arrows keys or the displayed arrows? If so then you just need to disable edit on the DateEditor text field.
           final GregorianCalendar nowCalendar = new GregorianCalendar();
            Date now = nowCalendar.getTime();
            nowCalendar.add(Calendar.DAY_OF_MONTH, -1);
            Date thisTimeYesterday = nowCalendar.getTime();
            final SpinnerDateModel spinnerDateModel = new SpinnerDateModel(now, thisTimeYesterday, null, Calendar.DAY_OF_MONTH);
            final JSpinner spin = new JSpinner(spinnerDateModel);
            final JSpinner.DateEditor dateEditor = new JSpinner.DateEditor(spin, "dd.MM.yyyy");
            dateEditor.getTextField().setEditable(false);
            spin.setEditor(dateEditor);
      
    >
    And no, the problem is not solved, but presently looks to me like a bug. But number of bug impressions turned out to be my own fault.
    I calculated the previous day using a Calendar beause I think you have to worry about Leap seconds/years when calculating previous day. You could end up only going back through 23 hours which is not enough.
  • kleopatra-JavaNet
    kleopatra-JavaNet Member Posts: 1,105 Gold Badge
    sabre150 wrote:

    I'm still not clear as to what you consider the problem to be.
    not quite clear why you are not clear : -)

    - start the program
    - try to spin to the "next" date (either by button or keyboard, doesnt matter)
    - expected: next day showing
    - actual: nothing happens

    as mentioned in my last post, the error (on part of the dev, IMO) is an incorrect min. So your approach goes into the right direction but is not general enough. Basically, all lower-precision date fields (compared to the formatter) have to be nulled to get the expected behaviour, which is to allow input >= min

    Cheers
    Jeanette
  • sabre150
    sabre150 Member Posts: 1,405
    edited Aug 11, 2011 8:59AM
    Kleopatra wrote:
    sabre150 wrote:

    I'm still not clear as to what you consider the problem to be.
    not quite clear why you are not clear : -)

    - start the program
    - try to spin to the "next" date (either by button or keyboard, doesnt matter)
    - expected: next day showing
    - actual: nothing happens
    Using Ubuntu 11.04 with both JDK1.6.0_26 and 1.7.0 it advances to the next day!

    Edited by: sabre150 on 11-Aug-2011 05:56

    And running on Windows XP using JDK1.6.0_26 it advances to the next day!
  • Jörg
    Jörg Member Posts: 1,301
    @Walter
    These damn non-native speakers always cause trouble ;-) How if I use "digit" instead of "cipher"?
    In German at least we use "cypher" for a single digit, wheras a "number" can have any count of digits.
    Do English natives make this difference, too?<br><br>

    @Sabre
    Using Ubuntu 11.04 with both JDK1.6.0_26 and 1.7.0 it advances to the next day!
    Now I understand. You don't meet what I experience under WIN7.
    Still strange that the jdks behave differently.<br><br>

    @Jeanette
    Thank you, that's it. So the date of the lower bound has to have hh:mm:ss:ms all set to zero - then it works.
    Great!
This discussion has been closed.