java 我可以在不向侦听器抛出事件的情况下为 JList 设置所选项目吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3092834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:18:52  来源:igfitidea点击:

Can I set the selected item for a JList without having an event thrown to the listeners?

javaswingeventsselectionjlist

提问by Andrei Vajna II

I am working on a viewer, which uses a JList to show thumbnails of the pages of a document. The user can open a page by selecting it through in the JList, or throught other mechanisms, like entering the number in a text box.

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

When using the latter alternative, I want that the JList also selects the page. I do this using setSelectedIndex(), but this triggers an event, which causes the page to be loaded again, as if the user had clicked and selected the page in the JList, and this is causing me some problems.

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

How I see it, the index should be set some way (perhaps in the model) so that only the UI of the JList updates, without firing an event that the index has changed.

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

Is this possible? Or is there a better way to solve my issue?

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

回答by Taisin

  1. You can remove all ListSelectionListenerfrom the list, make a selection and then add them again.

  2. You can create your own ListSelectionModelwith a method that doesn't throw the event and set it as a selection model to your JList, and then use getSelectionModel().yourSelectIndexMethod(index).

  3. You can also divert all your other methods of selection to the list, just find the corresponding entry if selecting the page by other means and select the item in the list. This way the item is selected and the page is loaded once.

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

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

  3. 您也可以将所有其他选择方式转移到列表中,如果通过其他方式选择页面,则只需找到相应的条目并选择列表中的项目即可。通过这种方式选择项目并加载页面一次。

Code for option 2:

选项 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);
}

}

回答by Catalina Island

It looks like setSelectedIndex()is just a convenient way to set the selection in the ListSelectionModel. Maybe your ListModelcould flag or cache the result so it won't get loaded a second time.

看起来setSelectedIndex()只是在ListSelectionModel. 也许你ListModel可以标记或缓存结果,这样它就不会被第二次加载。