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

JPanel异常问题:点击按钮后子面板无法正常显示圆形

Java Swing 图形绘制与组件显示问题修复

需求与问题现象

需求

实现初始界面显示图片与JButton,点击按钮后隐藏二者,显示带有圆形的子面板及左右箭头按钮,通过点击箭头重绘圆形实现移动。

问题现象

  • 初始界面显示正常
  • 点击按钮后子面板显示,但无圆形(仅示例文本可见)
  • 点击箭头按钮后圆形仍不出现,按钮旁反而出现第二个无圆形的子面板
  • 调整布局、面板大小后问题未解决

问题代码

驱动类 FinalProject

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class FinalProject{
   
   public static void main(String[] args){
      JFrame frame = new JFrame("exploration game");
      frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      Graphics x = frame.getGraphics();
      FinalProjectPanel panel = new FinalProjectPanel(x, new BorderLayout());
      frame.getContentPane().add(panel);
      frame.pack();
      frame.setResizable(false);
      
}
}

主面板类 FinalProjectPanel

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;
public class FinalProjectPanel extends JPanel{
   private JButton startButton;
   private JLabel starttext;
   private ImageIcon startingscren;
   private JButton Left;
   private JButton Right;
   private GraphicSubpanel subpanel;
   
   public FinalProjectPanel(Graphics g, BorderLayout b){
      startingscren = new ImageIcon("starting-screen.png");
      starttext = new JLabel(startingscren);
      starttext.setVisible(false);
      startButton = new JButton("Start Game");
      
      startButton.addActionListener(new startListener());
      Left = new JButton("<-");
      Left.setVisible(false);
      Left.addActionListener(new leftListener());
      Right = new JButton("->");
      Right.addActionListener(new rightListener());
      Right.setVisible(false);
      setPreferredSize(new Dimension(500,500));
      subpanel = new GraphicSubpanel(g, 10, 100);
      subpanel.setPreferredSize(new Dimension(100,100));
      subpanel.setVisible(false);
      
      add(starttext, BorderLayout.PAGE_START);
      add(startButton, BorderLayout.PAGE_END);
      
      add(Left,BorderLayout.LINE_START);
      add(Right,BorderLayout.LINE_END);
      add(subpanel, BorderLayout.CENTER);
      
      
   }
   
   private class startListener implements ActionListener{
      public void actionPerformed (ActionEvent event){
         startButton.setVisible(false);
         starttext.setVisible(false);
         subpanel.setVisible(true);
         Left.setVisible(true);
         Right.setVisible(true);
      }
   }
   
   private class leftListener implements ActionListener{
      public void actionPerformed (ActionEvent event){
         subpanel.setX(subpanel.getX()-10);
      }
   }
   private class rightListener implements ActionListener{
      public void actionPerformed (ActionEvent event){
         subpanel.setX(subpanel.getX()+10);
      }
   }
}

绘图子面板类 GraphicSubpanel

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;

public class GraphicSubpanel extends JPanel{
   
   private int x;
   private int y;
   private JLabel randomlabel;
   private Circle player;
   private Graphics2D g2d;
   public GraphicSubpanel(Graphics g2d, int x, int y){
     this.x = x;
     this.y = y;
     this.g2d = (Graphics2D) g2d;
     randomlabel = new JLabel("sample text");
     player = new Circle(60,x,y);
     player.setVisible(true);
     add(player);
     add(randomlabel);
     setBackground(Color.YELLOW);
     repaint();
     
   }
   public int getX(){
      return x;
   }public int getY(){
      return y;
   }
   public void setX(int a){
      x = a;
      repaint();
   }
   public void setY(int a){
      y = a;
      repaint();
   }
   
   private class Circle extends JComponent {
   
      private int diam;
      private int x;
      private int y;
   
      public Circle(int diam, int x, int y) {
         this.diam = diam;
         this.x = x;
         this.y = y;
         setPreferredSize(new Dimension(diam, diam));
      }
   
      @Override
      public void paintComponent(Graphics g) {
         super.paintComponent(g2d);
         g2d.setColor(Color.RED);
         g2d.fillOval(x, y, diam, diam);
         System.out.println("test");
      }
      public int getX(){
         return x;
      }
      public int getY(){
         return y;
      }
}

}

核心问题与修复点

  1. 禁止提前获取Graphics对象:删除main方法中Graphics x = frame.getGraphics();的调用,Swing组件的绘制必须使用paintComponent方法传入的上下文,临时获取的Graphics对象会失效。
  2. 重命名冲突的getX/getY方法:将自定义的坐标方法改为getCircleX/setCircleX,避免覆盖JComponent自带的组件位置获取方法,解决布局混乱问题。
  3. 修正Circle的绘制逻辑:
    • 在paintComponent中使用方法参数的g,转换为Graphics2D,而非外部传入的对象
    • 圆形绘制使用自身组件的相对坐标(0,0),通过setBounds控制组件在父面板的位置
  4. 同步坐标更新:点击箭头时,更新GraphicSubpanel的坐标后,同步更新Circle的坐标并调用repaint()
  5. 调整窗口初始化顺序:main方法中先添加组件,再调用frame.setVisible(true),确保组件正确渲染
  6. 修复布局问题:GraphicSubpanel使用绝对布局(或根据需求选择合适布局),避免FlowLayout导致的组件排列混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 03:34:50