2017-02-22 5 views
-1

矩形が画面の右側(画面の右端の右側)から開始し、左側に移動する単純なアニメーションを作成しようとしています。したがって、この場合、フレームの幅は1000になり、壁は1100のx値から始まります。最初は、長方形は であるはずです。しかし、長方形が左に移動すると、最終的に見えるようになります。しかし、このアニメーションはそれをしません。ウォールのx値が画面の境界内にある場合でも、レンダリングされません。JComponentがスクリーンから外れてレンダリングを停止する

私は壁のpaintComponent()方法でprintln()文を入れてみました、と私はpaintComponent()は、フレームのrepaint()メソッドによって呼び出さなっていなかったことを発見しました。私は、壁が最初にフレームに追加されたときに、スイングは画面外だったのでレンダリングする必要はないと判断し、壁が最終的に画面に表示されても、スイングはそれが必要ではないと考えましたレンダリングする。

フレームとコンポーネントの再検証と無効化を試みましたが、何も効果がありませんでした。これを解決するために私を助けてください。以下のコードです:

package graphics.simpleAnimation; 

public class Simple_Animation implements Runnable { 

    private UI ui; // The UI (frame) 

    private Wall wall; // Wall object that moves across the screen 

    private Simple_Animation() { 

     // Initialize the wall object (intentionally given an x value that is greater than the frame's width) 
     wall = new Wall(1100, 400, 200, 400); 

     // Initialize the UI (width is only 1000) 
     ui = new UI(1000, 600, "Geometry Dash"); 

     // Add the wall to the ui (the frame) 
     ui.add(wall); 

    } 

    public void run() { 
     // Set the frame visible 
     ui.setVisible(true); 

     // Repaint the frame and move the wall 
     while (true) { 
      ui.repaint(); 
      wall.moveWall(-2, 0); 

      try { 
       Thread.sleep(16); 
      } catch (InterruptedException IE) { 
       System.out.println(IE); 
      } 

     } 

    } 

    // Starts the program in a new thread 
    public static void main(String[] args) { 
     Simple_Animation simpleAnimation = new Simple_Animation(); 
     new Thread(simpleAnimation).start(); 
    } 

} 


package graphics.simpleAnimation; 

import javax.swing.*; 
import java.awt.*; 

public class UI extends JFrame { 

    // Variables storing the width and height of the content pane (where the components are being rendered) 
    public int content_pane_width; 
    public int content_pane_height; 

    public UI(int frameW, int frameH, String frameTitle) { 

     setTitle(frameTitle); 
     setSize(frameW, frameH); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     setLayout(null); 

     content_pane_width = getContentPane().getWidth(); 
     content_pane_height = getContentPane().getHeight(); 

    } 

    @Override 
    public void paint(Graphics g) { 
     super.paint(g); 
    } 

} 

package graphics.simpleAnimation; 

import java.awt.*; 
import javax.swing.*; 

public class Wall extends JComponent { 

    private int wallX; 
    private int wallY; 
    private int wallW; 
    private int wallH; 


    Wall(int x, int y, int sizeX, int sizeY) { 
     wallX = x; 
     wallY = y; 
     wallW = sizeX; 
     wallH = sizeY; 

     setSize(getPreferredSize()); 
    } 

    public void moveWall(int moveX, int moveY) { 
     wallX += moveX; 
     wallY += moveY; 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(wallW, wallH); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     Graphics2D g2d = (Graphics2D) g; 

     setLocation(wallX, wallY); 
     g2d.fillRect(0, 0, wallW, wallH); 
    } 
} 
+1

ペイントメソッド内で 'setLocation(wallX、wallY);'を実行しないでください。ペイントは現在の状態をペイントして決して変更しないでください。また、自分のプロパティをコンポーネントのプロパティと混在させているので、自分でコンポーネントを配置/サイズ変更しようとしているので、単にコンポーネントの既存のプロパティを使用することをお勧めします。また、 'getPreferredSize'は' null'レイアウトを使用しているときには何もしません。おそらく問題の一部を説明しています。 – MadProgrammer

+0

[コードブロックのぶら下げ括弧の検出/修正](http:// meta .stackexchange.com/q/251795/155831)私はもはや気にすることができなかった問題を解決する。 –

答えて

3

私はあなたのプログラムに

  1. あなたが使用していることを見つけることができます null layoutの場合は、 Null layout is evilと答えを this questionに表示して、その使用を避ける理由を確認してください。 (おそらく、この場合には、以下の@ MadProgrammerさんのコメントどおりではない)、これは単なる別のアプローチである

  2. while (true) {このラインこのラインとともにEvent Dispatch Thread (EDT)をブロックする可能性があります:詳細とHow to use Swing Timersを学ぶためにLesson: Concurrency in Swingを参照してください、Thread.sleep(16);。あなたも行うことができEDT上でプログラムを置く必要があります:あなたは、塗料のチェーンを破ることができWallクラスのごpaintComponent()方法にsuper.paintComponent()を呼び出していない

    public static void main(String[] args) { 
        SwingUtilities.invokeLater(new Runnable() { 
         @Override 
         public void run() { 
          //Your constructor here 
         } 
        }); 
    } 
    
  3. 、常に最初にそれを呼び出します。あなたはJComponentを拡張している

  4. 、それはJPanelを拡張し、心の中で上記のすべてとShapeのAPI

を使用してその上にカスタムペイントを行う方が良いでしょう、あなたは、コードを持つことができます

このような類似した出力を生成します
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.Rectangle2D; 

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

public class SingleAnimation { 

    private JFrame frame; 
    private Timer timer; 

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

    public void createAndShowGui() { 
     frame = new JFrame(getClass().getSimpleName()); 

     Wall wall = new Wall(300, 0); 

     timer = new Timer(16, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       wall.moveWall(-2, 0); 
      } 
     }); 

     timer.setInitialDelay(0); 
     timer.start(); 

     frame.add(wall); 
     frame.pack(); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 
} 

class Wall extends JPanel { 
    private int xCoord; 
    private int yCoord; 

    public int getxCoord() { 
     return xCoord; 
    } 

    public void setxCoord(int xCoord) { 
     this.xCoord = xCoord; 
    } 

    public int getyCoord() { 
     return yCoord; 
    } 

    public void setyCoord(int yCoord) { 
     this.yCoord = yCoord; 
    } 

    public Wall(int x, int y) { 
     this.xCoord = x; 
     this.yCoord = y; 
    } 

    public void moveWall(int xUnits, int yUnits) { 
     xCoord += xUnits; 
     yCoord += yUnits; 
     repaint(); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(400, 400); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setColor(Color.BLUE); 

     g2d.fill(new Rectangle2D.Double(xCoord, yCoord, 100, 20)); 
    } 
} 

このような

+0

あなたの例では議論はありませんが、正しいアプローチを決めるために質問に文脈が必要です。ヌルレイアウトを使用している場合は、Nullレイアウトが悪いのを見て、この質問の答えを使用して避けるべき理由を見てください。」*問題の単純化されたものであり、 'nullが必要だと思う時間の99% 'layout、あなたはそうではありませんが、(コンポーネントベースのアニメーションを実行するような)有用であると何度も考えることができます。' null'レイアウトは、正しく使用されたときに使用できるツールですが、ほとんどの人は間違ったやり方で、間違った時に;) – MadProgrammer

+0

@MadProgrammerはあなたのフィードバックのおかげで、私はすでにあなたの例を見て、それは素晴らしい作品、私は今日あなたのコメントのおかげで何か新しいことを学んだ。私は、 'null layout'が有用な例をもっと見る必要があります。(GUIにコンポーネントを置くのではなく、このようなものを置くのではなく):) – Frakcool

+0

私は間違っていません。あなたが気をつけなければ、あなたは家を燃やすでしょう;)ところで良い例;) – MadProgrammer

2
  • paintメソッド内setLocation(wallX, wallY);をしないが、絵はそれを変更することはありません、現在の状態をペイントする必要があります。
  • また、独自のプロパティをコンポーネントのプロパティと混在させているので、コンポーネント自体を配置/サイズ変更しようとしているので、コンポーネントの既存のプロパティを使用することをお勧めします。あなたがコンポーネントがスイングはスレッドセーフではないので、使用することが賢明だろう0x0
  • のデフォルトサイズを想定しているとして、おそらくあなたの問題の一部を説明しnullレイアウトを、使用しているとき
  • getPreferredSizeは何もしませんあなたの「メインループ」の代わりに、Thread

として機能するようにスイングTimer私はカスタムペイントに直行する代わりに好む、目的のこの種の「コンポーネントベースのアニメーション」のファンではないんだけど、それは私です

しかし、ifあなたは、あなたがしようとするとあなたに利用できるAPI機能を利用する必要がありますする必要が

エラーのカップルがあります
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

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

    public Test() { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame("Test"); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private WallPane wallPane; 

     public TestPane() { 
      setLayout(null); // :(
      wallPane = new WallPane(); 
      wallPane.setLocation(-100, 150); 
      add(wallPane); 

      Timer timer = new Timer(16, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        wallPane.moveBy(2, 0); 
        repaint(); 
       } 
      }); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(400, 400);    
     } 

    } 

    public class WallPane extends JPanel { 
     public WallPane() { 
      setSize(100, 100); 
      setBackground(Color.RED); 
     } 

     public void moveBy(int xDelta, int yDelta) { 
      int x = getX() + xDelta; 
      int y = getY() + yDelta; 
      setLocation(x, y); 
     } 
    } 
} 
+0

質問は下降しておらず、新しい票が追加されていないので、質問に間違いはないと思います。どんな方法でそれは質問に答えることができないのですか?どのように改善できるか?新しい答えが提供されていないので、あなたは問題の解決方法を理解していないと思います。他の回答は投票されていないので、あなたに私の個人的な問題があると仮定することができます。 – MadProgrammer

関連する問題