Как мы знаем, интерфейс ComboBoxModel используется для создания класса в witch, мы можем указать, как связать коллекции объектов (модель) с полем со списком, в основном путем предоставления необходимой «информации» о том, как получать элементы и устанавливать текущий элемент.
Обычно я писал эти классы, объявляя их членами коллекции , и просто делегировал некоторые функции объекту коллекции в реализованных методах.
Когда фактический класс из всех содержащихся объектов являются непроксируемыми объектами, все идет нормально (вероятно, в 90% случаев у нас возникает такая ситуация), но на этот раз мы сталкиваемся с фактом наличия ссылок на проксируемые объекты, и все идет странно неправильно.
Поведение JComboBox идет не так, поскольку он не может изменить текущий выбор.
Я пытаюсь получить дополнительную информацию, но на данный момент я знаю только, что метод setSelectedItem Интерфейс ComboBoxModel, который реализует любой конкретный класс, не вызывается, когда вокруг есть прокси-объекты. Вот мой вопрос: что происходит и, что более важно, поправимо ли это?
Оставляю пример, готов посмотреть и убедиться самому.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
/**
*
* @author Administrador
*/
public class AComboBoxWithProxyProblem extends JFrame implements ActionListener
{
ComboBoxModel modelWithProxies = new ItemComboBoxModelWithProxies();
ComboBoxModel modelWithoutProxies = new ItemComboBoxModelWithoutProxies();
public AComboBoxWithProxyProblem()
{
final JComboBox comboBox = new JComboBox();
comboBox.addActionListener( this );
getContentPane().setLayout(new BoxLayout(this.getContentPane(),BoxLayout.LINE_AXIS));
getContentPane().add(comboBox);
JRadioButton btnProxy = new JRadioButton("Proxy model");
btnProxy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
comboBox.setModel(modelWithProxies);
comboBox.setSelectedIndex(0);
}
});
getContentPane().add(btnProxy);
JRadioButton btnNoProxy = new JRadioButton("Non Proxy model");
btnNoProxy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e)
{
comboBox.setModel(modelWithoutProxies);
comboBox.setSelectedIndex(0);
}
});
getContentPane().add(btnNoProxy);
ButtonGroup group = new ButtonGroup();
group.add(btnProxy);
group.add(btnNoProxy);
setTitle("Mmmm...");
}
@Override
public void actionPerformed(ActionEvent e)
{
JComboBox comboBox = (JComboBox)e.getSource();
Item item = (Item)comboBox.getSelectedItem();
System.out.println("[actionPerformed] - " + item.getId() + " : " + item.getDescription() );
}
interface ItemInterface
{
String getDescription();
int getId();
@Override
String toString();
}
class Item implements AComboBoxWithProxyProblem.ItemInterface
{
private int id;
private String description;
public Item(int id, String description)
{
this.id = id;
this.description = description;
}
@Override
public int getId()
{
return id;
}
@Override
public String getDescription()
{
return description;
}
@Override
public String toString()
{
return description;
}
}
private class ItemComboBoxModelWithoutProxies extends AbstractListModel implements ComboBoxModel
{
List foos;
ItemInterface selected;
public ItemComboBoxModelWithoutProxies()
{
foos = new ArrayList ();
foos.add(new Item(1,"One"));
foos.add(new Item(2,"Two"));
foos.add(new Item(3,"Three"));
}
@Override
public Object getSelectedItem()
{
return selected;
}
@Override
public void setSelectedItem(Object tournament)
{
System.out.println("[setSelectedItem] " + tournament);
selected = (ItemInterface) tournament;
}
@Override
public int getSize()
{
return this.foos.size();
}
@Override
public Object getElementAt(int i)
{
return this.foos.get(i);
}
}
private class ItemComboBoxModelWithProxies extends AbstractListModel implements ComboBoxModel
{
List foos;
Object selected;
public ItemComboBoxModelWithProxies()
{
foos = new ArrayList ();
ItemInterface item;
item = (ItemInterface) Proxy.newProxyInstance(Item.class.getClassLoader(),
Item.class.getInterfaces(),
new ItemInvocationHandler (new Item(1,"One")));
foos.add(item);
item = (ItemInterface) Proxy.newProxyInstance(Item.class.getClassLoader(),
Item.class.getInterfaces(),
new ItemInvocationHandler (new Item(2,"Two")));
foos.add(item);
item = (ItemInterface) Proxy.newProxyInstance(Item.class.getClassLoader(),
Item.class.getInterfaces(),
new ItemInvocationHandler (new Item(3,"Three")));
foos.add(item);
}
@Override
public Object getSelectedItem()
{
return selected;
}
@Override
public void setSelectedItem(Object tournament)
{
System.out.println("[setSelectedItem] " + tournament);
selected = (ItemInterface) tournament;
}
@Override
public int getSize()
{
return this.foos.size();
}
@Override
public Object getElementAt(int i)
{
return this.foos.get(i);
}
private class ItemInvocationHandler implements InvocationHandler {
Item item;
public ItemInvocationHandler(Item item)
{
this.item = item;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
return method.invoke(this.item, args);
}
}
}
public static void main(String[] args)
{
JFrame frame = new AComboBoxWithProxyProblem();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible( true );
}
}
Подробнее здесь: https://stackoverflow.com/questions/179 ... ed-objects