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

Java Swing双可移动圆形绘制问题:仅绿色圆形显示,蓝色不显示

问题排查与解决:蓝色圆形无法显示的原因及修复方案

我帮你梳理了代码里导致蓝色圆形(Bleu类)无法显示的几个核心问题,以及对应的修复办法:

核心问题1:绘制方法名称错误

Swing组件的自定义绘制必须重写paintComponent(Graphics g)方法,而你的Bleu类里写的是paintComponent1(Graphics f)——这个方法永远不会被Swing的绘制机制调用,所以蓝色圆形根本没有机会被画出来。

核心问题2:共享坐标变量+无独立尺寸

你把xPos和yPos定义在父类FenJeu里,Vert和Bleu共用这两个变量,这会导致两个圆形的位置完全绑定,初始值都是0的情况下,蓝色圆会被绿色圆完全挡住。另外,Bleu类没有重写getPreferredSize(),默认尺寸极小,就算绘制了也看不到。

核心问题3:布局导致组件被遮挡

FenJeu默认使用FlowLayout,你直接添加的Vert组件尺寸是1680x1050,会占据整个容器,导致Bleu被挤出可视区域。


完整修复后的代码

我把这些问题都修复了,同时优化了代码结构(比如每个圆形拥有独立坐标、复用按键绑定方法、调整布局为绝对定位):

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class FenJeu extends JPanel {
    public FenJeu(int r, int v, int b) {
        // 设置绝对布局,自由控制组件位置
        setLayout(null);
        // 创建绿色圆形并设置初始位置
        Vert vertCircle = new Vert();
        vertCircle.setBounds(100, 100, 50, 50);
        add(vertCircle);
        
        // 创建蓝色圆形并设置初始位置
        Bleu bleuCircle = new Bleu();
        bleuCircle.setBounds(300, 100, 50, 50);
        add(bleuCircle);
        
        // 设置父容器的整体尺寸
        setPreferredSize(new Dimension(1680, 1050));
    }

    // 通用按键绑定方法,两个圆形类复用
    protected void bindKeyStroke(JComponent comp, int condition, String name, KeyStroke keyStroke, Action action) {
        InputMap im = comp.getInputMap(condition);
        ActionMap am = comp.getActionMap();
        im.put(keyStroke, name);
        am.put(name, action);
    }

    public class Vert extends JPanel {
        // 绿色圆形的独立坐标
        private int xPos = 0;
        private int yPos = 0;

        public Vert() {
            // 设置透明背景,避免遮挡其他组件
            setOpaque(false);
            
            Action leftAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos -= 50;
                    xPos = Math.max(xPos, 0);
                    updatePosition();
                    repaint();
                }
            };
            Action rightAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos += 50;
                    xPos = Math.min(xPos, getParent().getWidth() - getWidth());
                    updatePosition();
                    repaint();
                }
            };
            Action upAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    yPos -= 50;
                    yPos = Math.max(yPos, 0);
                    updatePosition();
                    repaint();
                }
            };
            Action downAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    yPos += 50;
                    yPos = Math.min(yPos, getParent().getHeight() - getHeight());
                    updatePosition();
                    repaint();
                }
            };

            // 绑定方向键控制绿色圆形
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.left",
                    KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), leftAction);
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.right",
                    KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), rightAction);
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.up",
                    KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), upAction);
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.down",
                    KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), downAction);
        }

        // 更新组件位置
        private void updatePosition() {
            setBounds(xPos, yPos, getWidth(), getHeight());
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50); // 圆形尺寸
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setPaint(Color.GREEN);
            g2d.fillOval(0, 0, getWidth(), getHeight());
            g2d.dispose();
        }
    }

    public class Bleu extends JPanel {
        // 蓝色圆形的独立坐标
        private int xPos = 0;
        private int yPos = 0;

        public Bleu() {
            setOpaque(false);
            
            Action lefttAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos -= 50;
                    xPos = Math.max(xPos, 0);
                    updatePosition();
                    repaint();
                }
            };
            Action righttAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos += 50;
                    xPos = Math.min(xPos, getParent().getWidth() - getWidth());
                    updatePosition();
                    repaint();
                }
            };
            Action uppAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    yPos -= 50;
                    yPos = Math.max(yPos, 0);
                    updatePosition();
                    repaint();
                }
            };
            Action downnAction = new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    yPos += 50;
                    yPos = Math.min(yPos, getParent().getHeight() - getHeight());
                    updatePosition();
                    repaint();
                }
            };

            // 绑定Z/Q/S/D键控制蓝色圆形
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.leftt",
                    KeyStroke.getKeyStroke(KeyEvent.VK_Q, 0), lefttAction);
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.rightt",
                    KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), righttAction);
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.upp",
                    KeyStroke.getKeyStroke(KeyEvent.VK_Z, 0), uppAction);
            bindKeyStroke(this, WHEN_IN_FOCUSED_WINDOW, "move.downn",
                    KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), downnAction);
        }

        private void updatePosition() {
            setBounds(xPos, yPos, getWidth(), getHeight());
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50);
        }

        // 修复绘制方法名称,确保Swing能调用
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g3d = (Graphics2D) g.create();
            g3d.setPaint(Color.BLUE);
            g3d.fillOval(0, 0, getWidth(), getHeight());
            g3d.dispose();
        }
    }

    // 测试主方法
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Double Circle Controller");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new FenJeu(0,0,0));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}

关键修复点说明

  • 修正Bleu类的绘制方法名称为paintComponent,确保Swing能触发绘制逻辑
  • 给每个圆形类添加独立的坐标变量,避免两个圆形位置互相干扰
  • 设置圆形组件为透明背景(setOpaque(false)),防止遮挡其他组件
  • 使用绝对布局控制组件初始位置,避免布局管理器导致的遮挡问题
  • 修复了原代码中移动边界判断的错误(比如upAction误用getWidth的问题)
  • 复用按键绑定方法,简化代码结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:56:24