如何为JavaBean属性设置新值(日期)?
我正在编程一个bean(我正在学习Java和javabean),它是一个扩展了如何为JavaBean属性设置新值(日期)?,java,swing,date,javabeans,jlabel,Java,Swing,Date,Javabeans,Jlabel,我正在编程一个bean(我正在学习Java和javabean),它是一个扩展了JLabel的数字手表。显示的文本将是hh:mm:ss 当我尝试在一个新项目中使用组件(watch)时,它默认显示系统的日期(我将bean编程为以这种方式工作)。然而,我想让开发者(在本例中是我自己)可以编辑属性“hora”来设置不同的日期。因此,如果开发人员在新项目中插入组件,则文本必须是系统的时间。但是,如果开发人员编辑属性“hora”并设置一个新日期,例如再设置一个小时,则显示的文本应为新值,在本例中为系统日期+
JLabel
的数字手表。显示的文本将是hh:mm:ss
当我尝试在一个新项目中使用组件(watch)时,它默认显示系统的日期(我将bean编程为以这种方式工作)。然而,我想让开发者(在本例中是我自己)可以编辑属性“hora”来设置不同的日期。因此,如果开发人员在新项目中插入组件,则文本必须是系统的时间。但是,如果开发人员编辑属性“hora”并设置一个新日期,例如再设置一个小时,则显示的文本应为新值,在本例中为系统日期+1小时
我当前的代码部分工作:
在上图中:
- 在右侧,属性“hora”的值为:系统日期+1小时
- 在左侧,NetBeans的预览视图显示了正确的时间(系统时间+1小时)。分钟数的不同是因为手表每秒钟都在工作和改变时间。屏幕截图是在编辑属性值几分钟后制作的
- 在中心,项目正在运行,并显示错误的日期(系统日期)
- 请忽略按钮和微调器,它们仅用于测试目的
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 );
} );
}
}