Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a new value (Date) for a Java bean property?

I am programming a bean (I am learning Java and Java beans) that is a digital watch which extends of JLabel. The text showed would be hh:mm:ss.

When I try to use the component (the watch) in a new project it shows by default the date of the system (I programmed the bean to work in this way). However I would like to allow the developer (in this case myself) can edit the property "hora" to set a different date. So if the developer insert the component in a new project, the text must be the time of the system. However if the developer edit the property "hora" and set a new date, for instance one hour more, the text showed should be the new value, in this example the system date + 1 hour.

My current code work partially:

Use of the bean in a new project with the date changed.

In the previous image:

  • On the right the property "hora" has the value: system date + 1 hour.
  • On the left the preview view of NetBeans shows the right time (system time + 1 hour). The difference in the minutes is because the watch works and changes its every second its time. The screenshot was made a few minutes after edit the property value.
  • In the center the project is running and shows the wrong date (system date).
  • Please ignore the button and the spinner, they are only for testing purposes.

How can I change this behavior? So when I run the project the time showed is the same than the selected in the "hora" property?

Relevant code:

public class Reloj extends JLabel implements Serializable {
    private Date hora = new Date();
    private SimpleDateFormat formatoHora;
    private boolean doceHoras = false;

    public Reloj() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
             public void run() {
                setHora(new Date((getHora().getTime())+1000));

            }
        }, 0, 1000);
    }

    public Date getHora() {
        return this.hora;
    }

    public void setHora(Date hora) {
        this.hora = hora;
        this.setText(this.getFormatoHora().format(hora));
        this.repaint();
    }

    public SimpleDateFormat getFormatoHora() {
        if (this.isDoceHoras()) {
            this.formatoHora = new SimpleDateFormat("hh:mm:ss a");
        } else {
            this.formatoHora = new SimpleDateFormat("HH:mm:ss");
        }
        return this.formatoHora;
    }

    public void setDoceHoras(boolean doceHoras) {
        this.doceHoras = doceHoras;
        this.setHora(hora);
    }
}

Thank you for helping and sorry for my English.


1 Answers

JavaBeans as widget component

(I am learning Java and Java beans)

As far as I know, using JavaBeans as a component in visual design tools never caught on. I am surprised that NetBeans still supports that. I recommend you not spend too much time or effort on that aspect of JavaBean technology.

java.time

it shows by default the date of the system (I programmed the bean to work in this way).

You are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310.

Never use Date or SimpleDateFormat. If you must interoperate with old code not yet updated to java.time, do all your logic in java.time and at the end convert using new methods added to the old classes.

For a time-of-day only value, without a date and without a time zone, use LocalTime.

Time zone

Getting the current time-of-day involves getting the current moment. And that requires a time zone. For any given moment both the date and the time-of-day vary around the globe by time zone.

If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If you want to use the JVM’s current default time zone, make your intention clear by calling ZoneId.systemDefault(). If critical, confirm the zone with your user.

Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalTime lt = LocalTime.now( z ) ;

If you want to use the JVM’s current default time zone, ask for it explicitly, and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.
LocalTime lt = LocalTime.now( z ) ;

If this content is crucial, you should confirm the time zone with the user. The system default may not match the user's intention, especially given that mobile devices and laptops easily move between time zones. In such a case, you should be keeping the ZoneId object as a member field on your widget class or somewhere else accessible to the widget.

So if the developer insert the component in a new project, the text must be the time of the system.

You can parse the text input by the user. If in standard ISO 8601 format, HH:MM:SS with 24-hour clock, you need not bother with specifying a formatting pattern. The java.time classes use the standard formats by default when parsing/generating text.

String input = "23:01:23" ;
LocalTime lt = LocalTime.parse( input ) ;

If you want to localize the display text representing the value of our LocalTime object, use a DateTimeFormatter. Specify a Locale to determine the human language and cultural norms used in localizing. And specify a FormatStyle to say how long or abbreviated.

Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ) ;

Search to learn more. This has been covered many times already on Stack Overflow.

Dynamic updating

The rest of your code is a bit confusing to me. You seem to want to update the clock to the current moment, continuously refreshed. Yet you also allow the user to alter the time. This is contradictory.

I suspect what you really want is two pieces working together: A time-of-day display and a time zone. If you are trying to enable the user to shift the clock display to match their time zone, you should do that by letting the user specify a time zone (as discussed above). In other words, shifting the clock should be an effect, not a cause. The user manipulates your time zone property, and the clock automatically changes its time as seen in the offset used by the people of the region represented by that time zone.

Another issue: Periodic updating. You are using Timer and TimerTask, two classes which have been supplanted by the Executor framework. And specifically in Swing, you should be using the javax.swing.Timer class (see Tutorial) rather than java.util.Timer.

Obligatory warning: Never access, update, or manipulate Swing widgets from a background thread. Do so only in the user-interface thread.

Example app

Here is a quick-and-dirty example Swing app. This is not a JavaBean component. And I don't remember much of Swing. But this might help you a bit. You can see how changing the time zone (ZoneId) updates the time-of-day while shifting it to the offset currently in effect in that zone.

Screenshot of localized time-of-day with a field to enter a time zone.

package org.example;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.DateTimeException;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

/**
 * Hello world!
 */
public class App extends JFrame
{
    ZoneId zoneId;
    LocalTime localTime;
    JTextField timeZone;
    JLabel displayTime;
    DateTimeFormatter formatter;


    public App ( )
    {
        initUI();
    }

    private void initUI ( )
    {

        setTitle( "Simple example" );
        setSize( 300 , 200 );
        setLocationRelativeTo( null );
        setDefaultCloseOperation( EXIT_ON_CLOSE );

        // Widgets
        this.zoneId = ZoneId.systemDefault();
        this.timeZone = new JTextField( this.zoneId.getId() , 20 );
        this.localTime = LocalTime.now( this.zoneId );
        Locale locale = Locale.CANADA_FRENCH;
        this.formatter = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM );
        this.displayTime = new JLabel( this.localTime.format( this.formatter ) );

        this.timeZone.addActionListener( new ActionListener()
        {
            @Override
            public void actionPerformed ( ActionEvent event )
            {
                System.out.println( "The entered text is: " + timeZone.getText() );
                try
                {
                    zoneId = ZoneId.of( timeZone.getText() );
                    localTime = LocalTime.now( zoneId );
                    String output = LocalTime.now( zoneId ).format( formatter );
                    displayTime.setText( output );
                }
                catch ( DateTimeException e )
                {
                    System.out.println( "BAD INPUT - The user gave an invalid time zone: " + timeZone );
                }
            }
        } );

        // Arrange
        JPanel panel = new JPanel();
        panel.add( this.displayTime );
        panel.add( this.timeZone );
        this.add( panel );
    }

    public static void main ( String[] args )
    {

        EventQueue.invokeLater( ( ) -> {

            var ex = new App();
            ex.setVisible( true );
        } );
    }
}

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

like image 180
Basil Bourque Avatar answered Feb 18 '26 06:02

Basil Bourque



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!