3

我刚刚开始学习 Java 编程,甚至最近学习图形,我遇到了一些问题。我想创建一个外观类似于矮人要塞的游戏,使用彩色文本而不是图像。

这是我到目前为止所拥有的:

public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.red);

    for (int i = 0; i < 50; i++) {
        g.drawString("[Game goes here]", 100, 150);
        g.dispose();
        System.out.println(i);
    }
    g.dispose();
}

public GTest() {
    setSize(Toolkit.getDefaultToolkit().getScreenSize().width / 3, Toolkit
            .getDefaultToolkit().getScreenSize().width / 3 + 50);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
}

public static void main(String[] args) {
    GTest myWindow = new GTest();
}

我希望它更新计时器上的图形,但我不确定如何执行此操作。

我知道这是一个相当广泛的问题,我很乐意澄清您可能想知道的任何事情。

编辑:

所以我添加了这一点:

String[] letters = new String[10];
float fontsize = Toolkit.getDefaultToolkit().getScreenSize().width / 30;

public void paint(Graphics g) {

    g.setColor(textColor);
    setFont(getFont().deriveFont(fontsize));
    for(int i = 0; i < 10; i++){
        if((int) (Math.random() * 100) > 97){
            letters[i] = "w";
            textColor = new Color(0, 0, 100);

        }else{
            letters[i] = "l";
            textColor = new Color(0, 100, 0);
        }
        g.drawString(letters[i], i * 3, 10);
    }

但现在它根本不显示。我在 g.drawString 之后添加了一个 sysout 并执行了它,所以我不确定问题是什么。

4

2 回答 2

2

在 Swing 中基于计时器做任何事情时,javax.swing.Timer类是你最好的朋友。

它的 JavaDocs 很好地解释了它的用法,所以这里有一个例子。

public class GTest extends JFrame implements ActionListener {
    private Color textColor = Color.BLACK;
    private Random random = new Random();

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(textColor);
        g.drawString("[Game goes here]", 100, 150);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        textColor = new Color(random.nextInt(0x00ffffff));
        repaint();
    }

    public GTest() {
        setSize(Toolkit.getDefaultToolkit().getScreenSize().width / 3,
                Toolkit.getDefaultToolkit().getScreenSize().width / 3 + 50);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        Timer timer = new Timer(500, this);
        timer.setInitialDelay(0);
        timer.start();

        setVisible(true);
    }

    public static void main(String[] args) {
        GTest myWindow = new GTest();
    }
}

又是你的GTest课,但这次文本颜色每 0.5 秒自动更改一次。

注意两个主要变化:

  1. 构造函数现在设置一个Timer没有初始延迟的新实例,周期为 500 毫秒,其侦听器设置为this. 这意味着这个构造的实例将监听该计时器的滴答声。
  2. 为此,我们需要实现ActionListener接口。这迫使我们编写actionPerformed()每次 Timer 滴答时都会调用的方法。在此方法中,我们将 textcolor 更改为随机颜色并调用repaint()它随后调用我们的paint()方法并获取写入的文本。

PS你不必每次都对dispose()你的对象。Graphics它实际上也在它的 JavaDoc 中说过(强调我的):

当这些方法返回时,作为参数提供给组件的paint()update()方法的图形对象由系统自动释放。为了提高效率,程序员应该 dispose()在使用完一个Graphics对象后调用,只有当它是直接从一个组件或另一个Graphics对象创建时。

于 2013-09-10T21:25:57.610 回答
2

首先,如果您不创建Graphics上下文的副本,则不应丢弃它。这实际上可以防止您的申请表的其他部分被绘制;)

其次。我会避免从顶级容器扩展,例如JFrame,除了允许您在窗口的框架/边框装饰下绘制之外,它们不是双缓冲的。

相反,我会使用类似 a 的东西JPanel并覆盖它的paintComponent方法。这将为您提供自动双缓冲。

因为 Swing 是一个单线程框架,所以对 UI 的所有更新都应该在 Event Diapatching Thread 的上下文中执行。

在尝试执行诸如等待和同步绘画更新之类的事情时,这使现场变得有些困难。

幸运的是,Swing 提供了一个javax.swing.Timer允许您在未来某个时间安排活动的功能。这也可以设置为重复和定期间隔。

Timer timer = new Timer(40, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // perform your required actions here
    }
});

现在,请注意,该actionPerformed方法是在 EDT 的上下文中执行的,这意味着,您在此处执行的任何长时间运行/耗时的处理都可能导致您的 UI 停止绘制

看一眼

更多细节...

于 2013-09-10T21:38:37.980 回答