【问题标题】:Double printing JList双打印JList
【发布时间】:2017-12-23 22:57:06
【问题描述】:

我不确定为什么所有内容都打印两次。例如,如果您按“Male”,则程序将打印 MaleMale。这是一个更大程序的一部分:我想要性别(一个字符串)来存储最后的选择。这段代码是这样做的吗?

DefaultListModel toAdd = new DefaultListModel();
toAdd.addElement("Male");
toAdd.addElement("Female");
toAdd.addElement("Others");

JList list = new JList();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setBorder(new TitledBorder(null, "How do you identify yourself?", ` 
TitledBorder.CENTER, TitledBorder.TOP, null, null));
list.setBackground(SystemColor.info);
list.setBounds(57, 85, 244, 97);
list.setModel(toAdd);
frame.getContentPane().add(list);

list.addListSelectionListener(new ListSelectionListener() {

        public void valueChanged (ListSelectionEvent event) {
            int lastSelIx = list.getMaxSelectionIndex();
            gender = (String) list.getModel().getElementAt(lastSelIx);
            System.out.print(gender);
        }       
    );
}

【问题讨论】:

  • 每次更改都会收到两个valueChanged 事件吗?
  • 1) 为了尽快获得更好的帮助,请发帖 minimal reproducible exampleShort, Self Contained, Correct Example。 2) Java GUI 必须在不同的语言环境中使用不同的 PLAF 在不同的操作系统、屏幕尺寸、屏幕分辨率等上工作。因此,它们不利于像素完美布局。而是使用布局管理器,或combinations of them 以及white space 的布局填充和边框。 3)"How do you identify yourself?"在性别方面..
  • .. 这更常表示为ButtonGroup 中的单选按钮 (JRadioButton)。为每个按钮添加一个ActonListener,以便为每个选择获取一个操作事件(而不是JList 中的每个选择两个事件)。

标签: java swing jlist


【解决方案1】:

一般来说,ListSelectionListener 会产生两个事件,一个用于“取消选择”当前选定的项目/范围,一个用于“选择”新项目/范围。

如果您只对已选择的内容感兴趣,您可以使用ListSelectionEvent#getValueIsAdjusting,如果还有更多活动将返回true,如果没有更多相关活动(或选择)将返回false已经稳定了),例如...

import java.awt.EventQueue;
import java.awt.SystemColor;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class JavaApplication20 {

    public static void main(String[] args) {
        new JavaApplication20();
    }

    public JavaApplication20() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                DefaultListModel toAdd = new DefaultListModel();
                toAdd.addElement("Male");
                toAdd.addElement("Female");
                toAdd.addElement("Others");

                JList list = new JList();
                list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                list.setBorder(new TitledBorder(null, "How do you identify yourself?", TitledBorder.CENTER, TitledBorder.TOP, null, null));
                list.setBackground(SystemColor.info);
                list.setModel(toAdd);
                frame.getContentPane().add(new JScrollPane(list));

                list.addListSelectionListener(new ListSelectionListener() {

                    public void valueChanged(ListSelectionEvent event) {
                        if (!event.getValueIsAdjusting()) {
                            int lastSelIx = list.getMaxSelectionIndex();
                            String gender = (String) list.getModel().getElementAt(lastSelIx);
                            System.out.println(gender);
                        } else {
                            // You can ignore this, I was just testing ;)
                            int lastSelIx = event.getFirstIndex();
                            String gender = (String) list.getModel().getElementAt(lastSelIx);
                            System.out.println(gender);
                        }
                    }
                });
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

您可以阅读How to Write a List Selection Listener了解更多详情

【讨论】:

  • 一时我还以为第一个事件可能是“取消选择”引起的,但事实并非如此。 (也许你(和我 ;-))将它与 JCheckBox 混合在一起,ChangeListener 会导致“取消选择事件”,通常,人们只希望 ActionListener 用于选择)。不过getValueIsAdjusting的一般解法是一样的。
  • @Marco13 我确信我已经看到它为键盘和编程选择更改执行双重事件 - 认为我可以让它工作。我第一次测试这个时,我无法让它为鼠标按下和释放生成单独的事件,但下一次我运行它时确实如此 - 所以很混乱
  • 现在可能会详细介绍。如果要进一步调查这些细节:我还认为它可能取决于 LookAndFeel,因为这可能会控制此类事件在“复杂”组件(如 JList)中的行为。但是对于getValueIsAdjusting,应该是安全的。
【解决方案2】:

每次单击列表中的项目时会生成两个事件:第一个在您按下鼠标按钮时创建,第二个在您松开 按钮。

(这主要与更复杂的范围选择模式、拖放模式或按下一个项目上的按钮然后将鼠标拖到另一个项目的情况有关)

解决方法是检查ListSelectionListener中的“选择值是否还在调整中”。所以你可以做类似的事情

if (event.getValueIsAdjusting()) return;

在您的事件侦听器方法中。

这里是一个 MCVE,以及其他一些清理工作:

import java.awt.SystemColor;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class JListSelectionDoubleEvent
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        DefaultListModel<String> listModel = new DefaultListModel<String>();
        listModel.addElement("Male");
        listModel.addElement("Female");
        listModel.addElement("Others");

        JList<String> list = new JList<String>(listModel);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setBorder(
            BorderFactory.createTitledBorder("How do you identify yourself?"));
        list.setBackground(SystemColor.info);

        list.addListSelectionListener(new ListSelectionListener()
        {
            @Override
            public void valueChanged(ListSelectionEvent event)
            {
                if (event.getValueIsAdjusting())
                {
                    //System.out.println("Adjusting. Ignore this");
                    return;
                }
                String gender = list.getSelectedValue();
                System.out.print(gender);
            }
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(list);
        frame.setSize(400, 400);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多