Java - 游戏在绘制方法中循环还是在单独线程的 while 循环中循环?

标签 java multithreading jpanel paint

我正在尝试编写一个应用程序,该应用程序获取用户鼠标输入并在每次单击时绘制一个点(并不是特别重要)。游戏循环函数应该在哪里,在 Paint 方法中还是在单独的 while 循环中?这是我的代码:

import java.awt.*;
import java.awt.geom.*;

import javax.swing.*;


@SuppressWarnings("serial")
public class Main extends JPanel{

    static Rectangle scrnSize = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
    //static Dimension wholeScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
    //public static int taskbarHeight = wholeScreenSize.height - scrnSize.height;

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.RED);
        g2d.fillOval(0, 0, 30, 30);
        g2d.drawOval(0, 50, 30, 30);        
        g2d.fillRect(50, 0, 30, 30);
        g2d.drawRect(50, 50, 30, 30);

        g2d.draw(new Ellipse2D.Double(0, 100, 30, 30));
        //do loop stuff here?
    }

    public static void main(String[] args) throws InterruptedException {
        //init
        JFrame frame = new JFrame("DrillSweet");
        frame.setLayout(new GridLayout());
        Main main = new Main();
        frame.add(main);
        frame.setSize(new Dimension(scrnSize.width, scrnSize.height));
        frame.setPreferredSize(new Dimension(scrnSize.width, scrnSize.height));
        frame.setMaximumSize(new Dimension(scrnSize.width, scrnSize.height));
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //game loop
        while(true){
            //do loop stuff here?
            main.repaint();
            Thread.sleep(10);
        }
    }

}

最佳答案

您需要知道的第一件事......

  1. 你无法控制绘制过程,所以不要搞砸它。绘画是由 RepaintManager 完成的,您可以向RepaintManager提出建议关于应该画什么,但这是 RepaintManager 的责任决定应该画什么以及什么时候画。
  2. Swing 不是一个线程安全的框架。也就是说,对 UI 的所有更新都必须在事件调度线程的上下文中完成...看看 Concurrency in Swing了解更多详情...
  3. Swing 中的绘画是一系列复杂的方法调用,它们链接在一起产生最终结果,不遵守此链将导致令人讨厌的绘画伪影...

所以,考虑到所有这些......

  1. 切勿在任何 paint 内执行任何操作可能需要时间执行的方法,这包括无限循环、加载资源或使用类似Thread.sleep之类的东西
  2. 如果必须更改 UI,请在事件调度线程的上下文中执行此操作
  3. 调用 super.paint或者更好的是,覆盖 paintComponent相反(并在进行任何自定义绘画之前调用 super.paintComponent)

而不是 Thread ,根据您的需求,考虑使用Swing Timer ,这将允许您安排将在上下文 EDT 内完成的定期回调。这将确保一定程度的同步,因为您对 UI 属性所做的任何更改都不能在任何绘制方法中使用(因为您的回调和绘制方法是从同一线程调用的),并有助于防止可能的脏绘制...

您可能还想看看Painting in AWT and SwingInitial ThreadsShould I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?欲了解更多信息...

关于Java - 游戏在绘制方法中循环还是在单独线程的 while 循环中循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25396134/

相关文章:

java - 2 人掷硬币

java - 为什么在排序数组的二分查找场景中仍然出现错误情况?

android - 应用查询服务器时需要显示加载屏幕

java - 尝试使用关键监听器,但形状不会移动

java - JButton 退出 JPanel

java - 为什么我们不能在java中通过charAt(index)在特定位置添加字符

java - Hibernate:如何建模双重父/子关系

java - 如何解决这个僵局呢?

c - C 中的 Go 风格 channel

Java GUI - 嵌套面板