качели: выбор среди множества объектов - PullRequest
1 голос
/ 02 ноября 2010

Мне нужен метод статической утилиты для выбора объектов из List<T>. Я сталкиваюсь с двумя проблемами. Вот короткая тестовая программа:

package com.example.test.gui;

import java.util.Arrays;
import java.util.List;
import javax.swing.JOptionPane;

public class SelectionTest {
    public interface NameExtractor<T> {
        public String extractName(T object);
    }

    static public <T> T selectFromList(String message, List<T> list, NameExtractor<T> nameExtractor) {
        String[] choices = new String[list.size()];
        int i = 0;
        for (T t : list)
            choices[i++] = nameExtractor.extractName(t);
        Object s = JOptionPane.showInputDialog(null, message, "",
                JOptionPane.QUESTION_MESSAGE, null, choices, null);
        System.out.println(s);
        // crap, we get a string back. Now how do we get back the object in question?
        return null;
    }

    static public void main(String[] args)
    {
        List<Integer> numbers = Arrays.asList(1,2,3,4,10);
        System.out.println(selectFromList("Pick one", numbers, new NameExtractor<Integer>(){
            @Override public String extractName(Integer object) {
                return object.toString();
            }
        }));
    }
}

Есть ли альтернатива JOptionPane.showInputDialog () , которая позволила бы мне получить индекс списка, а не отображаемую строку?

edit: Я бы также предпочел использовать JList, а не поле со списком или то, что JOptionPane хочет по умолчанию.

Ответы [ 3 ]

2 голосов
/ 02 ноября 2010

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

/**
 * @param <T> element class
 * @param title dialog title
 * @param message message
 * @param list list
 * @param nameExtractor gets names from element
 * @return item from the list
 */
static public <T> T selectFromList(String title, String message, List<T> list, NameExtractor<T> nameExtractor) {
    JPanel p = new JPanel();
    JList jlist = new JList();
    DefaultListModel model = new DefaultListModel();
    for (T t : list)
        model.addElement(nameExtractor.extractName(t));
    jlist.setModel(model);
    p.setLayout(new BorderLayout());
    p.add(new JLabel(message), BorderLayout.NORTH);
    p.add(jlist, BorderLayout.CENTER);
    JOptionPane op = new JOptionPane(p, JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
    JDialog d = op.createDialog(title);
    d.setVisible(true);
    Object sel = op.getValue();
    int i = jlist.getSelectedIndex();
    d.dispose();
    if (i != -1 && sel instanceof Integer && (Integer)sel == JOptionPane.OK_OPTION)
        return list.get(i);
    else
        return null;
}
2 голосов
/ 02 ноября 2010

Есть ли альтернатива JOptionPane.showInputDialog (), которая позволила бы мне получить индекс списка, а не отображаемую строку?

Все методы панели опций showXXX позволяют вам добавлять любые объекты непосредственно на панель опций. Таким образом, вы можете просто добавить свой список (панель прокрутки?) В диалоговое окно.

JList list = new JList(...);
int value = JOptionPane.showOptionDialog(null, list, ...);

Прочтите раздел из учебника по Swing на Как использовать диалоги . Вы можете даже запретить закрытие диалогового окна, пока элемент не будет выбран из списка, если хотите.

2 голосов
/ 02 ноября 2010

Почему бы вам просто не поместить объекты в JOptionPane вместо того, чтобы помещать массив строк?JOptionPane вызовет метод toString объекта для отображения.

    Object selectedObject = JOptionPane.showInputDialog(null, message, "",
            JOptionPane.QUESTION_MESSAGE, null, list.toArray(), null);

    return (T)selectedObject;

ИЛИ :

Поиск по именам для выбранного имени и возврат объекта:

    for(int j = 0 ; j < choices.length; j++){
        if(selectedObject.equals(choices[j])){
            return list.get(j);
        }
    }
    return null;
...