如何为JavaBean属性设置新值(日期)?

如何为JavaBean属性设置新值(日期)?,java,swing,date,javabeans,jlabel,Java,Swing,Date,Javabeans,Jlabel,我正在编程一个bean(我正在学习Java和javabean),它是一个扩展了JLabel的数字手表。显示的文本将是hh:mm:ss 当我尝试在一个新项目中使用组件(watch)时,它默认显示系统的日期(我将bean编程为以这种方式工作)。然而,我想让开发者(在本例中是我自己)可以编辑属性“hora”来设置不同的日期。因此,如果开发人员在新项目中插入组件,则文本必须是系统的时间。但是,如果开发人员编辑属性“hora”并设置一个新日期,例如再设置一个小时,则显示的文本应为新值,在本例中为系统日期+

我正在编程一个bean(我正在学习Java和javabean),它是一个扩展了
JLabel
的数字手表。显示的文本将是
hh:mm:ss

当我尝试在一个新项目中使用组件(watch)时,它默认显示系统的日期(我将bean编程为以这种方式工作)。然而,我想让开发者(在本例中是我自己)可以编辑属性“hora”来设置不同的日期。因此,如果开发人员在新项目中插入组件,则文本必须是系统的时间。但是,如果开发人员编辑属性“hora”并设置一个新日期,例如再设置一个小时,则显示的文本应为新值,在本例中为
系统日期+1小时

我当前的代码部分工作:

在上图中:

  • 在右侧,属性“hora”的值为:系统日期+1小时
  • 在左侧,NetBeans的预览视图显示了正确的时间(系统时间+1小时)。分钟数的不同是因为手表每秒钟都在工作和改变时间。屏幕截图是在编辑属性值几分钟后制作的
  • 在中心,项目正在运行,并显示错误的日期(系统日期)
  • 请忽略按钮和微调器,它们仅用于测试目的
我怎样才能改变这种行为?因此,当我运行项目时,显示的时间与“hora”属性中选择的时间相同

相关代码:

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);
    }
}

感谢您的帮助,我的英语很抱歉。

JavaBeans作为小部件组件 (我正在学习Java和JavaBeans)

据我所知,在视觉设计工具中作为组件使用从未流行过。我感到惊讶的是,他们仍然支持这一点。我建议您不要在JavaBean技术的这方面花费太多时间或精力

java.time 默认情况下,它显示系统的日期(我将bean编程为以这种方式工作)

您正在使用可怕的日期时间类,这些类在几年前被JSR310中定义的现代java.time类所取代

切勿使用
日期
简化格式
。如果您必须与尚未更新到java.time的旧代码进行互操作,请在java.time中执行所有逻辑,最后使用添加到旧类中的新方法进行转换

对于一天中的某个时间值,如果没有日期和时区,请使用
LocalTime

时区 获取当前时间包括获取当前时刻。这需要一个时区。对于任何给定的时刻,一天中的日期和时间在全球各地因时区而异

如果未指定时区,JVM将隐式应用其当前默认时区。该默认值可能在运行时(!)期间出现,因此您的结果可能会有所不同。最好将所需/预期时区明确指定为参数。如果要使用JVM的当前默认时区,请通过调用
ZoneId.systemDefault()
明确您的意图。如果关键,请与用户确认区域

大陆/地区
的格式指定,例如
美国/蒙特利尔
非洲/卡萨布兰卡
,或
太平洋/奥克兰
。切勿使用2-4个字母的缩写,如
EST
IST
,因为它们不是真正的时区,也不是标准化的,甚至不是唯一的(!)

如果要使用JVM的当前默认时区,请显式请求它,并作为参数传递。如果省略,代码将变得模棱两可,我们无法确定您是否打算使用默认值,或者您是否像许多程序员一样不知道这个问题

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.
LocalTime lt = LocalTime.now( z ) ;
如果此内容至关重要,则应与用户确认时区。系统默认值可能与用户的意图不符,特别是考虑到移动设备和笔记本电脑很容易在时区之间移动。在这种情况下,您应该将
ZoneId
对象作为小部件类上的成员字段或小部件可以访问的其他地方

因此,如果开发人员在新项目中插入组件,则文本必须是系统的时间

您可以解析用户输入的文本。如果采用标准格式,即带有24小时时钟的HH:MM:SS,则无需费心指定格式模式。在解析/生成文本时,java.time类默认使用标准格式

String input = "23:01:23" ;
LocalTime lt = LocalTime.parse( input ) ;
如果要本地化表示
LocalTime
对象值的显示文本,请使用
DateTimeFormatter
。指定一个用于确定人类语言和文化规范的标准。并指定一个字母来表示长度或缩写

Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ) ;
搜索以了解更多信息。这已经在堆栈溢出上讨论过很多次了

动态更新 你剩下的代码让我有点困惑。您似乎想将时钟更新到当前时刻,不断刷新。然而,您也允许用户更改时间。这是矛盾的

我怀疑你真正想要的是两个部件一起工作:一个时间显示和一个时区。如果您试图让用户改变时钟显示以匹配其时区,则应让用户指定时区(如上所述)。换句话说,改变时钟应该是一种结果,而不是原因。用户操纵您的时区属性,时钟会自动更改其时间,如该时区所代表区域的人使用的偏移量所示

另一个问题:定期更新。您使用的是
Timer
TimerTask
,这两个类已被替代。特别是在Swing中,您应该使用
javax.Swing.Timer
类(请参阅),而不是

强制性警告:切勿从后台线程访问、更新或操作Swing小部件。仅在用户界面线程中执行此操作

示例应用程序 这是一个快速而简单的例子-
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ) ;
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 );
        } );
    }
}