2010-11-26 22 views
1

JavaをNetbeansで約1年間コーディングしていて、グラフを画面にプロットするデータ操作コードがたくさん書かれています。私は通常、メインウィンドウにJPanelオブジェクトを作り、カスタムペイントコードを書いて、必要に応じてrepaint()メソッドを呼び出します。別のクラスから呼び出されたときにJavaの再描画メソッドが動作しない

しかし、今日、はじめて、パネルを含むクラス(オブジェクト)からパネル上の再描画を呼び出そうとしました。コンパイラはこれに何も問題はなく、デバッグモードでは再ペイントの外部呼び出しに対して適切にシングルステップしましたが、実際に再描画は行われず、コードは実際に再描画メソッドに入りませんでした。

下図のように、私は(それは2つだけ、画面上のパネルを設定するコードが含まれているため、メインが、省略されている。)、問題を実証するためのミニマリストプログラムを書いた

---クラスの説明を、最初の誰もがこのに任意の洞察力を持っている、または回避策を知っている場合は、描画面、他の再描画コール---

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

public class Panel1 extends JComponent 
{ 
    GraphPnl graphPnl; 
    boolean colorFlag; 

    public Panel1() 
    { 
    setLayout(null); 
    colorFlag = true; 

    graphPnl = new GraphPnl(); 
    graphPnl.setBounds(10, 10, 110, 110); 
    graphPnl.setBackground(Color.black); 
    add(graphPnl); 

}//Panel1() 

public class GraphPnl extends JPanel 
{ 
    //just draws a line segment, toggling color 

    @Override 
    public void paint(Graphics g) 
    { 
     super.paint(g); 
     Graphics2D g2 = (Graphics2D) g; 
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
       RenderingHints.VALUE_ANTIALIAS_ON); 

     if (colorFlag) {g2.setColor(Color.red);} else {g2.setColor(Color.green);} 
     g2.drawLine(10, 10, 50, 50); 
    }//paint 
}//GraphPnl 
}//Panel1 

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

public class Panel2 extends JComponent 
{ 
    JButton testBtn; 
    TestAction testAction; 
    Panel1 p1; 

    public Panel2() 
    { 
     p1 = new Panel1(); 
     testBtn = new JButton("Click"); 
     testBtn.setBounds(10, 10, 80, 30); 
     add(testBtn); 
     testAction = new TestAction(); 
     testBtn.addActionListener(testAction); 
    }//Panel2() 


    public class TestAction implements ActionListener 
    { 
    public void actionPerformed(ActionEvent evt) 
    { 
     p1.colorFlag = ! p1.colorFlag; 
     p1.graphPnl.repaint(); 
    } 
    }//TestAction 
}//Panel2 

が含まれている、私はあなたから を聞いてとても幸せに思います。

ありがとうございました。

ジョンDoner

+0

もちろん、ウィンドウ1のrepaint()メソッドは、ウィンドウ2にフォーカスがある間に機能します。複数のスレッドはこれとは関係がなく、実際にはあなたが望むものと完全に反対です。すべてのSwingの更新はEDTで行う必要があります。あなたが受け入れた答えのあなたのコメントは理にかなっていません。その他の回答では、あなたの問題に対する本当の解決策が得られました(SSCCEをまだ投稿していないので、あなたが提供した制限付きコードに基づいています)。がんばろう。 – camickr

答えて

0

私はあなたのJComponentをペイントしているとき、クリップ領域はそのJComponentのに設定されていることを信じています。したがって、他のコンポーネントがペイントしようとした場合(または再ペイントを呼び出した場合)、クリッピングのためにコンポーネントはペイントされません。

+0

あなたはおそらくそれが正しいと思います。私は上記の答えの点で簡単な例を改めて試してみましたが、同じ結果が得られました。つまり、画面上に2つの別々のウィンドウを作成すると、ウィンドウ2にフォーカスがあるときに呼び出された場合、ウィンドウ1の再描画メソッドは有効になりません。おそらく、私が追求する複数のスレッドを使用することによって、これを回避する方法があります。 –

+0

私は、スイングは主にマルチスレッドではないので、マルチスレッドのアプローチに反対することをお勧めします。代わりに、ダーティリージョンの概念を調査する必要があります。各ウィンドウは、ウィンドウの一部が汚れているときに注意する必要があります。次に、再描画メカニズムを自動的に呼び出さなければなりません。詳細については、http://java.sun.com/products/jfc/tsc/articles/painting/を参照してください。 – vy32

1

"スイングプログラムはpaint()を上書きするのではなくpaintComponent()を上書きする必要があります。" - Painting in AWT and Swing: The Paint Methods

mainは、2つのオンスクリーンパネルを設定するコードしか含まれていないため、省略されています。

Initial Threadsのように、EDTでGUIを構築していることを確認してください。

補遺:ここでは、両方の原則を示す例です:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.event.ActionEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** @see http://stackoverflow.com/questions/4282159 */ 
public class GraphPanel extends JPanel { 

    private boolean colorFlag; 

    public GraphPanel() { 
     this.setPreferredSize(new Dimension(640, 480)); 
    } 

    public void toggle() { 
     colorFlag = !colorFlag; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     if (colorFlag) { 
      g2.setColor(Color.red); 
     } else { 
      g2.setColor(Color.blue); 
     } 
     g2.drawLine(0, 0, getWidth(), getHeight()); 
    } 

    private void display() { 
     JFrame f = new JFrame("GraphPanel"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(this, BorderLayout.CENTER); 
     f.add(new ControlPanel(this), BorderLayout.SOUTH); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new GraphPanel().display(); 
      } 
     }); 
    } 
} 

class ControlPanel extends JPanel { 

    public ControlPanel(final GraphPanel gp) { 
     this.add(new JButton(new AbstractAction("Click") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       gp.toggle(); 
       gp.repaint(); 
      } 
     })); 
    } 
} 

補遺:@のcamickrさんのコメントで述べたように、A Visual Guide to Layout Managersがあなたのレイアウト選択を導くに役立つことがあります。それは2つだけ、画面上のパネルを設定するコードが含まれているため

+0

+1、例とチュートリアルのリンクです。今ではポスターもレイアウトマネージャを使って読むことができ、 'setPreferredSize()'の代わりに – camickr

1

メインは、省略されている。)

さて、あなたは知っていない問題が発生した際にどのようなコードがある定義しますか、問題が解決されるまでは相対的ではありません。したがって、完全なSSCCEを投稿する必要があります。

あなたのコンポーネントのサイズが0であるため、塗装するものは何もありません。

あなたが中心にパネルを追加しましたので、私は一般的に、私のメインウィンドウでのJPanelオブジェクトを植えるカスタムペイントコードを書き、

を必要に応じてあなたがおそらく幸運再描画()メソッドを呼び出しますフレームに使用可能なすべてのスペースをパネルに自動的に与えるBorderLayout

trashgodの例は、カスタムコンポーネントの推奨サイズを設定する方法の1つを示しています。別の方法は、getPreferredSize()メソッドをオーバーライドして適切な値を返すことです。

nullレイアウトを使用するのではなく、レイアウトマネージャを使用する方法を学ぶ必要があります。このような問題は今後回避できます。ドラッグ・ドロップ型のアプリケーションを使用しない限り、ヌル・レイアウトを使用する必要はありません。

+0

+1というリンクを投稿する必要はありません。 – trashgod

+0

私はヌルレイアウトプロセスが好きです。私は非常にカスタムのGUIをたくさん作成し、いろいろなレイアウトを試しましたが、今は1時間ほどで非常に複雑なインターフェースを作り出すことができます。もし私がこれを変更したいのであれば、フィットを参照してください。私の意見では、SwingのレイアウトはJavaの最も弱い部分です。 –

+0

これは、レイアウト管理者を理解していないため、初心者の皆さんが考えるものです。数時間ではなく、複雑なインターフェースを作成するのに数分しかかかりません。プログラミングだけでなく、コードを作成するのにかかる時間ではなく、コードやレイアウトマネージャを維持することで、次の人のための作業が容易になります。たとえば、10個のコンポーネントの行があり、最初にコンポーネントを追加する必要がある場合などです。 FlowLayoutを使用する場合、これは1行のコードです。ヌルレイアウトを使用すると、元の10個のコンポーネントの境界を調整する必要があります。 – camickr

関連する問題