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

Java中Frame切换为JFrame出现绘制残留问题及JPanel使用咨询

问题根因

你遇到的残影问题本质是不规范的Swing绘制写法导致的,在AWT Frame上没出问题只是两个组件库的绘制逻辑差异造成的巧合:

  • AWT组件的默认重绘流程是:触发重绘时先调用update()方法,用背景色填充整个组件区域清空旧内容,再调用paint()执行自定义绘制。哪怕你重写paint()不调用父类实现,清屏步骤已经在update里做完了,所以旧的坐标文字不会残留。
  • Swing组件(包括JFrame)重写了这套逻辑,默认update()会直接调用paint(),而paint()的默认实现会依次执行三个步骤:绘制组件本身、绘制边框、绘制所有子组件,其中就包含清空旧内容的逻辑。你直接重写JFrame的paint()方法且没有调用super.paint(g),等于跳过了所有默认绘制流程,既不会清空之前画的内容,还可能出现组件层级渲染错乱。
  • 另外你代码里虽然创建了JPanel,但从来没把它添加到JFrame中,也没有把监听器绑定到有效组件上,自然达不到避开标题栏计算坐标的效果。
最简单的修复方案

不要重写JFrame的paint()方法,把自定义绘制逻辑放到JPanel上,这也是Swing官方推荐的标准写法,同时能自动解决标题栏计入坐标的问题——JPanel本身就是JFrame去掉标题栏的内容区域,点击坐标天然从JPanel左上角开始计算,不需要额外做坐标偏移。
修复后的可运行代码如下:

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

public class Proj07Runner {
  Proj07Runner(){
    System.out.println("Terminal text");
    new GUI();
  }
  // 补上原代码缺失的main入口
  public static void main(String[] args) {
    new Proj07Runner();
  }
}

// 自定义面板承载绘制逻辑,代替继承JFrame重写paint
class MyPanel extends JPanel {
  int clickX = -1;
  int clickY = -1;

  @Override
  protected void paintComponent(Graphics g) {
    // 必须先调用父类方法,这一步会自动清空面板上的旧绘制内容
    super.paintComponent(g);
    g.setColor(Color.BLACK);
    // 首次点击前不绘制坐标
    if (clickX != -1 && clickY != -1) {
      g.drawString(clickX + ", " + clickY, clickX, clickY);
    }
  }
}

class GUI {
  public GUI(){
    JFrame displayWindow = new JFrame();
    MyPanel myPanel = new MyPanel();
    displayWindow.setSize(300,100);
    displayWindow.setTitle("Title");
    // 把自定义面板添加到JFrame内容区域
    displayWindow.add(myPanel);

    // 只给面板加鼠标监听,获取的坐标自动排除标题栏区域
    myPanel.addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        myPanel.clickX = e.getX();
        myPanel.clickY = e.getY();
        // 触发面板重绘
        myPanel.repaint();
      }
    });

    // 用Swing自带的关闭逻辑代替自定义窗口监听器,写法更简洁
    displayWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    displayWindow.setVisible(true);
  }
}
关键改动说明
  • 删除了自定义继承JFrame的类,不需要修改JFrame本身的逻辑
  • 自定义MyPanel继承JPanel,重写paintComponent()而非paint(),第一行必须调用super.paintComponent(g),该方法会自动用面板背景色清空整个绘制区域,旧文字残影问题会直接解决
  • 鼠标监听器只绑定在JPanel上,获取到的坐标天然是面板内的有效坐标,不需要手动减去标题栏高度,正好匹配你最初的需求
  • 补上了原代码缺失的main方法,程序可以直接启动运行

通用Swing开发提示:所有自定义绘制逻辑,永远不要直接重写顶层容器(JFrame、JDialog)的paint方法,一律把绘制逻辑放在JPanel等轻量级组件上,重写paintComponent且第一行调用父类实现,能避开90%的Swing渲染异常问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:39:38