[英]How to set a new value (Date) for a Java bean property?
我正在编写一个 bean(我正在学习 Java 和 Java bean),它是一个扩展JLabel
的数字手表。 显示的文本将是hh:mm:ss
。
当我尝试在新项目中使用组件(手表)时,它默认显示系统的日期(我将 bean 编程为以这种方式工作)。 但是我想允许开发人员(在这种情况下我自己)可以编辑属性“hora”来设置不同的日期。 所以如果开发者在新项目中插入组件,文字一定是系统的时间。 但是,如果开发人员编辑属性“hora”并设置新日期,例如多一小时,则显示的文本应为新值,在本例中为system date + 1 hour
。
我当前的代码部分工作:
在上一张图片中:
我怎样才能改变这种行为? 那么当我运行项目时,显示的时间与“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);
}
}
感谢您的帮助,并为我的英语感到抱歉。
(我正在学习 Java 和 Java bean)
据我所知,在可视化设计工具中使用JavaBeans作为组件从未流行起来。 我很惊讶NetBeans仍然支持它。 我建议您不要在 JavaBean 技术的这方面花费太多时间或精力。
它默认显示系统的日期(我将 bean 编程为以这种方式工作)。
您正在使用多年前被 JSR 310 中定义的现代java.time类取代的糟糕的日期时间类。
永远不要使用Date
或SimpleDateFormat
。 如果您必须与尚未更新为java.time 的旧代码进行互操作,请在java.time 中执行所有逻辑,最后使用添加到旧类的新方法进行转换。
对于只有时间的值,没有日期和时区,请使用LocalTime
。
获取当前时间涉及获取当前时刻。 这需要一个时区。 对于任何给定时刻,日期和时间在全球各地因时区而异。
如果未指定时区,JVM 会隐式应用其当前默认时区。 该默认值可能会在运行时随时更改(!),因此您的结果可能会有所不同。 最好将您想要/预期的时区明确指定为参数。 如果您想使用 JVM 的当前默认时区,请通过调用ZoneId.systemDefault()
明确您的意图。 如果关键,请与您的用户确认该区域。
以Continent/Region
格式指定正确的时区名称,例如America/Montreal
、 Africa/Casablanca
或Pacific/Auckland
。 永远不要使用EST
或IST
等 2-4 个字母的缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalTime lt = LocalTime.now( z ) ;
如果您想使用 JVM 的当前默认时区,请明确要求并作为参数传递。 如果省略,代码读起来会变得模棱两可,因为我们不确定您是否打算使用默认值,或者您是否像许多程序员一样没有意识到这个问题。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
LocalTime lt = LocalTime.now( z ) ;
如果此内容至关重要,则应与用户确认时区。 系统默认值可能不符合用户的意图,特别是考虑到移动设备和笔记本电脑很容易在时区之间移动。 在这种情况下,您应该将ZoneId
对象作为小部件类或小部件可访问的其他位置的成员字段。
所以如果开发者在新项目中插入组件,文字一定是系统的时间。
您可以解析用户输入的文本。 如果采用标准ISO 8601格式,HH:MM:SS 与 24 小时制,您无需费心指定格式模式。 java.time类在解析/生成文本时默认使用标准格式。
String input = "23:01:23" ;
LocalTime lt = LocalTime.parse( input ) ;
如果要本地化表示LocalTime
对象值的显示文本,请使用DateTimeFormatter
。 指定Locale
以确定本地化中使用的人类语言和文化规范。 并指定一个FormatStyle
来说明多长时间或缩写。
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ) ;
搜索以了解更多信息。 这已经在 Stack Overflow 上多次讨论过。
你的其余代码对我来说有点混乱。 您似乎想将时钟更新到当前时刻,不断刷新。 然而,您还允许用户更改时间。 这是矛盾的。
我怀疑您真正想要的是两个一起工作的部分:时间显示和时区。 如果您试图让用户改变时钟显示以匹配他们的时区,您应该通过让用户指定时区来实现(如上所述)。 换句话说,时钟偏移应该是结果,而不是原因。 用户操作您的时区属性,时钟会自动更改其时间,如该时区所代表地区的人们使用的偏移量所示。
另一个问题:定期更新。 您正在使用Timer
和TimerTask
,这两个类已被Executor 框架取代。 特别是在 Swing 中,您应该使用javax.swing.Timer
类(参见教程)而不是java.util.Timer
。
强制性警告:切勿从后台线程访问、更新或操作 Swing 小部件。 仅在用户界面线程中执行此操作。
这是一个快速而肮脏的示例 Swing 应用程序。 这不是 JavaBean 组件。 而且我不太记得 Swing。 但这可能会对您有所帮助。 您可以看到更改时区 ( ZoneId
) 如何更新时间,同时将时间移动到该时区中当前有效的偏移量。
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 );
} );
}
}
java.time框架内置于 Java 8 及更高版本中。 这些类取代麻烦的老传统日期时间类,如java.util.Date
, Calendar
,和SimpleDateFormat
。
要了解更多信息,请参阅Oracle 教程。 并在 Stack Overflow 上搜索许多示例和解释。 规范是JSR 310 。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
您可以直接与您的数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC 驱动程序。 不需要字符串,不需要java.sql.*
类。
从哪里获得 java.time 类?
ThreeTen-Extra项目用额外的类扩展了 java.time。 该项目是未来可能添加到 java.time 的试验场。 您可以在这里找到一些有用的类,比如Interval
, YearWeek
, YearQuarter
,和更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.