2017-01-07 8 views
0

フレームの端に触れるたびにバウンスする四角形を含むアプリを作成しました。アプリをランチするときに問題はありません。問題はさまざまなスレッドを作成する方法がわからないことですフレーム内の複数の正方形。 私は複数のものを試しましたが、私はスレッドを作成する必要があるのか​​分かりません。 私は、正方形がフレーム内に直接追加されたときにのみ表示され、JPanelの内部に配置したときは表示されないことにも気付きました。paintComponent()でマルチスレッドする方法は?

Square.java

public class Square extends JComponent implements ActionListener { 

    int width = 20; 
    int height = 20; 
    double y = Math.random() * 360; 
    double x = Math.random() * 360; 
    boolean xMax = false; 
    boolean yMax = false; 
    boolean xMin = true; 
    boolean yMin = true; 
    Rectangle2D.Double square = new Rectangle2D.Double(x, y, width, height); 

    public Square() { 
    Timer t = new Timer(2, this); 
    t.start(); 
    } 

    public void paintComponent(Graphics g) { 
    Graphics2D g2 = (Graphics2D) g; 
    super.paintComponent(g); 
    g2.setColor(Color.BLUE); 
    g2.fill(square); 

    x_y_rules(); 


    } 
    public void x_y_rules() { 
    if (xMax == true) { 
     x = x - 0.5; 
     if (x <= 0) { 
      xMax = false; 
     } 
    } else { 
     x = x + 0.5; 
     if (x >= this.getWidth()) { 
      xMax = true; 
     } 
    } 
    if (yMax == true) { 
     y = y - 0.5; 
     if (y <= 0) { 
      yMax = false; 
     } 
    } else { 
     y = y + 0.5; 
     if (y >= this.getHeight()) { 
      yMax = true; 
     } 
    } 
    square.setFrame(x, y, width, height); 
    } 

@Override 
public void actionPerformed(ActionEvent arg0) { 
    repaint(); 
} 
} 

App.java

public class App extends JFrame { 

public static void main(String[] args) { 
    JFrame jf = new JFrame(); 
    Square sqr = new Square(); 
    jf.setSize(400, 400); 
    jf.setVisible(true); 
    jf.add(sqr); 
    jf.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    jf.setLocationRelativeTo(null); 
} 
} 

それは私がタイマー内の2の時間をかけたにもかかわらず、広場は非常にゆっくりと移動していること正常ですか?

+0

がActionListener.The問題内側x_y_rulesを置く()メソッドは次の場合には、別の正方形を作成することであると私はフレームに追加you.Iありがとうございました後者は1つの正方形しか表示しません。そのため、私はスレッドを使うべきだと思ったのです。 – TomCa

+0

レイアウトマネージャの問題を解決するためにスレッディングを使用しないので、レイアウトマネージャを調べたいと思うでしょう。 JFrame contentPaneはBorderLayoutを使用し、デフォルトでコンポーネントをJFrameに追加すると、最後に追加されたコンポーネントだけが表示されます。 –

答えて

2

問題:

  1. あなたはpaintComponentメソッドの内部で、プログラムロジック、x_y_rules()メソッド呼び出しを持っています。それがそこに属さないのでそれを取り出し、代わりにそれが属するTimerのActionListenerコードに入れます。
  2. 必要に応じて、各スクエアに独自のスイングタイマーを付けることができます。各タイマーのActionListenerはEDT上で実行されるため、これは実際にスレッドの問題ではありません。
  3. 2ミリ秒は、スイングタイマーで使用すると予想される非現実的なタイムスライスであり、タイマーはその速さで実行されません。 11時から13時までは、期待しているか、望むのが最速です。
  4. スプライトの移動を速くしたい場合は、移動コードのdelta-xとdelta-yの値を大きくします。
  5. JComponentには、JPanelで表示されない理由が定義されていないため、デフォルトのFlowLayoutは[0、0]にサイズを設定します。 getPreferredSize()をオーバーライドし、適切な次元値を返します。
  6. すべてのコンポーネントを追加する前に、JFrameでsetVisible(true)と呼んでいます。

[OK]を、私は正方形のクラス内)getPrefferedSizeを(置くが、私は、問題が発生しました:正方形は、「一緒に」ではありません、彼らは別のパネル

にバウンドしているみたいです

あなたのプログラム構造が壊れています。別のSwingコンポーネントを作成することは本当に望ましくありません。実際、SquareクラスはJComponentまたはJPanelを拡張するべきではありません。むしろ

  • スクエアは論理クラス、(デフォルトのオブジェクト以外の)何もないから延びているものでなければなりません。
  • それに描画方法を与える、public void draw(Graphics g) {....}
  • は、JPanelのを拡張する1つのクラスを作成しますDrawingPanel呼ば言うと、そのpaintComponentメソッドをオーバーライドすると言います。
  • DrawingPanelクラスに複数のSquareオブジェクトを保持できるように、ArrayList<Square>を与えます。
  • 、DrawingPanelクラスのタイマーでDrawingPanelクラスにスイングタイマー
  • を与えることがArrayListの中ですべての正方形の位置を更新し、paintComponentメソッドでrepaint()
  • を呼び出す必要があり、中にすべての正方形を反復処理リストをforループを使用して呼び出し、それぞれのdrawメソッドを呼び出します。たとえば、

enter image description here

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class DrawingPanel extends JPanel { 
    private static final int PREF_W = 600; 
    private static final int PREF_H = PREF_W; 
    private static final int TIMER_DELAY = 20; 
    private static final Color[] SQUARE_COLOR = { Color.BLUE, Color.CYAN, Color.DARK_GRAY, 
      Color.BLACK, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, 
      Color.PINK, Color.RED, Color.YELLOW }; 
    List<Square> squareList = new ArrayList<>(); 

    public DrawingPanel() { 
     // create a bunch of squares 
     for (int i = 0; i < SQUARE_COLOR.length; i++) { 
      squareList.add(new Square(SQUARE_COLOR[i], PREF_W, PREF_H)); 
     } 

     setBackground(Color.WHITE); 

     // create and start the timer 
     new Timer(TIMER_DELAY, new TimerListener()).start(); 
    } 

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

     // simply draw all the squares in the list 
     for (Square square : squareList) { 
      square.draw(g); 
     } 
    } 

    // set size of JPanel 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) {    
      // simply iterate through list and move all squares 
      for (Square square : squareList) { 
       square.move(); 
      } 
      repaint(); // then repaint the GUI 
     } 
    } 

    private static void createAndShowGui() { 
     DrawingPanel mainPanel = new DrawingPanel(); 

     JFrame frame = new JFrame("Drawing Panel"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

// this class does *not* extend JPanel or JComponent 
class Square { 
    public static final int WIDTH = 20; 

    // location of Square 
    private double sqrX; 
    private double sqrY; 

    // X and Y speed 
    private double deltaX; 
    private double deltaY; 

    // width and height of DrawingPanel JPanel 
    private int dpWidth; 
    private int dpHeight; 

    // image to draw 
    private Image image; 

    public Square(Color color, int dpWidth, int dpHeight) { 
     this.dpWidth = dpWidth; 
     this.dpHeight = dpHeight; 

     // create square at random location with random speed 
     sqrX = Math.random() * (dpWidth - WIDTH); 
     sqrY = Math.random() * (dpHeight - WIDTH); 
     deltaX = Math.random() * 10 - 5; 
     deltaY = Math.random() * 10 - 5; 

     // one way to draw it is to create an image and draw it 
     image = new BufferedImage(WIDTH, WIDTH, BufferedImage.TYPE_INT_ARGB); 
     Graphics g = image.getGraphics(); 
     g.setColor(color); 
     g.fillRect(0, 0, WIDTH, WIDTH); 
     g.dispose(); 
    } 

    public void move() { 

     // check that we're not hitting boundaries 
     if (sqrX + deltaX < 0) { 
      deltaX = Math.abs(deltaX); 
     } 
     if (sqrX + deltaX + WIDTH >= dpWidth) { 
      deltaX = -Math.abs(deltaX); 
     } 
     sqrX += deltaX; 

     // check that we're not hitting boundaries 
     if (sqrY + deltaY < 0) { 
      deltaY = Math.abs(deltaY); 
     } 
     if (sqrY + deltaY + WIDTH >= dpHeight) { 
      deltaY = -Math.abs(deltaY); 
     } 
     sqrY += deltaY; 

    } 

    public void draw(Graphics g) { 
     int x = (int) sqrX; 
     int y = (int) sqrY; 
     g.drawImage(image, x, y, null); 
    } 
} 
+0

5.私は正方形クラス内にgetPrefferedSize()を入れましたが、問題が発生しました。四角形は「一緒に」ではなく、別々のパネルでバウンスしているようです。 – TomCa

+0

@TomCa:答えを編集してください –

+0

うわー、ありがとうございます!私はあなたのコードを慎重に研究します。あなたが書いたものは分かりませんが、私は何かを学ばなければなりません。 – TomCa

関連する問題