2016-10-13 4 views
0

У меня есть небольшой движок, который хорошо работает на моем ноутбуке OSX, но работает с ошибками или сильно задерживается при работе на менее мощном Linux-ПК. Я свести к минимуму код в том месте, где он всего лишь один маленький класс, но такая же лаги. Я думаю, что это имеет какое-то отношение к стратегии буфера и потокам. Вот этот класс:Стратегия Java Buffer вызывает серьезное отставание

public class Test extends Canvas implements Runnable { 

    private Thread thread; 
    private boolean running = false; 

    public Test() 
    { 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(new Dimension(1000, 1000)); 
     frame.add(this); 
     frame.setVisible(true); 
     start(); 
    } 

    public static void main(String[] args) 
    { 
     new Test(); 
    } 

    public synchronized void start() 
    { 
     this.thread = new Thread(this); 
     this.thread.start(); 
     this.running = true; 
    } 

    public synchronized void stop() 
    { 
     try 
     { 
      this.thread.join(); 
      this.running = false; 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    public void run() 
    { 
     while(running) 
     { 
      render(); 
     } 
    } 

    private void render() 
    { 
     BufferStrategy bs = this.getBufferStrategy(); 
     if(bs == null) 
     { 
      this.createBufferStrategy(2); 
      return; 
     } 

     Graphics g = bs.getDrawGraphics(); 
     g.setColor(Color.black); 
     g.fillRect(0, 0, 1000, 1000); 
     g.dispose(); 
     bs.show(); 
    } 
} 
+0

Для тех, кто читает это, не стоит смешивать легкие весовые и тяжеловесные компоненты AWT. Если вы хотите нарисовать приложение Swing, используйте JPanel. –

+0

Было бы целесообразно использовать AWT над Swing при создании 2D-игры? – Bun

+0

Нет. См. Мой ответ для примера графического приложения с использованием Swing. –

ответ

2

Я видел задержку, прежде чем холст был окрашен в черный цвет. Перед тем, как установить JFrame, вы должны нарисовать что-нибудь на холсте.

Вот изменения, которые я внес в ваш код.

  1. Я использовал JPanel вместо холста. Я получаю автоматическую двойную буферизацию с помощью JPanel.

  2. Я начал приложение Swing с вызова метода SwingUtilities invokeLater. Это ставит создание и выполнение компонентов Swing на Event Dispatch thread. Oracle и я настаиваем на том, что все приложения Swing начинаются именно так. Позже в этом объяснении вы увидите, почему это важно.

  3. Я рисую белое изображение, а затем черное изображение каждые 250 миллисекунд. Таким образом, я уверен, что код картины работает.

  4. Я переместил код потока в свой класс. У меня возникла проблема, когда в потоке использовался поток boolean и JPanel. Поместив поток в свой класс, я смог создать отдельные булевы для потока и JPanel.

  5. В методе JPanel paintComponent я нарисовал что-то перед тем, как установить JFrame на вид.

  6. Я установил предпочтительный размер JPanel, а не размер JFrame. Во всяком случае, я хочу знать размер панели чертежа.

  7. В коде потока вызов метода на чертеж JPanel помещается внутри метода SwingUtilities invokeLater. Это гарантирует, что картина происходит в потоке Dispatch Event, в то время как цикл синхронизации выполняется в другом потоке. Это гарантирует, что графический интерфейс останется отзывчивым.

Вот код.

package com.ggl.testing; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class DrawingTest extends JPanel { 
    private static final long serialVersionUID = 2584117430541789858L; 

    private DrawingTestRunnable drawingTestRunnable; 

    private boolean isWhite; 

    public DrawingTest() { 
     this.setPreferredSize(new Dimension(1200, 700)); 
     this.isWhite = true; 

     JFrame frame = new JFrame("Drawing Test"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(this); 
     frame.pack(); 
     frame.setVisible(true); 
     start(); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new DrawingTest(); 
      } 
     }); 
    } 

    public synchronized void start() { 
     drawingTestRunnable = new DrawingTestRunnable(this); 
     new Thread(drawingTestRunnable).start(); 
    } 

    public boolean isWhite() { 
     return isWhite; 
    } 

    public void setWhite(boolean isWhite) { 
     this.isWhite = isWhite; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     if (isWhite) { 
      g.setColor(Color.WHITE); 
     } else { 
      g.setColor(Color.BLACK); 
     } 

     g.fillRect(0, 0, this.getWidth(), this.getHeight()); 
     g.dispose(); 
    } 

    public class DrawingTestRunnable implements Runnable { 
     private boolean isWhite; 
     private volatile boolean running; 

     private DrawingTest drawingTest; 

     public DrawingTestRunnable(DrawingTest drawingTest) { 
      this.drawingTest = drawingTest; 
      this.running = true; 
     } 

     @Override 
     public void run() { 
      long duration = 250L; 
      long startTime = System.currentTimeMillis(); 
      while (running) { 
       repaintPanel(); 
       long elapsedTime = System.currentTimeMillis() - startTime; 
       long loopDuration = Math.max((duration - elapsedTime), 5L); 
       sleep(loopDuration); 
       startTime = System.currentTimeMillis(); 
      } 
     } 

     private void repaintPanel() { 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        drawingTest.repaint(); 
        isWhite = !isWhite; 
        drawingTest.setWhite(isWhite); 
       } 
      }); 
     } 

     private void sleep(long duration) { 
      try { 
       Thread.sleep(duration); 
      } catch (InterruptedException e) { 

      } 
     } 

     public synchronized void setRunning(boolean running) { 
      this.running = running; 
     } 

    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^