我是否可以为JList设置所选项目而不向监听器抛出事件?

时间:2010-06-22 12:00:45

标签: java swing events selection jlist

我正在使用一个查看器,它使用JList显示文档页面的缩略图。用户可以通过在JList中选择它或通过其他机制打开页面,例如在文本框中输入数字。

当使用后者时,我希望JList也选择页面。我使用setSelectedIndex()执行此操作,但这会触发一个事件,导致再次加载页面,就好像用户单击并选择了JList中的页面一样,这导致了一些问题。

我怎么看,索引应该以某种方式设置(可能在模型中),这样只有JList的UI更新,而不会触发索引已经改变的事件。

这可能吗?或者有更好的方法来解决我的问题吗?

2 个答案:

答案 0 :(得分:6)

  1. 您可以从列表中删除所有ListSelectionListener,进行选择,然后重新添加。

  2. 您可以使用不会抛出事件的方法创建自己的ListSelectionModel,并将其设置为JList的选择模型,然后使用getSelectionModel().yourSelectIndexMethod(index)

  3. 您还可以将所有其他选择方法转移到列表中,只需在通过其他方式选择页面时找到相应的条目,然后选择列表中的项目。这样就可以选择项目并加载页面一次。

  4. 选项2的代码:

    public class ListTest extends JPanel{
    
    private static final String[] items = new String[]{"1", "2", "3"};
    private JList mylist;
    private JComboBox myCombo;
    private JTextArea myTA;
    
    public ListTest() {
        setLayout(new BorderLayout());
        myCombo = new JComboBox(items);
        myCombo.addActionListener(new ActionListener(){
    
            @Override
            public void actionPerformed(ActionEvent e){
                valueSelectedCombo(myCombo.getSelectedIndex());
            }
        });
        JPanel pn = new JPanel();
        pn.setLayout(new BoxLayout(pn, BoxLayout.X_AXIS));
        pn.add(myCombo);
        pn.add(Box.createHorizontalGlue());
        pn.add(new JButton(new AbstractAction("Clear"){
    
            @Override
            public void actionPerformed(ActionEvent e){
                myTA.setText("");
            }
        }));
        add(pn, BorderLayout.NORTH);
        add(new JScrollPane(getJList()), BorderLayout.WEST);
        add(new JScrollPane(myTA = new JTextArea()), BorderLayout.CENTER);
    }
    
    private void valueSelectedList(int index){
        myTA.setText(myTA.getText() + "\n" + items[index]);
    }
    
    private void valueSelectedCombo(int index){
        myTA.setText(myTA.getText() + "\n" + items[index]);
        ((CustomSelectionModel)mylist.getSelectionModel()).setSelectionSilent(index);
    }
    
    private JList getJList(){
        if (mylist == null){
            mylist = new JList(items);
            mylist.setSelectionModel(new CustomSelectionModel());
            mylist.addListSelectionListener(new ListSelectionListener(){
    
                @Override
                public void valueChanged(ListSelectionEvent e){
                    if (!e.getValueIsAdjusting()){
                        valueSelectedList(mylist.getSelectedIndex());
                    }
                }
            });
    
            mylist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            mylist.setPreferredSize(new Dimension(100, 106));
    
        }
        return mylist;
    }
    
    private static class CustomSelectionModel extends DefaultListSelectionModel{
    
        private boolean isSilent = false;
    
        public void setSelectionSilent(int firstIndex){
            isSilent = true;
            setSelectionInterval(firstIndex, firstIndex);
            isSilent = false;
        }
        protected void fireValueChanged(int firstIndex, int lastIndex, boolean isAdjusting){
            if (isSilent){
                return;
            }
            super.fireValueChanged(firstIndex, lastIndex, isAdjusting);
        }
    }
    
    public static void main(String[] args){
        JFrame frame = new JFrame("test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
        // Add content to the window.
        frame.add(new ListTest());
    
        // Display the window.
        frame.pack();
        frame.setSize(300, 200);
        frame.setVisible(true);
    }
    
    }
    

答案 1 :(得分:1)

看起来setSelectedIndex()只是在ListSelectionModel中设置选择的便捷方式。也许您的ListModel可以标记或缓存结果,以便第二次不会加载。