You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RMI浏览器项目:paintComponent无法在JPanel上绘制内容的问题

RMI浏览器项目绘制异常问题

我正在开发一个RMI浏览器项目,包含Service和ServiceServer两个接口,以及ServiceServerImpl(服务端)、ServiceBrowser(客户端)、DiceTester三个类。客户端调用实现Service接口的DiceTester类,获取其返回的序列化JPanel并添加到界面中,JButton和JComboBox组件能正常显示,但paintComponent方法无法在客户端的JPanel上绘制内容。以下是项目代码及运行步骤:

ServiceServer接口代码

import java.rmi.Remote;
import java.rmi.RemoteException;

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

Service接口代码

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

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

ServiceServerImpl(服务端)代码

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 DiceTester());
    }

    @Override
    public Object[] getServiceList() throws RemoteException {
        System.out.println("已进入远程方法");
        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());
//请移除包名或根据实际情况修改
        } catch (Exception Ex){
            Ex.printStackTrace();
        }
    }
}

ServiceBrowser(客户端)代码

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浏览器");
        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");
////请移除包名或根据实际情况修改
        } 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("摇骰子!");
        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("绘制完成");
        }
    }

    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);//中心点
                        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);//中心点
                        g2d.fillOval(RECT_X + 60, RECT_Y + 42, 20, 20);//中心点

                        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执行完成");
        }
    }
}

运行步骤

  • 在cmd中启动rmiregistry,确保其可访问类文件;
  • 在另一个终端运行ServiceServerImpl;
  • 在第三个终端运行ServiceBrowser,必须按此顺序启动否则会失败。

界面效果:GUI界面

内容的提问来源于stack exchange,提问作者Nili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:31:13