javaswingdrawingrmipaintcomponent

paintComponent method doesn't draw on the JPanel in the RMI browser


I'm working on an RMI browser project. Which has two interfaces Service and ServiceServer. Three Classes ServiceServerImpl(Server), ServiceBrowser(Client), and DiceTester.

The ServiceBrowser (Client) calls the class DiceTester which implements the Service (Interface) which returns a serialized JPanel to the ServiceBrowser.

The ServiceBrowser adds the JPanel sent by the DiceTester, and even adds the JButton and JComboxBox, but when it calls the paintComponent method it doesn't draw anything on the Clients Browser.

ServiceServer Interface Code.

    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    public interface ServiceServer extends Remote {
        Object[] getServiceList() throws RemoteException;
        Service getService(Object serviceKey) throws RemoteException;
    }

ServiceInterface

    import javax.swing.*;
    import java.io.Serializable;

public interface Service extends Serializable {
    JPanel getGUIPane();
}

ServiceServerImpl (Server)

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;

public class ServiceServerImpl extends UnicastRemoteObject implements ServiceServer{
    HashMap serviceList;

    public ServiceServerImpl() throws RemoteException{
        setUpServices();
    }

    private void setUpServices(){
        serviceList = new HashMap();
        serviceList.put("New Dice Rolling Serivce", new DiceTester());
    }

    @Override
    public Object[] getServiceList() throws RemoteException {
        System.out.println("in remote");
        return serviceList.keySet().toArray();
    }

    @Override
    public Service getService(Object serviceKey) throws RemoteException {
        return (Service) serviceList.get(serviceKey);
    }

    public static void main(String[] args) {
        try{
            Naming.rebind("com.headfirstjava.ServiceServer", new ServiceServerImpl());
//Please remove the package name or change it accordingly.
        } catch (Exception Ex){
            Ex.printStackTrace();
        }
    }
}

ServiceBroswer(Client)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.Naming;

public class ServiceBrowser {
    JPanel mainPanel;
    JComboBox serviceList;
    ServiceServer server;

    private void buildGUI() {
        JFrame frame = new JFrame("RMI Browser");
        mainPanel = new JPanel();

        Object[] services = getServiceList();

        serviceList = new JComboBox(services);
        serviceList.addActionListener(new MyListListener());

        frame.getContentPane().add(BorderLayout.NORTH, serviceList);
        frame.getContentPane().add(BorderLayout.CENTER, mainPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setVisible(true);
    }

    private Object[] getServiceList() {
        Object obj = null;
        Object[] services = null;

        try {
            obj = Naming.lookup("rmi://127.0.0.1/com.headfirstjava.ServiceServer");
////Please remove the package name or change it accordingly.
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        server = (ServiceServer) obj;

        try {
            services = server.getServiceList();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return services;
    }

    class MyListListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            Object selection = serviceList.getSelectedItem();
            loadService(selection);
        }
    }

    private void loadService(Object serviceSelction) {
        try {
            Service svc = server.getService(serviceSelction);

            mainPanel.removeAll();
            mainPanel.add(svc.getGUIPane());
            mainPanel.validate();
            mainPanel.repaint();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new ServiceBrowser().buildGUI();
    }

}

DiceTester

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Objects;

public class DiceTester implements Service {
    static final long serialVersionUID = -7720503853902873983L;

    int i = 0;
    private static final int RECT_Y = 120;
    private static final int RECT_HEIGHT = 100;
    private static final int RECT_WIDTH = 100;

    JPanel mainPanel;
    JPanel diceTestPanel;
    JComboBox selection;

    @Override
    public JPanel getGUIPane() {
        mainPanel = new JPanel(new BorderLayout());
        JPanel componentPanel = new JPanel();
        diceTestPanel = new MyDrawPanel();

        String[] choices = {"0", "1", "2", "3", "4", "5"};
        selection = new JComboBox(choices);

        JButton button = new JButton("Roll 'em!");
        button.addActionListener(new RollTestListener());

        componentPanel.add(selection);
        componentPanel.add(button);
        mainPanel.add(BorderLayout.NORTH,componentPanel);
        diceTestPanel.add(new MyDrawPanel());

        mainPanel.add(BorderLayout.CENTER, diceTestPanel);

        return mainPanel;
    }

    class RollTestListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            mainPanel.repaint();
            System.out.println("Done");
        }
    }

    class MyDrawPanel extends JPanel {
        public void paintComponent(Graphics g) {
            int RECT_X = 10;
            String number = (String) selection.getSelectedItem();
            Graphics2D g2d = (Graphics2D) g;
            for (int x = 0; x < Integer.parseInt(Objects.requireNonNull(number)); x++) {
                g2d.setColor(new Color(0x0A0A0A));
                g2d.fill3DRect(RECT_X, RECT_Y, RECT_WIDTH, RECT_HEIGHT, true);

                int r = (int) ((Math.random() * 6) + 1);
                switch (r) {
                    case 1:
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(RECT_X + 36, RECT_Y + 36, 25, 25);
                        break;
                    case 2:
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(RECT_X + 20, RECT_Y + 36, 25, 25);
                        g2d.fillOval(RECT_X + 55, RECT_Y + 36, 25, 25);
                        break;
                    case 3:
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(RECT_X + 15, RECT_Y + 20, 25, 25);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 20, 25, 25);
                        g2d.fillOval(RECT_X + 37, RECT_Y + 50, 25, 25);
                        break;
                    case 4:
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(RECT_X + 15, RECT_Y + 15, 25, 25);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 15, 25, 25);
                        g2d.fillOval(RECT_X + 15, RECT_Y + 60, 25, 25);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 60, 25, 25);
                        break;
                    case 5:
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(RECT_X + 15, RECT_Y + 15, 20, 20);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 15, 20, 20);
                        g2d.fillOval(RECT_X + 37, RECT_Y + 37, 20, 20);//CenterDot
                        g2d.fillOval(RECT_X + 15, RECT_Y + 60, 20, 20);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 60, 20, 20);
                        break;
                    case 6:
                        g2d.setColor(Color.WHITE);
                        g2d.fillOval(RECT_X + 15, RECT_Y + 10, 20, 20);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 10, 20, 20);

                        g2d.fillOval(RECT_X + 15, RECT_Y + 42, 20, 20);//CenterDot
                        g2d.fillOval(RECT_X + 60, RECT_Y + 42, 20, 20);//CenterDot

                        g2d.fillOval(RECT_X + 15, RECT_Y + 75, 20, 20);
                        g2d.fillOval(RECT_X + 60, RECT_Y + 75, 20, 20);
                        break;
                }
                RECT_X += 120;
            }


            System.out.println("paintComponent done");
        }
    }
}

To run compile all the classes in let's say "classes" directory.

  1. cmd rmiregistry and make sure it has access to the classes.
  2. In another terminal java ServiceServerImpl.
  3. In another terminal java ServiceBrowser.

Should be open in the order given above else fails.

GUI


Solution

  • Ok, So, I'm actually reading this book "Head first java", and that was an exercise. A similar program was in the book. So I figured it out. And @camickr also suggested doing that.

    we have to override the getPrefferedSize() Method as @camickr also advised.

                public Dimension getPreferredSize(){
                return new Dimension(600,300);
            }
    

    Output After overriding the method