gpt4 book ai didi

java - 具有动态代理对象的 ComboBoxModel

转载 作者:行者123 更新时间:2023-11-30 07:15:18 25 4
gpt4 key购买 nike

据我们所知 ComboBoxModel接口(interface)用于在女巫中创建一个类,我们可以指定如何将对象集合(模型)与组合框相关联,基本上是通过提供有关如何检索项目和设置当前项目的必要“信息”。一般来说,我写了那些声明为成员的类 Collection <of a concrete type> ,并在实现的方法中将一些功能委托(delegate)给集合对象。当所有包含对象的实际类都是非代理对象时,一切都很好(肯定有 90% 的情况是我们遇到这种情况),但这次要面对一个事实,即引用代理对象,事情就会出现奇怪的错误。JComboBox 行为出错,因为它无法更改当前选择。

我正在尝试获取更多信息,但到目前为止我只知道方法 setSelectedItemComboBoxModel接口(interface),当周围有代理对象时,任何具体类实现都不会调用。这是我的问题:发生了什么,更重要的是,它是否可以修复?

我举个例子,准备自己看看。

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<ItemInterface> 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<ItemInterface> 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 );
}

}

好了,就这些了!

谢谢!!

维克多。

最佳答案

问题是,JComboBox 正在使用 Object#equals 来比较值。

JComboBox#setSelectedIndex 正在调用 JComboBox#getSelectedItem,它正在使用...

for (int i = 0; i < dataModel.getSize(); i++) {
E element = dataModel.getElementAt(i);
if (anObject.equals(element)) {
found = true;
objectToSelect = element;
break;
}
}

在设置之前验证对象是否存在于模型中。

问题是,您的代理对象不是在 Proxy 上调用 equals,而是在它所代理的对象中调用 equals,这最终 begin false(因为 Proxy#equals(Proxy) 更像是 Proxy.objectBeginProxied#equsl(Proxy)

这实际上在 Java Docs 中注明了

An invocation of the hashCode, equals, or toString methods declared in java.lang.Object on a proxy instance will be encoded and dispatched to the invocation handler's invoke method in the same manner as interface method invocations are encoded and dispatched, as described above. The declaring class of the Method object passed to invoke will be java.lang.Object. Other public methods of a proxy instance inherited from java.lang.Object are not overridden by a proxy class, so invocations of those methods behave like they do for instances of java.lang.Object.

虽然我不确定你会如何解决这个问题

关于java - 具有动态代理对象的 ComboBoxModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17914317/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com