从事件调度线程中分离逻辑线程 [英] Separate Logic Thread From Event Dispatch Thread

查看:186
本文介绍了从事件调度线程中分离逻辑线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我项目中最小的可运行的SSCCE ,我可以实现这一点。

This is the smallest runnable SSCCE,of my project, that I could implement to show you.


  • 我读过从Event Dispacth Thread调用游戏逻辑是一种不好的做法,我怎么能把它们分开呢,因为你可以看到 update() repaint()与循环相关
    我该怎么办?以一种漂亮的方式分开代码,我遇到了麻烦,试图找出如何做到这一点。

  • I've read that calling the game logic from the Event Dispacth Thread is a bad practice, how can I separate them, because as you can see update() and repaint() are related into loop and how can I separate code in a pretty way, I'm getting in trouble with this, trying to find out how to do it.

我发布了一个类似的问题关于和我得到了一个答案,即使用 Swing Timer ,但我有很大的任务要做,因为我读 Swing计时器对于这种情况并不理想。这就是问题:

I've posted a similar question regarding and I got an answer,that says to use a Swing Timer,but i have huge task to make and as i read Swing timer isn't ideal for this scenario.This is the question:

  • Event Dispatch Thread divided from logic thread,prevent blocking UI

主要课程

Main class

    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;

    public class Main {

        private static final Main mainFrame = new Main();
        private final JFrame frame;

        private Main() {
        frame = new JFrame();
        frame.setUndecorated(true);
        frame.add(new MyPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        }

        public static Main getMainFrameInstance() {
        return mainFrame;
        }


        public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
            Main.getMainFrameInstance();
            }
        });
        }

    }

MyPanel Class

MyPanel Class

        import java.awt.Dimension;
        import java.awt.Graphics;
        import java.awt.Graphics2D;
        import java.awt.RenderingHints;
        import java.awt.image.BufferedImage;

        import javax.swing.JPanel;

        public class MyPanel extends JPanel implements Runnable,KeyListener,MouseListeners {

            private static final long serialVersionUID = 1L;

            // thread and loop
            private Thread thread;
            private boolean running;
            private int FPS = 60;
            private long targetTime = 1000 / FPS;
            private long start;
            private long elapsed;
            private long wait;

            // image
            public BufferedImage image;
            // foo
            private Foo foo;

            private Render render = Render.getRenderManagerInstance();

            public MyPanel() {
            setPreferredSize(new Dimension(700, 700));
            setFocusable(true);
            requestFocus();
            }

            public void addNotify() {
            super.addNotify();
            if (thread == null) {
                    addKeyListeners(this);
                    addMouseListener(this);
                thread = new Thread(this);
                thread.start();
            }
            }


            private  void initGraphic() {
            image = new BufferedImage(700, 700, BufferedImage.TYPE_INT_RGB);
            foo = new Foo();
            running = true;

            }

            public void run() {
            initGraphic();

            // loop
            while (running) {
                start = System.nanoTime();
                foo.update();
                repaint();
                elapsed = System.nanoTime() - start;
                wait = (targetTime - elapsed / 1000000) - 8;
                if (wait <= 0)
                wait = 6;

                try {
                Thread.sleep(wait);
                } catch (Exception e) {
                e.printStackTrace();
                }

            }
            }

           public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        graphics = image.getGraphics();
        ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        render.setRenderState((Graphics2D) graphics);
        graphic.drawImage(image, 0, 0, this);
    // clear graphics resources after use them
    graphic2D.dispose();

      }
         public void keyPressed(KeyEvent keyEvent) {
                   //code not considerable
          }

          public void keyReleased(KeyEvent keyEvent) {
                       //code not considerable

            }

            public void mousePressed(MouseEvent mouseEvent) {
                       //code not considerable

            }

            public void mouseReleased(MouseEvent mouseEvent) {
                      //code not considerable
            }

    }


推荐答案

这就是它的样子。您需要在EDT或Swing Timer中的某处调用以下代码。我在这里假设您的巨大任务需要更新文本字段,但它也可以是任何其他UI控件。所有这些,只是为了展示一个想法。不要将其视为经过测试的代码。

This is how it can look like. You'll need to call the following code somewhere in EDT or through Swing Timer. I'm assuming here that your "huge" task will need to update a text field, but it can be any other UI control as well. All of that, just to demonstrate an idea. Do not treat it as a tested code.

//javax.swing.JTextField jfield; The field that needs to be updated. Take it from your Panel
String text = ""; // just a place holder
Object params [] = new Object []{jfield, text}; 
HugeTaskRunner ht = new HugeTaskRunner(params, new CallBack());

HugeTaskRunner派生自AbstractTaskRunner,如下所示:

HugeTaskRunner is derived from AbstractTaskRunner, which looks like follows:

public abstract class AbstractTaskRunner extends Thread {


CallBack callBack = null;
Object [] params = new Object[0];

public AbstractTaskRunner (Object [] params, CallBack callBack) {
    this.params = params;
    this.callBack = callBack;

}
public abstract void doTask ();
@Override
public void run() {
    doTask();
    if (callBack != null) {
        callBack.doCall(new Object[]{"DONE"});
    }
}

}

HugeTaskRunner:

HugeTaskRunner:

public class HugeTaskRunner extends AbstractTaskRunner {

public HugeTaskRunner(Object[] params, CallBack callBack) {
    super(params, callBack);
    // TODO Auto-generated constructor stub
}

@Override
public void doTask() {
    // HERE YOU'LL HAVE TO DO SOME HUGE TASK ACTIONS
    // THEN YOU'LL NEED TO CALL callBack.doCall(params) to update GUI 
    String newText = "Image #1 has been loaded";
    params[params.length -1] = newText; // assuming that the last param is for updated text
    callBack.doCall(params);

}

}

CallBack类:

CallBack class:

public class CallBack {
public void doCall (Object [] params) {
    javax.swing.SwingUtilities.invokeLater(new GUIUpdater(params, null));
}
}

GUIUpdater类:

GUIUpdater class:

public class GUIUpdater extends AbstractTaskRunner {

public GUIUpdater(Object[] params, CallBack callBack) {
    super(params, callBack);
}

@Override
public void doTask() {
    // UPDATE YOUR GUI HERE TAKING Swing UI objects from params, e.g.
    if (params.length == 1 && params[0].equals("DONE")) {
        // HUGE TASK IS COMPLETED, DO SOMETHING IF YOU NEED TO
    }
    else if (params.length == 2) { // It's a request to update GUI
        javax.swing.JTextField txt = (javax.swing.JTextField) this.params[0];
        txt.setText((String)this.params[1]);
    }
    else {
        // UNKNOWN REQUEST
    }

}

}

这篇关于从事件调度线程中分离逻辑线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆