2017-05-15 39 views
0

JPanelでJbuttonをクリックして図形を描くように練習していますが、できません。私がウェブをサーフィンしているのは5時間ありましたが、私はそれを行う方法を見つけることができません。 これは私がやりたいことです。「長方形」ボタンをクリックするとボタンの下に四角形が表示され、「円」ボタンをクリックすると円が表示されます。ActionListenerを使用してJPanelに図形を描画する方法は?

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

    class Shape extends JFrame { 
     JButton rec, circle; 
     static String botSelected; 
     Shape(){ 
      frameSet(); 
     } 

     void frameSet(){ 
      JFrame frame = new JFrame(); 
      frame.setVisible(true); 
      frame.setSize(600,300); 
      rec = new JButton ("Rectangle"); 
      circle = new JButton("Circle"); 
      JPanel panel = new JPanel(); 
      frame.add(panel); 
      panel.add(rec); 
      panel.add(circle); 
      Click clk = new Click(); 
      rec.addActionListener(clk); 
      circle.addActionListener(clk); 
     } 

     public void paint (Graphics g){ 
      super.paint(g); 
      if (botSelected.equals("Rectangle")) 
       g.fillRect(50,50,50,50); 
      else if (botSelected.equals("Circle")) 
       g.fillOval(50,50,50,50); 
     } 

     public static void main (String [] arg){ 
      Shape s = new Shape(); 
     } 
    } 

    class Click implements ActionListener{ 
     public void actionPerformed (ActionEvent e){ 
      Shape.botSelected = e.getActionCommand(); 
     } 
    } 
+0

変更が表示されるようにするには、repaintを呼び出す必要があります。このコードは非常に多くの悪い習慣で散らばっています。なぜあなたはJFrameを拡張していますか?あなたは 'Shape'クラスに名前をつけるべきではありません。なぜなら、awtのクラス、つまり' java.awt.Shape'です。 – matt

+0

最初に行うことは、[Painting in Swing](http:// www。 oracle.com/technetwork/java/painting-140037.html)と[カスタム・ペインティングの実行](https://docs.oracle.com/javase/tutorial/uiswing/painting/)を参照して、ペイント・プロセスの仕組みを理解してください。一般的な推奨として、私は '静的'を避けるだろう、それはクロスオブジェクトの通信のための解決策ではない – MadProgrammer

答えて

1

私はどうしたらまず最初に優れた塗装プロセスがどのように機能するかを理解するためにPainting in SwingPerforming custom painting一読を持っています。

次に、JFrameが絵画に悪い選択であることを理解する必要があります。どうして?それは多層的だからです。

RootPane

JFrameJLayeredPanecontentPaneglassPaneJMenuBarが含まれており、あなたの例では、それはまたJPanelを含む、JRootPaneが含まれています。

glassPaneの(デフォルト)例外を除いて、これらのコンポーネントはすべて不透明です。

paintの方法で描画されたものを表示することは可能ですが、他のコンポーネントのいずれかがペイントするときれいに拭き取られます。これはスイングコンポーネントが実際には互いに独立してペイントできるためです。最初に親塗料そのものを持っています。

より良い解決策は、JPanelから拡張し、そのpaintComponentメソッドをオーバーライドすることです。

簡単にするために、私もそれがコンポーネントのプロパティにアクセスするためのactionPerformed方法を許可すると、あなたのケースでは、ときペイントサイクルをトリガするrepaintを呼び出します、だけでなく、このクラスに対してActionListenerを実装することをお勧めしたいですUIを更新する必要があります。

+0

ありがとう。私はこのglassPaneについて知らなかった。私はそれについてもっと読むべきです。 –

1

コードの派生例を次に示します。

@MadProgrammerが言っているように、JFrameを拡張しないでください。

  • botSelectedにnull以外の値を与える、またはpaintComponentへの最初の呼び出しは、今、あなたにNullPointerException

  • クラスを提供します:次の例では

    、ここでの主な変更点は、 JPanelを拡張し、カスタムペイントのためにpaintComponentを上書きします。

  • ActionListenerは匿名クラスです。あなたが別のクラスを必要としない、それはもはや静的であるShape

  • botSelectedからフィールドへの直接アクセスを持っていない原因

(ポイント上記参照)。

import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

class Shape extends JPanel { 
    JButton rec, circle; 
    String botSelected = "";// don't let it be null, it would make paintComponent crash on startup 

    Shape() { 
     frameSet(); 
    } 

    void frameSet() { 
     JFrame frame = new JFrame(); 
     frame.setVisible(true); 
     frame.setSize(600, 300); 
     rec = new JButton("Rectangle"); 
     circle = new JButton("Circle"); 

     frame.add(this); 
     this.add(rec); 
     this.add(circle); 
     // anonymous class, has access to fields from the outer class Shape 
     ActionListener clk = new ActionListener() { 
      public void actionPerformed(final ActionEvent e) { 
       botSelected = e.getActionCommand(); 
       repaint(); 
      } 

     }; 
     rec.addActionListener(clk); 
     circle.addActionListener(clk); 
    } 

    //custom painting of the JPanel 
    @Override 
    public void paintComponent(final Graphics g) { 

     super.paintComponent(g); 
     if (botSelected.equals("Rectangle")) { 
      g.fillRect(50, 50, 50, 50); 
     } else if (botSelected.equals("Circle")) { 
      g.fillOval(50, 50, 50, 50); 
     } 
    } 

    public static void main(final String[] arg) { 
     Shape s = new Shape(); 
    } 

} 
+0

ありがとうございました。私は多くのことを学びました。 –

+0

JFrameの拡張がうまくいかず、Jpanelが機能する理由はまだ分かりません。ボタンを追加する方法は「これ」です。そして、なぜmainメソッドのfinal String?これらについてはどこでもっと読むことができますか? TNX –

+0

'JFrame'は独自のコンテンツ' JPanel'を持っています。 'JFrame'から' paint'をオーバーライドしようとすると何も役に立ちません。クラス自体が 'JPanel'なので、' this'は 'Shape' JPanel'それで、 'this.add ... 'で物事を簡単に追加することができます。 – Berger

関連する問題