我有一個本質上是JFormattedTextField,它使用一個 DateFormatter,它從用戶控制的區域設定中獲得其格式。 設定。下面的代碼試圖在不使用大量專有代碼的情況下再現這一點。(我為我在頂級 Swing 方面的笨拙嘗試表示歉意......)
我的問題是,如果我不知道該如何處理這個問題,那么我將會把這個問題交給我的同事。
我的問題是,如果用戶選擇了一個具有兩位數年份的地區,那么就不可能在 "錯誤 "的世紀中輸入日期。例如,如果我運行下面的程式,并將年份編輯為2047年,然后單擊 "確定",該程式就會列印出1947年的日期。
原因似乎是JFormattedTextField 喜歡通過文本表示法來 "規范化"其資料。一個解決方法是用一個方法覆寫commitEdit(),該方法可以測驗往返,如果發現它破壞了年份,就用一個硬編碼的YYY-MM-DD來替換格式。不過,這似乎有點強人所難。除了要求用戶選擇一個合理的地區或者為這個特定的欄位硬編碼格式之外,還有什么更好的方法嗎?(我知道有一些方法可以選擇哪一個100年的視窗是正確的,但是這仍然把我限制在一個100年的視窗)。
import javax.swing.*;
import javax.swing.text.DateFormatter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date。
import java.util.Locale;
public class Main {
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing"/span>)。
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)。
var gbl = new GridBagLayout()。
frame.setLayout(gbl)。
final Container contentPane = frame.getContentPane()。
Date date = new Date()。
JFormattedTextField dateField = new JFormattedTextField(date)。
dateField.setFormatterFactory(new JFormattedTextField.AbstractFormatterFactory() {
@Override[/span
public JFormattedTextField.AbstractFormatter getFormatter(JFormattedTextField tf) {
return new DateFormatter(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.GERMANY) ) 。
}
});
contentPane.add(dateField);
JButton button = new JButton("OK")。
contentPane.add(button);
button.addActionListener((ActionEvent e) -> {
try {
dateField.commitEdit()。
} catch (ParseException ex) {
ex.printStackTrace()。
}
System.out.println(dateField.getValue())。
});
frame.pack();
frame.setVisible(true)。
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(Main::createAndShowGUI)。
}
uj5u.com熱心網友回復:
下面的方法對我有用,但我并不是說這是最好的或唯一的方法。
你的問題只涉及日期,而不是時間,所以在下面的代碼中,我忽略了時間,只處理日期。
在你的情況下,JFormattedTextField類的方法getValue,回傳java.util.Date的一個實體。這個類已經被java.time包中的類所取代。其中一個原因是你所看到的[有問題的]行為。
因此,在下面的代碼中,我獲取了 JFormattedTextField 的文本內容,提取了 date 部分,并將其轉換為 java.time.LocalDate,以顯示您想要的年份。
我添加了很多 println 陳述句,只是為了演示我在上面寫的內容。
import java.awt.Container;
import java.awt.EventQueue。
import java.awt.GridBagLayout;
import java.text.DateFormat;
import java.text.ParseException;
import java.time.LocalDate。
import java.time.format.DateTimeFormatter;
import java.util.Date。
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.text.DateFormatter;
public class FmTxtFld {
private void createAndShowGUI() {
JFrame frame = new JFrame("FmTxtFld") 。
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)。
var gbl = new GridBagLayout()。
frame.setLayout(gbl)。
final Container contentPane = frame.getContentPane()。
Date date = new Date()。
JFormattedTextField dateField = new JFormattedTextField(date)。
dateField.setFormatterFactory(new JFormattedTextField.AbstractFormatterFactory() {
@Override[/span
public JFormattedTextField.AbstractFormatter getFormatter(JFormattedTextField tf) {
return new DateFormatter(DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.SHORT,
Locale.GERMANY))。)
}
});
contentPane.add(dateField);
JButton button = new JButton("OK")。
contentPane.add(button);
button.addActionListener(e -> {
String text = dateField.getText()。
System.out.println("Text: " text)。
int ndx = text.indexOf(', ');
String str = text.substring(0, ndx)。
System.out.println("Date: " str)。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy", Locale.GERMANY) 。
LocalDate ld = LocalDate.parse(str, formatter)。
System.out.println("java.time.LocalDate = " ld)。
try {
dateField.commitEdit()。
}
catch (ParseException ex) {
ex.printStackTrace()。
}
Object obj = dateField.getValue()。
System.out.println("值型別。" obj.getClass().getName())。)
System.out.println("值:" obj)。
});
frame.pack();
frame.setVisible(true)。
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new FmTxtFld().createAndShowGUI()) 。
}
當我運行上述代碼并將年份改為47,然后當我按下OK按鈕時,我得到如下輸出:
文本。16.09.47, 15:16
日期:16.09.47
java.time.LocalDate = 2047-09-16
值型別: java.util.Date
值。Tue Sep 16 15:16:00 IST 1947
換句話說,java.util.Date顯示的年份是1947年,而java.time.LocalDate顯示的年份是2047年(這就是你想要的,對吧?
uj5u.com熱心網友回復:
如果你需要四位數的年份以確保有正確的世紀,而你的地區在其SHORT日期格式中使用兩位數的年份,我看到兩個選擇:
- 使用
SHORT日期格式。 - 使用
MEDIUM格式來代替日期。我懷疑在許多地區,這將迫使用戶進行更多的輸入,他們可能不會感到滿意。 - 修改本地的格式,要求4位數的年份。根據不同的觀點,這可能被認為是粗暴或有趣的妥協,但它提供了我們所需要的東西。
我建議你在處理JFormattedTextField時也使用java.time,即現代Java日期和時間API。要獲得并修改你的用戶地區的格式模式:
Locale userSelectedLocale = Locale.GERMAN;
String formatPattern = DateTimeFormatterBuilder
.getLocalizedDateTimePattern(FormatStyle.SHORT, FormatStyle.SHORT,
IsoChronology.INSTANCE, userSelectedLocale)。)
System.out.println("本地化格式:"/span> formatPattern)。
formatPattern = formatPattern.replaceFirst("y ", "yyy")。
System.out.println("修改的本地化格式。" formatPattern)。)
到目前為止的輸出是:
本地化的格式:dd.MM.yy, HH:mm
修改后的本地化格式:dd.MM.yyy, HH:mm
為了在JFormattedTextField中使用這個,我們需要一個舊的Format類(DateFormat的超類)實體。要建立這個實體:
Format formatForFormattedTextField
= DateTimeFormatter.ofPattern(formatPattern, userSelectedLocale)
.toFormat(LocalDateTime::from)。
我正在指定格式化器應該決議成LocalDateTime物件。LocalDateTime是java.time類中的一個日期和時間,沒有時區或偏移。由于用戶既不輸入時區也不輸入偏移量,這似乎是適合我們目的的類。
關于如何將Format和JFormattedTextField一起使用,你可以參考我的另一個答案,下面有一個鏈接。
鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/310259.html
標籤:
