【问题标题】:Passing Swing classes (references) on network?在网络上传递 Swing 类(参考)?
【发布时间】:2011-08-15 20:29:31
【问题描述】:

我想知道是否可以通过 RMI 发送主要的 Swing 类事件/动作侦听器、事件、组件。

可能的情况:如果一个客户按下按钮或移动滑块,每个客户的按钮或滑块移动等对于其他摆动元素都是一样的。

我期待在 RMI 和 swing MVC 架构的上下文中得到答案,我想调用 swing 组件的模型,例如 ButtonModel,并希望在线发送 swing ActionEvent 并将 PropertyChangeListener/PropertyChangeSupport 注册为远程对象以获取更新在客户现场。

典型例子: 当模型发生一些变化时,服务器应该为每个客户端调用这个方法

 public void propertyChange(PropertyChangeEvent evt) {
        for (AbstractViewPanel view: registeredViews) {
            view.modelPropertyChange(evt);
        }
    }

如果一个客户端发生事件,则应从服务器调用每个客户端 actionPerformed:

@Override
public void actionPerformed(ActionEvent e)  {
}

可行吗?如果不是那为什么?我可能会遇到问题的地方,我的意思是哪些类是可转移(序列化)的,哪些不是......

编辑:在这里你看到我远程调用 Java Swing defaultbuttonmodel,当它的一些属性或方法改变其他客户端的获取更新时,唯一剩下的就是如果有人可以帮助我,请遵循 swing propertychangelistener 并意识到这一点,那就太好了:

public class RemoteButtonModel extends UnicastRemoteObject implements Model {

    private ButtonModel model = new DefaultButtonModel() ;

    protected myModel() throws RemoteException {
        super();
    }


    @Override
    public void setEnabled(boolean b) throws RemoteException {
        if (isEnabled())
            model.setEnabled(false);
        else{
            model.setEnabled(true);   
           }
    }

    @Override
    public boolean isEnabled() throws RemoteException {
        return model.isEnabled();

    }
}

【问题讨论】:

    标签: java model-view-controller swing user-interface rmi


    【解决方案1】:

    每个 Swing 类的 Javadoc 都说它不应该被序列化。

    您更可能应该传输相关的模型类。

    通过 RMI 监听事件是一种反模式。流量太大,故障点太多。

    【讨论】:

    • 这个想法是将 JComponent 的模型类保留在服务器上,并且只发送更改,而客户端上的控制器/视图。我想使用 Swing 默认 MVC 支持,请参阅我的其他问题了解详细信息。
    • @Static Void Main:您询问了有关通过 RMI 发送 Swing 组件的问题。我这样回答。如果你不这样做,那很好。如果您的问题在这里没有包含足够的上下文,也许您可​​以编辑它。
    【解决方案2】:

    我认为使用命令模式发送“滚动消息”或“按下按钮”消息会更有效。这将允许不同的客户端正确地使用不同的实现。

    编辑:

    我在客户端/服务器应用程序中执行此操作的方式(很容易适应您正在做的这种对等架构)是这样的(请注意,从我的生产代码复制并粘贴。)

    abstract public class UserRequest implements Serializable {
        
        public final String username;
        private transient ServersideThread thread;
        
        protected UserRequest(String username) {
            this.username = username;
            this.thread = null;
        }
        
        abstract public EngineMessage engineCallback(GenericEngine engine);
        
        public void setThread(ServersideThread thread) {
            if(this.thread == null) {
                this.thread = thread;
                return;
            }
            throw new IllegalStateException("Cannot set thread when already set:" + thread.getName());
        }
        
        public ServersideThread getThread() {
            return this.thread;
        }
    
    }
    

    所以,通过这种方法,我会做类似...

    public class SliderMoveNotification extends UserRequest {
    
        // need some way to say what slider moved
        public final int sliderId;
        public final int slideDistance;
    
        public SliderMoveNotification(String username) {
            super(username);
            sliderId = 0;
            sliderDistance = 0;
            throw new UnsupportedOperationException("Must supply a slider and a distance");
        }
    
        public SliderMoveNotification(String username, int sliderID, int slideDistance) {
            super(username);
            this.sliderId = sliderId;
            this.slideDistance = slideDistance;
        }
    
        public EngineMessage engineCallback(GenericEngine engine) {
            if(engine instanceof WindowEngine) {
                WindowEngine manager = (WindowEngine)engine;
                manager.slideWindow(sliderId,slideDistance);
                // you wouldn't need engine messages like I do in my client/server
                // relationship, but the idea stands.
            }
    
        }
    
    }
    

    【讨论】:

    • 更好的是,只需发送事件。它有更多信息,并且不需要发明语义事件,例如“按下按钮”。 (外部化可以处理可序列化的低效率。)
    • @alphazero 不同意。它将包含某些可能不兼容的数据。我当然赞成发送消息对象(比某些字符串更可靠......),但事件将特定于生成它的任何内容。
    • download.oracle.com/javase/1.5.0/docs/api/java/awt/… 没有太多“烘焙”内容。源代码显然是特定于 JVM 的,但请注意最后一个括号。外部化可以简单地取事件的类名..
    • @glowcoder:您是说通过客户端回调在接收字符串消息时触发其他客户端上的事件。 P.S:如果您的网站有一些具体的实现,我将不胜感激,因为我想了解不同解决方案的实现复杂性,所以我可以更进一步。
    • @alphazero:您正在谈论将事件发送到服务器,然后将该事件作为所有客户端的参数的服务器回调......已经定义的侦听器方法是否足以处理回调或者我会需要单独的方法来处理这些事件的回调。
    猜你喜欢
    • 2011-08-03
    • 1970-01-01
    • 2012-03-25
    • 2011-07-12
    • 1970-01-01
    • 2012-05-29
    • 2010-12-12
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多