2013-03-21 4 views
51

これは非常に問題になるかもしれません。私はちょうどJavaを学び始めていますpaintComponentはどのように機能しますか?

私はpaintComponentメソッドの動作を理解していません。私が何かを描きたいのであれば、私はpaintComponentメソッドをオーバーライドする必要があります。

public void paintComponent(Graphics g) 
{ 
    ... 
} 

いつ呼び出されますか?私は "object.paintComponent(g)"のようなものは見かけることはありませんが、プログラムが実行されているときに描画されます。

Graphicsパラメータは何ですか?これ、どこから来たの?メソッドの呼び出し時にパラメータを指定する必要があります。しかし、私が以前に言ったように、このメソッドが明示的に呼び出されることはないようです。誰がこのパラメータを提供しますか?なぜGraphics2Dにキャストする必要がありますか? GUIシステムの

public void paintComponent(Graphics g) 
{ 
    ... 
    Graphics2D g2= (Graphics2D) g; 
    ... 
} 
+6

[* AWTとSwingのペイント](http://www.oracle.com/technetwork/java/painting-140037.html)から始めます。いつもに見て:また、[スイングタグウィキ](http://stackoverflow.com/tags/swing/info):-)で、または他の言葉で参照されている - – trashgod

+2

@trashgodは常に具体的なリンクを投稿することがとても親切ですwiki first ... – kleopatra

+0

@kleopatra:+1また、次の(避けられない)リンク消滅で修正するのが簡単です。 – trashgod

答えて

29

あなたの質問に(非常に)短い答えはpaintComponentが呼び出されるということです「それがために必要がある場合。」時には、Java Swing GUIシステムを、多くの内部構造があまり視認されずに処理される「ブラックボックス」と考える方が簡単な場合もあります。

コンポーネントを再描画する必要があるときは、移動、サイズ変更、フォーカスの変更、他のフレームの隠蔽などのさまざまな要因があります。これらのイベントの多くは自動的に検出され、その操作が必要であると判断された場合はpaintComponentが内部的に呼び出されます。

私は何年もスウィングに取り組んできましたが、と直接呼ばれているとは思っていません。私が来ている最も近い私は、下流の通話正しいpaintComponent方法を想定している(プログラムで特定のコンポーネントの再描画をトリガするrepaint()メソッドを使用している。私の経験で

paintComponentはめったに直接上書きされません。私は、カスタムがあることを認めますそのような粒度を必要とするレンダリングタスクがありますが、Java Swingでは、かなり複雑なJComponentsとLayoutsのセットを提供していますので、paintComponentを直接オーバーライドしなくても大量の作業を実行できます。独自のカスタムレンダリングコンポーネントを展開しようとしてオフに行く前に、あなたはネイティブJComponentのとレイアウトで何かを行うことはできません。

+0

それを捕まえてくれてありがとう@GuillaumePolet。私の用語は、あなたが述べたと同じように、そこに技術的に間違っていました。私は明確にするために投稿を編集しました。 – SeKa

+0

SeKa、何年もスイングで仕事をしてきたので、質問すればスイング/ javafxは学生/求職者から学ぶ価値があると思いますか? swing/javafxはたくさん使われていますか?ご意見ありがとうございました。 – Thor

3

内部には、そのメソッドを呼び出すと、彼らはあなたが描くことができ、その上にグラフィックスコンテキストとしてGraphicsパラメータを渡します。あなたがここに行うことができます

+0

ありがとう、いつそのメソッドが呼び出されますか? –

+1

@ nubhihi219は関係ありません:-)あなたは絵がいつ起こっているのかについては何もしていません_internals_は...まあ...非常にまれなコーナーケースを除いて、アプリケーションの開発には何も納得していません – kleopatra

10

2つのこと:

  1. 読むPainting in AWT and Swing
  2. デバッガを使用し、paintComponentメソッドにブレークポイントを置きます。次に、スタックトレースに移動して、Graphicsパラメータがどのように提供されるかを確認します。

だけの情報のため、ここで私は私が最後に掲載のコードの例から得たスタックトレースは次のとおりです。

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 15 in TestPaint)) 
    TestPaint.paintComponent(Graphics) line: 15 
    TestPaint(JComponent).paint(Graphics) line: 1054  
    JPanel(JComponent).paintChildren(Graphics) line: 887  
    JPanel(JComponent).paint(Graphics) line: 1063 
    JLayeredPane(JComponent).paintChildren(Graphics) line: 887 
    JLayeredPane(JComponent).paint(Graphics) line: 1063 
    JLayeredPane.paint(Graphics) line: 585 
    JRootPane(JComponent).paintChildren(Graphics) line: 887 
    JRootPane(JComponent).paintToOffscreen(Graphics, int, int, int, int, int, int) line: 5228 
    RepaintManager$PaintManager.paintDoubleBuffered(JComponent, Image, Graphics, int, int, int, int) line: 1482 
    RepaintManager$PaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1413 
    RepaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1206 
    JRootPane(JComponent).paint(Graphics) line: 1040  
    GraphicsCallback$PaintCallback.run(Component, Graphics) line: 39  
    GraphicsCallback$PaintCallback(SunGraphicsCallback).runOneComponent(Component, Rectangle, Graphics, Shape, int) line: 78  
    GraphicsCallback$PaintCallback(SunGraphicsCallback).runComponents(Component[], Graphics, int) line: 115 
    JFrame(Container).paint(Graphics) line: 1967  
    JFrame(Window).paint(Graphics) line: 3867 
    RepaintManager.paintDirtyRegions(Map<Component,Rectangle>) line: 781  
    RepaintManager.paintDirtyRegions() line: 728  
    RepaintManager.prePaintDirtyRegions() line: 677 
    RepaintManager.access$700(RepaintManager) line: 59 
    RepaintManager$ProcessingRunnable.run() line: 1621 
    InvocationEvent.dispatch() line: 251  
    EventQueue.dispatchEventImpl(AWTEvent, Object) line: 705  
    EventQueue.access$000(EventQueue, AWTEvent, Object) line: 101 
    EventQueue$3.run() line: 666  
    EventQueue$3.run() line: 664  
    AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]  
    ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 76  
    EventQueue.dispatchEvent(AWTEvent) line: 675  
    EventDispatchThread.pumpOneEventForFilters(int) line: 211 
    EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 128  
    EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 117 
    EventDispatchThread.pumpEvents(int, Conditional) line: 113 
    EventDispatchThread.pumpEvents(Conditional) line: 105 
    EventDispatchThread.run() line: 90 

グラフィックスパラメータは、ここから来ている:

RepaintManager.paintDirtyRegions(Map) line: 781 

含まれるスニペットは次のとおりです。

Graphics g = JComponent.safelyGetGraphics(
         dirtyComponent, dirtyComponent); 
       // If the Graphics goes away, it means someone disposed of 
       // the window, don't do anything. 
       if (g != null) { 
        g.setClip(rect.x, rect.y, rect.width, rect.height); 
        try { 
         dirtyComponent.paint(g); // This will eventually call paintComponent() 
        } finally { 
         g.dispose(); 
        } 
       } 

JComponent自体(間接的にはjavax.swing.JComponent.safelyGetGraphics(Component, Component))のグラフィックスを取得し、それは最終的に、対応するネイティブリソースから自分自身を取り出す最初の "ヘビー級親"(コンポーネント境界にクリップされたもの)から取得します。あなたはGraphics2DGraphicsをキャストする必要があるという事実に関しては、それだけでウィンドウのツールキットで作業する場合、Graphicsが実際にGraphics2Dを拡張し、まだあなたがGraphics2Dを拡張「する必要はない」ん他のGraphicsを使用することができることを

起こります(それは頻繁に起こることはありませんが、AWT/Swingではこれを行うことができます)。

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

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

class TestPaint extends JPanel { 

    public TestPaint() { 
     setBackground(Color.WHITE); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawOval(0, 0, getWidth(), getHeight()); 
    } 

    public static void main(String[] args) { 
     JFrame jFrame = new JFrame(); 
     jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jFrame.setSize(300, 300); 
     jFrame.add(new TestPaint()); 
     jFrame.setVisible(true); 
    } 
} 
+0

TestPaintがJPanelクラスを継承しなかった場合、JPanelにペイントしますか? –

3

をを呼び出しますはエラーです。

このメソッドは、パネルの作成時に自動的に呼び出されます。 paintComponent()メソッドは、Componentクラスで定義されたrepaint()メソッドによって明示的に呼び出すこともできます。

repaint()の呼び出しの効果は、パネル上のグラフィックを自動的に消去し、paintComponentメソッドを実行してこのパネル上のグラフィックを再描画することです。

関連する問題