所以我想在java gui中创建2个下拉菜单,允许用户在时区之间进行选择并比较其中两个。但是我遇到的问题是尝试获取用户从lambda表达式中选择的时区的变量。我仍然是相当新的java所以任何帮助将不胜感激
这是给我问题的代码
tz tz1= new tz();
ComboBox<String> cboNation = new ComboBox<>();
ObservableList<String> items = FXCollections.observableArrayList
("GMT+14", "GMT+13", "GMT+12", "GMT+11","GMT+10", "GMT+9", "GMT+8",
"GMT+7", "GMT+6", "GMT+5", "GMT+4", "GMT+3", "GMT+2", "GMT+1",
"GMT0" ,"GMT-1", "GMT-2", "GMT-3", "GMT-4", "GMT-5", "GMT-6",
"GMT-7", "GMT-8", "GMT-9", "GMT-10", "GMT-11", "GMT-12", "GMT-13", "GMT-14");
cboNation.getItems().addAll(items);
cboNation.setValue(items.get(0));
cboNation.setOnAction(e ->
{
currentIndex = items.indexOf(cboNation.getValue());
TimeZone tz = TimeZone.getTimeZone(timezones[currentIndex]);
String Timezone2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(tz);
tz1.firstdisplay = Timezone2;
});
gridPane.add(new Label(tz1.firstdisplay), 0, 0);
我希望能够从表达式中获取tz,并能够将其格式化为显示日期的字符串。如果有帮助的话,它会出现在gui上。
编辑 我尝试通过引用传递程序现在运行但时区没有显示在gui中。我添加了应该显示它们的行,但没有发生任何事情
答案 0 :(得分:1)
定义ComboBox < ZoneOffset > offsetsMenu
而不是<String>
:
offsetsMenu.setOnAction( ( ActionEvent actionEvent ) -> { this.chosenOffset = offsetsMenu.getValue(); } );
ZoneOffset
类型的弹出菜单小部件,以避免在后备列表中查找。 Instant
,ZoneOffset
,ZoneId
和ZoneRules
。
TimeZone
,SimpleDateFormat
,java.util.Date
等。在时区之间进行选择,并比较两个时区。
...
((“ GMT + 14”,“ GMT + 13”,“ GMT + 12”,“ GMT + 11”,“ GMT + 10”,“ GMT + 9”,“ GMT + 8”, “ GMT + 7”,“ GMT + 6”,“ GMT + 5”,“ GMT + 4”,“ GMT + 3”,“ GMT + 2”,“ GMT + 1”, “ GMT0”,“ GMT-1”,“ GMT-2”,“ GMT-3”,“ GMT-4”,“ GMT-5”,“ GMT-6”, “ GMT-7”,“ GMT-8”,“ GMT-9”,“ GMT-10”,“ GMT-11”,“ GMT-12”,“ GMT-13”,“ GMT-14”); < / p>
这些不是时区。这些是偏移量,在本初子午线之前或之后数小时-数分钟-秒。
它们还不完整。偏移量可以是任何小时数-分钟-秒。各地的人们使用不同的偏移量。例如,现代印度使用+05:30
的偏移量,比UTC提前五个半小时。
时区远不止于此。时区是特定地区人民过去,现在和将来对偏移量的更改的历史记录。
以Continent/Region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
您正在使用的是可怕的旧类,现在这些旧类已被JSR 310中定义的现代 java.time 类取代。
如果要表示比UTC提前14小时的时间,请使用ZoneOffset
。
ZoneOffset offset = ZoneOffset.ofHours( 14 ) ;
表示比UTC提前五个半小时的时间。
ZoneOffset offset = ZoneOffset.ofHoursMinutes( 5 , 30 ) ;
更好,使用时区。该类为java.time.ZoneId
,代替了旧版TimeZone
。
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
通过ZoneRules
类向ZoneId
对象询问当前使用的偏移量。
ZoneOffset offsetInUseNowInIndia = z.getRules().getOffset( Instant.now() ) ;
在时区之间进行选择,并比较两个时区
让用户选择时区而不是时区偏移会更有意义。但是,如果您坚持要抵消...
列出类型为ZoneOffset
而不是字符串的列表。
List< ZoneOffset > offsets ;
让我们在特定时刻使用所有偏移量。
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
循环所有时区。对于每个,获取规则,并查询偏移量。存储在一组TreeSet
中以消除重复项(许多区域可能在任何特定时刻共享特定的偏移量)。
Set < ZoneOffset > offsets = new TreeSet <>(); // A sorted set of `ZoneOffset`, eliminates duplicates.
Instant instant = Instant.now(); // Capture the current moment as seen in UTC.
for ( String zoneIdString : ZoneId.getAvailableZoneIds() )
{
ZoneId zoneId = ZoneId.of( zoneIdString );
ZoneOffset offset = zoneId.getRules().getOffset( instant );
offsets.add( offset );
}
转储到控制台。
System.out.println( "offsets = " + offsets );
偏移量= [+14:00,+ 13:45,+ 13:00,+ 12:00,+ 11:00,+ 10:30,+ 10:00,+ 09:30,+ 09:00 ,+08:45,+08:00,+07:00,+06:30,+06:00,+05:45,+05:30,+05:00,+04:30,+04:00 ,+03:30,+03:00,+02:00,+01:00,Z,-01:00,-02:00,-03:00,-03:30,-04:00,-05 :00,-06:00,-07:00,-08:00,-09:00,-09:30,-10:00,-11:00,-12:00]
输入offsets
的副本以创建所需的列表。 (我不使用JavaFX。)
您问:
将其格式化为显示日期的字符串
以我们的代码中的Instant
对象为准,以UTC的当前时刻为准,并应用ZoneOffset
得到一个OffsetDateTime
。同样,这里没有时区,只有偏移量。我建议您改用时区(ZoneId
与ZoneOffset
,ZonedDateTime
与OffsetDateTime
)。但是您要求补偿,所以我们开始吧。
如果您列出的是文本而不是ZoneOffset
对象,请创建ZoneOffset
对象。
ZoneOffset offset = ZoneOffset.of( "+05:30" ) ;
将偏移量应用于Instant
对象,从而产生OffsetDateTime
。
OffsetDateTime odt = instant.atOffset( offset ) ;
以标准ISO 8601格式生成文本。
String output = odt.toString() ;
odt.toString()= 2020-02-13T02:16:57.883278 + 05:30
与您所需的格式接近。您可以在中间替换T
。并且您忽略了文本的偏移量。我不建议这样做,因为它会使阅读此值的人产生歧义。但是,如果您坚持使用,请使用忽略了偏移量的预定义常量DateTimeFormatter
对象,然后替换T
。
String output =
odt
.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
.replace( "T" , " " )
;
输出= 2020-02-13 02:16:57.883278
虽然我是JavaFX的新手,但您的弹出菜单小部件似乎支持泛型,并且可以表示智能对象而不是哑字符串。使您的ComboBox
的类型为ZoneOffset
(ComboBox< ZoneOffset >
)时,默认情况下,小部件似乎正在调用ZoneOffset.toString()
以便用户在屏幕上显示文本。该toString
方法在standard ISO 8601 format中生成文本。
现在,我们不再需要对偏移量列表进行查找。用户的选择本身就是ZoneOffset
对象!无需进一步查看。
我今天制作了我的第一个JavaFX应用程序,以演示此代码。
我不知道如何在Label
上添加Scene
,因此我将其留给读者练习。但是您可以在此处看到我们如何获得当前正在使用的所有偏移量的列表。然后,我们将ZoneOffset
对象的列表分配给我们的弹出菜单小部件ComboBox< ZoneOffset >
。当用户选择一个项目时,该项目本身就是列表中的ZoneOffset
对象。因此,我们不再真正关心列表本身。这种策略在面向对象的用户界面框架中很常见。
运行该应用程序时,每次从列表中选择一项时,请观看控制台。
package work.basil.example;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Set;
import java.util.TreeSet;
/**
* JavaFX App
* Untested code example.
* <p>
* © 2020 Basil Bourque.
* Use by terms of ISC License: https://www.isc.org/licenses/ (basically, do anything but sue me)
*/
public class App extends Application
{
ZoneOffset chosenOffset;
@Override
public void start ( Stage stage )
{
var javaVersion = SystemInfo.javaVersion();
var javafxVersion = SystemInfo.javafxVersion();
Set < ZoneOffset > offsets = new TreeSet <>(); // A sorted set of `ZoneOffset`, eliminates duplicates.
Instant instant = Instant.now(); // Capture the current moment as seen in UTC.
for ( String zoneIdString : ZoneId.getAvailableZoneIds() )
{
ZoneId zoneId = ZoneId.of( zoneIdString );
ZoneOffset offset = zoneId.getRules().getOffset( instant );
offsets.add( offset );
}
System.out.println( "offsets = " + offsets );
ComboBox < ZoneOffset > offsetsMenu = new ComboBox <>();
ObservableList < ZoneOffset > items = FXCollections.observableArrayList( offsets );
offsetsMenu.getItems().addAll( items );
offsetsMenu.getSelectionModel().selectFirst(); // Might be more orthodox than: offsetsMenu.setValue( items.get( 0 ) );
this.chosenOffset = offsetsMenu.getSelectionModel().getSelectedItem(); // Record the default we assign.
offsetsMenu.setOnAction( ( ActionEvent actionEvent ) ->
{
this.chosenOffset = offsetsMenu.getValue();
System.out.println( "DEBUG - User chose ZoneOffset: " + this.chosenOffset );
} );
var scene = new Scene( new StackPane( offsetsMenu ) , 640 , 480 );
stage.setScene( scene );
stage.show();
}
public static void main ( String[] args )
{
launch();
}
}
ZoneId
对象:Android TimeZone.getAvailableIDs() producing strange strings 答案 1 :(得分:0)
实际上你在lambda表达式中创建了TimeZone tz
变量,并且你试图使用的是在你的lambda表达式之外的代码行
String Timezone2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(tz);
。您应该将TimeZone tz
变量声明为实例变量。