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,必须按此顺序启动否则会失败。
界面效果:
内容的提问来源于stack exchange,提问作者Nili
相关产品推荐
相关产品推荐

