【问题标题】:How to trace any change in JTextField in order to update other textfields immediately?如何跟踪 JTextField 中的任何更改以立即更新其他文本字段?
【发布时间】:2015-08-18 22:01:35
【问题描述】:

我想编写一个简单的 Swing 应用程序。它应该根据用户输入(初始日期和天数)计算日期。 这就是我的应用程序现在的样子。

但是由于经验不足,我在应用程序中遇到了一些问题。

  1. 当中间字段 textField 中的值更改时,resultDayField 中的值不会更改,但只有在按下“Enter”后才会更改。我在这里看到了如何使用DocumentListenerJFormattedField 跟踪更改的不同解决方案,但我的情况需要面板中所有小部件的通用侦听器以同时跟踪更改。我不明白如何混合ActionListenerDocumentListener 来同时使用它们。我该怎么办?

  2. 此外,如果中间字段 textField 为空,则选择任何日期都会导致应用程序崩溃并出现空指针异常。但是我不明白为什么应用程序不能只写“Null”。

  3. 一段奇怪的代码

    SomeActionListener listen = new SomeActionListener(datePicker, textField, resultDateField);
    datePicker.addActionListener(listen);
    textField.addActionListener(listen);
    

    我不确定这样做是否好。

您能评论一下这些问题吗?

这是应用程序的两个源文件。 第一个(主要)是TestJDatePicker.java

import org.jdatepicker.JDatePicker;
import org.jdatepicker.impl.JDatePanelImpl;
import org.jdatepicker.impl.JDatePickerImpl;
import org.jdatepicker.impl.UtilDateModel;

import javax.swing.*;
import java.awt.*;
import java.util.Properties;

public class TestJDatePicker extends JPanel {
    JTextField textField;
    JTextField resultDateField;
    JDatePicker datePicker;

    public TestJDatePicker() {

        Properties p = new Properties();
        p.put("text.today", "Today");
        p.put("text.month", "Month");
        p.put("text.year", "Year");

        UtilDateModel model = new UtilDateModel();
        JDatePanelImpl datePanel = new JDatePanelImpl(model, p);
        JDatePickerImpl datePicker = new JDatePickerImpl(datePanel, new DateLabelFormatter());

        textField = new JTextField(20);
        textField.setText("10");

        resultDateField = new JTextField(20);

        SomeActionListener listen = new SomeActionListener(datePicker, textField, resultDateField);

        datePicker.addActionListener(listen);
        textField.addActionListener(listen);

        add(datePicker);
        add(textField);
        add(resultDateField);

        setPreferredSize(new Dimension(850, 450));
        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
    }

    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("DocumentEventDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new TestJDatePicker();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

我写的第二个文件是SomeActionListener.java:

import org.jdatepicker.impl.JDatePickerImpl;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class SomeActionListener implements ActionListener {

    private JTextField resultDateField;
    private JTextField textField;
    private JDatePickerImpl datePicker;
    //...

    public SomeActionListener(JDatePickerImpl datePicker, JTextField textField, JTextField resultDateField){
        this.textField=textField;
        this.datePicker=datePicker;
        this.resultDateField = resultDateField;
        //...
    }

    public void actionPerformed(ActionEvent e) {
        final SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
        Date selectedDate = (Date) datePicker.getModel().getValue();
        //System.out.println(selectedDate);
        System.out.println(textField.getText());

        int days = Integer.parseInt(textField.getText());

        Calendar cal = Calendar.getInstance();
        cal.setTime(selectedDate);
        cal.add(Calendar.DATE, days);

        resultDateField.setText(cal != null ? sdf.format(cal.getTime()) : null);
    }

}

【问题讨论】:

  • “但我的情况需要面板中所有小部件的通用侦听器以同时跟踪更改” 这是否意味着对任何字段的任何更改都可能导致其他字段的更改?如果有,是什么关系?
  • int days = Integer.parseInt(textField.getText()); 将在文本字段为空时导致Exception,因为"" 不是有效数字,您需要先检查该字段是否有值,然后再执行任何其他操作计算。
  • 中间字段上的DocumentListener 是检测实时变化的最佳选择。你也可以考虑JSpinner
  • @MadProgrammer 左侧和中间字段应相互跟踪,以便在右侧字段中计算正确的日期。右侧字段不应该是可编辑的。
  • 所以,据我了解,左侧和中间字段在更改时会更新右侧字段,但左侧或右侧字段都不会相互影响,对吧?

标签: java swing actionlistener jtextfield


【解决方案1】:

当中间字段 textField 中的值更改时,没有 resultDayField 发生变化,但仅在按下“Enter”后才会发生变化。我看到这里 不同的解决方案如何使用 DocumentListener 和 JFormattedField 但我的情况需要所有人的通用监听器 面板中的小部件可同时跟踪更改。我不明白 如何混合使用 ActionListener 和 DocumentListener 来同时使用它们。什么 我应该怎么做?

首先创建一个从日期选择器和文本字段中获取值的方法,生成所需的结果并更新正确的字段

在日期选择器上使用 ActionListener(或其他适当的侦听器),让该侦听器调用您的“更新”方法

在文本字段上使用 DocumentListener,当它的任何事件通知方法被调用时,调用你的“更新”方法

此外,如果中间字段 textField 为空,则选择任何日期都会 使用空指针异常使应用程序崩溃。但我没有 了解为什么应用不能只写“Null”。

int days = Integer.parseInt(textField.getText()); 在文本字段为空时会导致Exception,因为"" 不是有效数字,您需要先检查该字段是否有值,然后再进行任何其他计算。

关于您的最后一个问题,不,以这种方式使用单个侦听器并不罕见。虽然我建议在您的情况下使用两个不同的侦听器,但它们会将其实际功能委托给共享方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-16
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    相关资源
    最近更新 更多