Ошибки DefaultListModel.clear - PullRequest
       1

Ошибки DefaultListModel.clear

0 голосов
/ 05 марта 2011

Я пытаюсь отобразить список элементов и, когда пользователь нажимает на элемент, очистить список и отобразить другой список.

Если я запустлю это и нажму на первую запись в отображаемом списке, программа умрет с большим количеством исключений во время выполнения. Если я уберу строку clear () (прокомментированную ниже), она будет работать нормально. Добавление try / catch не выявило никакой полезной для меня информации. Извиняюсь за длинный код, но я не мог понять, как сократить и по-прежнему генерировать ошибки.

Что я делаю не так?

import java.util.*;

import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

class ListGui extends JPanel implements ListSelectionListener {

    private static JList list;
    private static DefaultListModel listModel = new DefaultListModel();

    public ListGui() {
        super(new BorderLayout());
        list = new JList(listModel);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.addListSelectionListener(this);
        JScrollPane listScrollPane = new JScrollPane(list);
        add(listScrollPane, BorderLayout.CENTER);
    }

    public static void Populate(List<String> lines) {
        listModel.clear();
        for(String line : lines) {
            listModel.addElement(line);
        }
    }

    public void valueChanged(ListSelectionEvent e) {
        if (e.getValueIsAdjusting() == false) {
            List<String> out = new ArrayList<String>();
            out.add("three");
            out.add("four");
            Populate(out);
        }
    } 
}

public class TestClear {

    static JComponent newContentPane = new ListGui();

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("toast");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) { 

        List<String> out = new ArrayList<String>();

        createAndShowGUI();

        out.add("one");
        out.add("two");
        ListGui.Populate(out);               
    }
}

Ответы [ 2 ]

3 голосов
/ 05 марта 2011

Я пытаюсь отобразить список элементов и, когда пользователь нажимает на элемент, очистить список и отобразить другой список.

Для меня это не лучший дизайн. Выбор будет меняться всякий раз, когда вы нажимаете на элемент или когда вы используете клавиши со стрелками для перемещения вверх или вниз по списку. Я уверен, что пользователям, которым нравится использовать клавиатуру, список не нужно менять каждый раз, когда вы используете клавишу со стрелкой.

Нормальным дизайном будет вызывать действие в списке «двойным щелчком» или когда пользователь «Вводит» с keboard. Это легко реализовать, используя концепцию List Action .

Однако, если вы действительно хотите обновлять список при каждом выборе, я бы использовал код, подобный следующему:

list.removeListSelectionListener( this );
populate(...);
list.addListSelectionListener(this); 
1 голос
/ 05 марта 2011

Проблема заключается в том, что вы вызываете Populate () в valueChanged (), который вызывает valueChanged () и, следовательно, стекопоток.

Самое простое решение - иметь флаг для предотвращения повторного входа.

 boolean busy = false;
    public void valueChanged(ListSelectionEvent e) {

        if (e.getValueIsAdjusting() == false && !busy) {
            busy = true;
            List<String> out = new ArrayList<String>();
            out.add("three");
            out.add("four");
            Populate(out);
            busy = false;
        }
    } 

Если ваш код может быть доступен из нескольких потоков, вам следует изучить ReentrantLock

...