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

使用方向键移动矩形的Java Applet程序无图形显示问题排查

解决Java Applet无图形显示及方向键移动问题

嘿,我帮你排查下这个Java Applet的问题——你看不到图形、方向键没反应主要是因为几个关键的Applet生命周期和绘图逻辑的错误,咱们一步步来修复:

核心问题分析

  • 缺少Applet生命周期方法,线程未启动
    Applet的运行依赖init()、start()这类生命周期方法,你代码里的loopThread根本没被初始化和启动,而且run()方法里的Graphics g是null,直接调用g.setColor()肯定会触发空指针异常,连绘图的基础条件都不满足。

  • 绘图逻辑错误:直接操作未初始化的Graphics对象
    你在updatePlatter()里直接操作null的Graphics对象,而且这种“擦除旧图形→更新位置→画新图形”的方式不符合AWT/Applet的绘图规范——正确的做法是让组件自己管理绘图,线程只负责更新状态,然后触发重绘。

  • 键盘事件处理不完整
    你只处理了按键按下的事件,没处理按键松开,这会导致按下方向键后托盘一直移动;另外Applet默认可能没有焦点,接收不到键盘事件。

修复后的完整代码

import java.awt.*;
import java.applet.Applet;

public class Game extends Applet implements Runnable {
    Thread loopThread;
    boolean left = false;
    boolean right = false;
    int platPos = 50;

    // Applet初始化:创建线程并设置焦点
    @Override
    public void init() {
        loopThread = new Thread(this);
        setFocusable(true); // 确保Applet能接收键盘事件
    }

    // Applet启动时启动线程
    @Override
    public void start() {
        if (loopThread != null && !loopThread.isAlive()) {
            loopThread.start();
        }
    }

    // Applet停止时终止线程
    @Override
    public void stop() {
        if (loopThread != null) {
            loopThread = null;
        }
    }

    @Override
    public void run() {
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        while (Thread.currentThread() == loopThread) {
            updatePlatterPosition(); // 只更新位置状态
            repaint(); // 触发paint()方法重绘
            try {
                Thread.sleep(16); // 控制帧率(约60fps),避免过度占用资源
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 单独处理位置更新逻辑
    private void updatePlatterPosition() {
        if (left) {
            platPos--;
        }
        if (right) {
            platPos++;
        }
        // 添加边界限制,防止托盘移出窗口
        platPos = Math.max(0, Math.min(getWidth() - 100, platPos));
    }

    // 重写paint方法,负责所有绘图操作
    @Override
    public void paint(Graphics g) {
        // 先清屏(用白色填充整个窗口)
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());
        // 绘制灰色托盘
        g.setColor(new Color(100, 100, 100));
        g.fillRect(50 + platPos, 200, 100, 20);
    }

    // 处理按键按下事件
    @Override
    public boolean keyDown(Event e, int key) {
        if (key == Event.LEFT) {
            left = true;
        } else if (key == Event.RIGHT) {
            right = true;
        }
        return true;
    }

    // 处理按键松开事件,避免托盘持续移动
    @Override
    public boolean keyUp(Event e, int key) {
        if (key == Event.LEFT) {
            left = false;
        } else if (key == Event.RIGHT) {
            right = false;
        }
        return true;
    }
}

关键改动说明

  • 规范Applet生命周期:通过init()创建线程、start()启动线程、stop()终止线程,符合Applet的运行机制。
  • 正确的绘图流程:所有绘图操作都放在paint()方法里,线程只负责更新位置状态,然后调用repaint()触发重绘,避免直接操作未初始化的Graphics对象。
  • 完善键盘事件:添加keyUp()方法,松开方向键时停止移动;设置setFocusable(true)确保Applet能接收键盘输入。
  • 优化体验:添加边界限制防止托盘移出窗口,通过Thread.sleep()控制帧率,减少资源消耗。

另外要提一句:Java Applet现在已经被绝大多数浏览器废弃了,如果你是用来学习AWT的基础绘图和线程知识没问题,但实际开发建议用Swing或者JavaFX这类更现代的UI框架哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:11:21