【问题标题】:Why do the date pickers trigger a JComboBox's actionPerformed unexpectedly?为什么日期选择器会意外触发 JComboBox 的 actionPerformed?
【发布时间】:2012-01-12 11:19:39
【问题描述】:

我有两个日期选择器组件和一个带有关联动作侦听器的 JComboBox 组件。我的问题是:当我从任何日期选择器中选择一个日期时,不会触发它们的关联事件,还会触发 JComboBox 的事件。更令人惊讶的是,首先触发 JComboBox 的事件!

另一方面,当我单击 JComboBox 组件并选择一个值时,只会触发 JComboBox 事件,而不会触发日期选择器事件,这很好。但是上段所述情况的原因是什么?

为了进一步澄清,这里是控制台的示例输出。首先我点击第一个日期选择器并选择一个日期:

index: -1  null
Combo Box is involved. Surprised?
This is only fired when datePicker1 is involved.

(是的,我很惊讶!)然后我点击第二个日期选择器并选择一个日期:

index: -1  null
Combo Box is involved. Surprised?
This is only fired when datePicker2 is involved.

(是的,我再次感到惊讶!)最后我点击组合框并选择一个项目:

 index: 1  Last 6 months
 Combo Box is involved. Surprised?

不,看到上面的输出我并不感到惊讶。

关于为什么会发生这种奇怪情况的任何想法?

完整的源代码:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;

import net.sourceforge.jdatepicker.JDateComponentFactory;
import net.sourceforge.jdatepicker.impl.JDatePickerImpl;
import net.sourceforge.jdatepicker.impl.UtilCalendarModel;
import org.jdesktop.swingx.JXDatePicker;

public class DatePickerDemo {

    private static boolean isDateRangeConsistent(UtilCalendarModel m1, UtilCalendarModel m2) {
        return m1.getValue().compareTo(m2.getValue()) <= 0 ? true : false;  
    }

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

        final JLabel label1 = new JLabel();
        label1.setText("Choose Range (Start - End): ");

        String[] fixedRanges = {"Last 3 months", "Last 6 months", "Last 12 months"};
        final JComboBox<String> fixedRangesComboBox = new JComboBox<String>(fixedRanges);
        fixedRangesComboBox.setSelectedIndex(-1);


        final JDatePickerImpl datePicker1 = (JDatePickerImpl) JDateComponentFactory.createJDatePicker();
        datePicker1.getModel().setSelected(true);

        final JDatePickerImpl datePicker2 = (JDatePickerImpl) JDateComponentFactory.createJDatePicker();
        datePicker2.getModel().setSelected(true);


        datePicker1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // Start date cannot be after end date!
                if ( ! isDateRangeConsistent((UtilCalendarModel) datePicker1.getModel(), 
                        (UtilCalendarModel) datePicker2.getModel())) { 
                    ((UtilCalendarModel) datePicker1.getModel())
                        .setValue(((UtilCalendarModel) datePicker2.getModel()).getValue());
                }

                //if the date range is changed by date picker, the fixed combo box becomes irrelevant
                fixedRangesComboBox.setSelectedIndex(-1);

                int rangeDaysStart = datePicker1.getModel().getDay();
                int rangeMonthsStart = 1 + datePicker1.getModel().getMonth();
                int rangeYearsStart = datePicker1.getModel().getYear();             
                label1.setText("Choose Range (Start - End): " + rangeDaysStart 
                                + "/" + rangeMonthsStart + "/" + rangeYearsStart);

                System.out.println("This is only fired when datePicker1 is involved.");
            }
        });


        datePicker2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // End date cannot be before start date!
                if ( ! isDateRangeConsistent((UtilCalendarModel) datePicker1.getModel(), 
                        (UtilCalendarModel) datePicker2.getModel())) {                  
                        ((UtilCalendarModel) datePicker2.getModel())
                            .setValue(((UtilCalendarModel) datePicker1.getModel()).getValue());
                }

                //if the date range is changed by date picker, the fixed combo box becomes irrelevant
                fixedRangesComboBox.setSelectedIndex(-1);

                int rangeDaysStart = datePicker2.getModel().getDay();
                int rangeMonthsStart = 1 + datePicker2.getModel().getMonth();
                int rangeYearsStart = datePicker2.getModel().getYear();             
                label1.setText("Choose Range (Start - End): " + rangeDaysStart 
                                + "/" + rangeMonthsStart + "/" + rangeYearsStart);

                System.out.println("This is only fired when datePicker2 is involved.");
            }
        });

        fixedRangesComboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              System.out.println("index: " + fixedRangesComboBox.getSelectedIndex() + "  "
                  + fixedRangesComboBox.getSelectedItem()); 

              System.out.println("Combo Box is involved. Surprised?");
            }
          });

        frame.getContentPane().add(label1, BorderLayout.NORTH);
        frame.getContentPane().add(datePicker1, BorderLayout.CENTER);        
        frame.getContentPane().add(datePicker2, BorderLayout.EAST); 
        frame.getContentPane().add(fixedRangesComboBox, BorderLayout.PAGE_END);

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

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

【问题讨论】:

  • JComboBox 的事件首先被触发 不,事实并非如此,相反,由于打印输出的顺序,它才会出现:选择器触发它的 actionEvent,在您的侦听器中更改触发组合动作的组合,在其侦听器中打印出消息,然后在选择器的侦听器中打印另一条消息

标签: java swing event-handling datepicker jcombobox


【解决方案1】:

您应该从两个 ActionListener 匿名类中删除 fixedRangesComboBox.setSelectedIndex(-1); :)

【讨论】:

  • 但是我怎样才能“重置”组合框呢?在我的用例中,如果用户在组合框中选择了某些内容,然后从日期选择器之一中选择了一个日期,我希望组合框被重置。
  • @EmreSevinç 不明白您为什么会感到惊讶 - 更改组合的选择总是会触发一个 actionEvent。这意味着当您以编程方式更改选择时触发...
  • 换句话说:我需要通过单击组合并选择一个项目来区分“更改组合的选择”,以及从日期选择器的 actionPerformed 函数中“更改组合的选择”。
  • 我通过控制 if index == -1(组合框中所选项目的索引)解决了这个问题。所以不需要跟踪事件是如何被触发的。我接受 Eng.Fouad 的回答,因为它通过澄清问题引导我找到解决方案。
【解决方案2】:

有(最好的解决方法)JCalendarSwingX,我从未见过 FocusAction 的任何问题,通过使用这两个 DatePickers 实现的方法或意外事件

【讨论】:

  • 删除了最后一条评论,OP not 使用 JXDatePicker - 被未使用的导入愚弄了 ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多