Swing GUI Client Listeners не отвечает на обновление свойства Remote RMI - PullRequest
1 голос
/ 01 декабря 2011

У меня возникли проблемы с перерисовкой JTree при явном вызове его модели (вызов, который я делаю, когда добавляю в него несколько новых узлов).

Код, которыйИзначально работал нормально, теперь происходит сбой при экспорте приложения в RMI.

Я сохраняю объект DefaultTreeModel в классе Controller, который является удаленным объектом.

Я добавляю объект DefaultTreeModel в JTreeв моем клиенте, используя tree.addModel (controller.getModel ());

Я использую ActionListener, подписанный на кнопку в клиентском графическом интерфейсе, для вызова метода в контроллере, который выполняет действие «Добавить новый узел».

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

Не работают ли клиентские приемники Swing не через RMI?

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

Класс драйвера сервера:

package server;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import client.controller.TestTreeControllerService;

import server.controller.TestTreeControllerImpl;


public class TestTreeServerStart {

    /**
     * @param args
     */
    public static void main(String[] args) {
        new TestTreeServerStart();

    }

    public TestTreeServerStart() {

        try {

            LocateRegistry.createRegistry(1099);

            TestTreeControllerService c = new TestTreeControllerImpl();

             Registry registry = LocateRegistry.getRegistry();
             registry.rebind("TestTreeControllerService", c);

            System.out.println("Started the RMI Server");
        }
        catch (RemoteException e) {
            System.out.println(e.getMessage());
        }
    }

}

Класс реализации контроллера сервера:

package server.controller;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import client.controller.TestTreeControllerService;



@SuppressWarnings("serial")
public class TestTreeControllerImpl extends UnicastRemoteObject implements TestTreeControllerService {

    /**
     * 
     */
    //private static final long serialVersionUID = -8137864611400855504L;
    private DefaultTreeModel m ;


    public DefaultTreeModel getModel() {

        return m;
    }


    public TestTreeControllerImpl() throws RemoteException {

        super();
        m = new DefaultTreeModel(new DefaultMutableTreeNode("Root"));

    }

    public void addNodeAction() throws RemoteException {
        DefaultTreeModel m = (DefaultTreeModel) getModel();
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("New Node");
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) m.getRoot();
        root.add(newNode);
        //m.insertNodeInto(newNode, (DefaultMutableTreeNode) m.getRoot(), m.getChildCount(m.getRoot()));
        m.nodeStructureChanged(root);

    }

}

Класс драйвера клиента:

package client;
import java.rmi.Naming;
import java.rmi.RemoteException;

import client.controller.TestTreeControllerService;
import client.view.TreeTestClient;



public class TreeTestClientStart {

    /**
     * @param args
     */
    public static void main(String[] args) {


            try {
                TestTreeControllerService c = (TestTreeControllerService) Naming.lookup("rmi://localhost:1099/TestTreeControllerService");
                 new TreeTestClient(c);
            }
            catch(RemoteException e) {
                System.out.println("Remote service not found: " + e.getLocalizedMessage());
            }
            catch (Exception e) {
                System.out.println("Splat");
            }
    }

}

Интерфейс клиентского контроллера:

package client.controller;
import javax.swing.tree.DefaultTreeModel;


public interface TestTreeControllerService extends java.rmi.Remote {


    public DefaultTreeModel getModel() throws java.rmi.RemoteException;

    public void addNodeAction() throws java.rmi.RemoteException;
}

Интерфейс клиента:

package client.view;
import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;

import client.controller.TestTreeControllerService;
import client.view.action.AddNodeAction;
import client.view.action.RefreshTreeAction;



public class TreeTestClient {

    private JTree t;
    private TestTreeControllerService c;

    public JTree getTree() {
        return t;
    }

    public TestTreeControllerService getController() {
        return c;
    }

    public void setTree(JTree tIn) {
        t = tIn;
    }

    public TreeTestClient(TestTreeControllerService cIn) {

        //Add controller
        try {
            c = cIn;

            //Draw Frame & Panel  - set dimensions
            JFrame f = new JFrame();
            f.setSize(new Dimension(800,600));
            JPanel p = new JPanel();
            p.setSize(new Dimension(800,600));

            //Create a tree and add the Model from the Controller to it
            t = new JTree();
            t.setModel(c.getModel());


            //Try a Tree Model Listener
            t.getModel().addTreeModelListener(new RefreshTreeAction(this));

            //Add listener to a button which adds nodes to the tree when clicked
            JButton addNode = new JButton("Add node");
            addNode.addActionListener(new AddNodeAction(this));

            JScrollPane s = new JScrollPane(t);


            p.add(s);
            p.add(addNode);

            p.setVisible(true);
            f.add(p);
            f.setVisible(true);
    }
    catch(Exception e) {
        System.out.println("Splat");
    }
    }

}

* Слушатель действия "Добавить узел" клиента (вызывает добавление действия в контроллере) *

package client.view.action;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;

import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import client.view.TreeTestClient;


public class AddNodeAction implements ActionListener {

    private TreeTestClient treeTest;

public AddNodeAction(TreeTestClient treeTestIn) {
    treeTest=treeTestIn;
}
@Override
public void actionPerformed(ActionEvent arg0) {

    try {
        treeTest.getController().addNodeAction();
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

}

Клиент «Обновить действие» Tree Listener (Печатает на экране, чтобы доказать, что Listener запущен)

package client.view.action;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;

import client.view.TreeTestClient;


public class RefreshTreeAction implements PropertyChangeListener, TreeModelListener {

    private TreeTestClient treeTest;

    public RefreshTreeAction(TreeTestClient treeTestIn) {
        treeTest = treeTestIn;
    }
    private void refreshTree() {
        System.out.println("Refresh tree fired");

    }
    @Override
    public void treeNodesChanged(TreeModelEvent arg0) {
        refreshTree();

    }

    @Override
    public void treeNodesInserted(TreeModelEvent arg0) {
        refreshTree();
    }

    @Override
    public void treeNodesRemoved(TreeModelEvent arg0) {
        refreshTree();

    }

    @Override
    public void treeStructureChanged(TreeModelEvent arg0) {
            refreshTree();

    }
    @Override
    public void propertyChange(PropertyChangeEvent arg0) {
        refreshTree();

    }

}

Ответы [ 2 ]

2 голосов
/ 02 декабря 2011

TreeModel, экспортируемая сервером, сериализуется клиенту как его собственная копия.Сервер ничего не знает о том, что происходит с копией клиента, а клиент ничего не знает о том, что происходит с копией сервера.Это не один и тот же объект.

1 голос
/ 02 декабря 2011

Добавив следующий код в ActionListener, подписанный на новую кнопку в графическом интерфейсе, я смог проверить содержимое модели одним нажатием кнопки:

                //Loop contents of model attached to Client Tree
                for (int i=0; i<t.getModel().getChildCount(t.getModel().getRoot()); i++) {
                        System.out.println("From Tree: Row #" + i + ": " + t.getModel().getChild(t.getModel().getRoot(), i));
                }

                //Loop contents of model object stored in Controller
                try {
                    for (int i=0; i<c.getModel().getChildCount(c.getModel().getRoot()); i++) {
                        System.out.println("From Controller: Row #" + i + ": " + c.getModel().getChild(c.getModel().getRoot(), i));
                    }
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

Я обнаружил, чтоссылка на модель клиента отличалась от состояния, поддерживаемого в объекте модели контроллера.В цикле Client не было выходных данных, но цикл Controller дал правильное состояние.

Впоследствии я добавил таймер Swing в графический интерфейс, чтобы обновить модель дерева, чтобы она соответствовала модели конструктора.Далее следуют обновленный класс графического интерфейса и действие обновления графического интерфейса, которые работают:

Обновленный интерфейс:

package client.view;
import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.Timer;

import client.controller.TestTreeControllerService;
import client.view.action.AddNodeAction;
import client.view.action.GUIRefreshAction;
import client.view.action.RefreshTreeAction;



public class TreeTestClient {

    private JTree t;
    private TestTreeControllerService c;

    public JTree getTree() {
        return t;
    }

    public TestTreeControllerService getController() {
        return c;
    }

    public void setTree(JTree tIn) {
        t = tIn;
    }

    public TreeTestClient(TestTreeControllerService cIn) {

        //Add controller
        try {
            c = cIn;

            //Draw Frame & Panel  - set dimensions
            JFrame f = new JFrame();
            f.setSize(new Dimension(800,600));
            JPanel p = new JPanel();
            p.setSize(new Dimension(800,600));

            //Create a tree and add the Model from the Controller to it
            t = new JTree();
            t.setModel(c.getModel());

            //Try a listener that doesn't use the Remote object
            t.addTreeSelectionListener(new RefreshTreeAction(this));

            //Try a property change listener on the TreeModel   
            t.addPropertyChangeListener("treeModel", new RefreshTreeAction(this));

            //Try a Tree Model Listener
            t.getModel().addTreeModelListener(new RefreshTreeAction(this));

            //Add listener to a button which adds nodes to the tree when clicked
            JButton addNode = new JButton("Add node");
            addNode.addActionListener(new AddNodeAction(this));

            JScrollPane s = new JScrollPane(t);

            //Add a GUI redraw timer
            Timer timer = new Timer(1000, new GUIRefreshAction(this));
            timer.setInitialDelay(1);
            timer.start();

            p.add(s);
            p.add(addNode);

            p.setVisible(true);
            f.add(p);
            f.setVisible(true);
    }
    catch(Exception e) {
        System.out.println("Splat");
    }
    }

}

Класс прослушивателя обновления графического интерфейса

package client.view.action;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;

import client.view.TreeTestClient;

public class GUIRefreshAction implements ActionListener {

    private TreeTestClient client;

    public GUIRefreshAction(TreeTestClient clientIn) {
        client = clientIn;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        //Update the Tree's Model to match latest on Server
        try {
            client.getTree().setModel(client.getController().getModel());
        } catch (RemoteException e1) {
            e1.printStackTrace();
        }

    }

}

Надеюсь, это поможет кому-то, кто предъявляет те же требования к графическому интерфейсу клиента RMI Swing, обновляться в ответ на изменения на сервере.

...