痔になりやすい生活習慣とは?

 JAVA初心者です、宜しくお願いします。
 参考書で、Swingについて以下のようなコメントを見つけました、ただ何故そうなのかの理由を書いていません。
 以下の内容はどのような理由からそうなるのでしょうか。

 「Swing コンポーネントでは、メソッドpaintは推奨されていません。
 paintComponentをプログラムから呼び出してはいけません。描画をしたい場合は、 paintComponent をオーバー
ライドしたクラスの repaint() メソッドを呼び出します。
 Swing コンポーネント上に描画するには、 描画したいコンポーネントのクラスを継承したクラスで、
メソッド paintComponent(Graphics g) をオーバーライドし、 パラメータで渡された g に対して Graphics
クラスのメソッドで描画をします。
 オーバーライドした paintComponent の先頭で、このコンポーネントの土台を描画するために、
super.paintComponent(g) を呼び出しておきます。」

 宜しくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

Swingでは、コンポーネントの描画はかなり複雑になっている。

AWTでは、repaintが呼ばれると、updateが呼ばれた後、paintが呼ばれる。が、Swingでは、paing内で更にpaintComponentによってコンポーネントが描画され、それからpaintBorderでボーダーが描画され、最後にpaintChildrenによって内包するコンポーネントの描画が呼び出される、という仕組みになっている。

したがって、paintをオーバーライドしてしまうとその中で呼ばれる各種描画メソッドが呼ばれなくなり、コンポーネントの描画が正しく行われなくなる可能性がある。このため、何かを描画したい場合には、paint内の、コンポーネント描画のために用意されているpaintComponentをオーバーライドして描画を行う。ただし、これもsuperにメソッドを送るのを忘れると本来の描画が正しくなされないため、かならずsuper.paintComponentしないといけない。

また、このように複雑に描画が行われるため、全体を再描画する場合にはかならずrepaintしないといけない。途中のメソッドを呼び出すと、全体の描画が正しく行われない可能性がある。

要するに、AWTの場合は、paintは描画処理の末端のメソッドであり、「プログラマが勝手に使っていいメソッド」として用意されていて、そこではコンポーネントのクラスでは何も処理が実装されていなかった。ところがSwingでは、paintは末端の何もしていないメソッドではなくなり、その内部でコンポーネントの描画に必要なメソッドの呼び出しなどが細かく実行されるようになった。このために、すべてのメソッドが正しく実行されるように注意してコードを書かないといけなくなった、ということ。やれ、「このメソッドはオーバーライドするな」とか「これは最初にsuperに送れ」とかというのは、すべて「あらかじめ設計されたとおり、描画のためのメソッドが正しい順にすべてきちんと実行される」ようにするためのマナー、ということ。
    • good
    • 0
この回答へのお礼

logger_manさん、有り難うございました、今後とも宜しくお願いします

お礼日時:2009/09/22 18:53

このQ&Aに関連する人気のQ&A

Java 参考書」に関するQ&A: submitとは?

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QJava、jPanelに描画する

お世話になっています。
Java言語を始め、オブジェクト指向というなれない環境にいます。(今まではBASICを利用)

今回、jPanelなるものを使い、その中に四角形などを描画したいのですが、
うまくいきません。

public void paintComponent(){
Graphics pnl = panel.getGraphics();
pnl.setColor(new Color(0,0,255));
pnl.drawOval(100,100,50,50);
}

こういう関数を作り、プログラムから呼び出しています。(フレーム作成時には表示しない)
おそらくこの辺りがダメだと思うのですが、よくわかりません。

すいませんが、jPanelの使い方を詳しく教えていただけないでしょうか。
ゲームを作る課題なのですが、ここで詰まってしまい進めません。

ご存じの方がいらっしゃいましたら、ご教授ください。
よろしくお願い致します。

Aベストアンサー

このクラスの定義をざっくり書くと、

class Frame extends JFrame{
 Jpanel panel = new Jpanel(); //描画領域
 Jpanel label = nel Jpanel("得点");
 JButton btnNewButton = new JButton("ヘルプ");

 public Frame(){
  いろいろコンポーネントを追加...
  btn.newActionListener(this);
  this.setVisible(true);★
 }

 actionPerformed(ActionEvent e){
  this.repaint(); //自身のインスタンス(フレームを再描画)
 }
}

と推測しました。★のタイミングでpaintComponent(Graphics g)が呼び出されます。引数Graphics ???(なんでもよい)は必要です。描画が必要なタイミングでpaintComponentメソッドを呼び出します。詳しくは後述。

>はよく見るカタチのサンプルですが、これは呼びださなくてもjFrameだけなら描画されていることがないですかね?^^;
回答はJPanelを想定しております。
JFrameに対して、setVisible(true)した段階では、JPanelのpaintComponentのことまで構っていないように感じられますが、きちんと伝搬されます。 contentPane.add によってJpanelをJFrameに追加しているためです。

描画の際は、描画対象となるオブジェクトの情報がGraphicsクラスに入っているため、Graphicsのインスタンスを参照します。Graphics gならば"g"がインスタンスにあたります。

>引数に何を渡しているのか、それはどうやって取得するのか……
paintComponentの引数は(Graphics g)が必須だったと思います。
"paintComponent Java" をキーワードとして検索します。JComponentのクラスに関するドキュメントが得られます。クラスドキュメントを参照する限りでは、引数Graphics gは必須です。その他の条件のpaintComponentメソッドがここに記載されていないためです。

http://docs.oracle.com/javase/jp/6/api/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)
Jpanelじゃないの?という疑問が生まれると思いますが、前提をお読みください。

java.lang.Object
 └java.awt.Component ◎
  └java.awt.Container
    └javax.swing.JComponent ★
      └javax.swing.JPanel ☆

(前提)
1)お示ししたURLは★のJComponentですが、☆のJPanelから上位のクラスで定義されているメソッドを参照することができます。今回は継承と呼びます。
2)定義済みのメソッドをプログラマ自身が書き換えることができます。これをオーバーライドと言います。
3)特に定義しなくても★のpaintメソッドでpaintComponent(Graphics g)を呼ぶよう定義されているため、プログラマは、paintComponent(Graphics g)を定義すればよいことになります。

(重要)
・paintComponent(Graphics g)が発生するのは、イベントが発生して、FrameやPanelに描画の必要が生じた時です。例えばフレームの表示、サイズの変更が挙げられます。他にもあるかもしれませんが全てを把握しておりません。
JFrame.setVisible(true)を強調しているのは、これが発行されるまでJFrameに配置したコンポーネントのpaintComponentが呼ばれることがないためです。

paintComponent()と定義することはできますが、Javaは、paintComponent(Graphics g)に対して呼び出しをかけるので、定義されたメソッドは呼び出されないことになります。

プログラム上の処理が発生して、再描画が必要であれば、そのコンポーネントに対して、repaint()を起こすことになります。その延長でpaintComponent(Graphics g)が呼び出されます。repaintは◎で定義されているメソッドです。前提1に基づいて呼び出し可能となります。

>(※1)System.out.printlnでnullpointerが返ってきていないのでそう判断
これは再上位から「標準出力」をとっているだけなので、NullPointerは返りません。ハンドル(Javaではインスタンス)が取得できていることにはなりません。

>Javaにはデバイスコンテキストという概念が表に出ていないと聴きました。
インスタンスという概念で特定をします。
例えば、paintComponent(Graphics g)の場合、

paintComponentメソッドは、Graphicsクラスの gインスタンス(変数)を引数に持つ。という意味になります。デバイスハンドラやデバイスコンテキストはインスタンスになっているという認識で私はいます。
また、paintComponent()としてしまうと、引数を持たないpaintComponentメソットとなります。同時に定義することができる全く違うメソッドになってしまうので注意が必要です(多相性といいます)。

このクラスの定義をざっくり書くと、

class Frame extends JFrame{
 Jpanel panel = new Jpanel(); //描画領域
 Jpanel label = nel Jpanel("得点");
 JButton btnNewButton = new JButton("ヘルプ");

 public Frame(){
  いろいろコンポーネントを追加...
  btn.newActionListener(this);
  this.setVisible(true);★
 }

 actionPerformed(ActionEvent e){
  this.repaint(); //自身のインスタンス(フレームを再描画)
 }
}

と推測しました。★のタイミングでpaintComponent(Graphics g)が呼び...続きを読む

Q描画処理が実行されない

while(gameflag==true){
(数値設定)   
repaint();
long start = System.currentTimeMillis();
while(System.currentTimeMillis()<start+1000){
}
}

上記のようにwhileループの中で数値などの設定を行い、描画をし、遅延をしているのですが他の処理はちゃんと実行されるのになぜか描画処理だけが行われません。また、whileループ外でも描画を行っていますがその時点ではきちんと描画されます。描画されない原因はどのようなことが考えられるでしょうか?描画はpaintComponent(Graphics g) メソッドで描画しています。

Aベストアンサー

>描画されない原因はどのようなことが考えられるでしょうか?

Swingの描画はダブルバッファを使っている関係上、描画メソッドを呼び出したときではなく、その後、もっとも早く再描画できるタイミングで表示を更新します。このため、while内で描画を行っている場合には、そのwhileを抜け、処理が終了した頃で表示が更新されるため、while中で行っている描画処理は見えません。(途中の描画は見えず、最終的に描画された状態だけが表示される)

この処理は、別スレッドを使って実行していますか? メインスレッドでは、上のような理由で途中の更新は見えませんから、マルチスレッドで実行し、描画ごとに強制的にrepaintするなどしてみてはいかがでしょう。

Qボタンクリック後パネルを再描画repaintしたい

ボタンをクリック後にstaticで保持していた値にプラス1して
その値をパネルに再描画したいと思っています。
下記のプログラムだとボタンをクリックすると
(<1<2<3<4)となって画像と数字が増えてしまいます
行いたいのは数字の部分だけが再描画されて
カウントされて<3と表示されるだけになってもらいたい


クラス1つ目

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class Sample extends JFrame{
static int value=1;
JPanel work = new JPanel();
public static void main(String[] args) {
Sample frame = new Sample();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 200, 200, 100);
frame.add(frame.createPanel(), BorderLayout.LINE_END);
frame.setVisible(true);
}
public JPanel createPanel() {

ImageIcon icon = new ImageIcon("./img/left.gif");
JLabel label = new JLabel();
Cursor c = new Cursor(Cursor.HAND_CURSOR);
label.setCursor(c);
label.setIcon(icon);
JLabel strLabel = new JLabel();
String str = Integer.toString(value);
strLabel.setText(str);
work.add(label);
work.add(strLabel);
label.addMouseListener(new myListener());
return work;
}
class myListener extends MouseAdapter{
public void mouseClicked(MouseEvent e){
System.out.print(Sample.value++);
createPanel().repaint();
setVisible(true);
}
}
}


クラス2つ目
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class MouseAdapter implements MouseListener{
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
}

ボタンをクリック後にstaticで保持していた値にプラス1して
その値をパネルに再描画したいと思っています。
下記のプログラムだとボタンをクリックすると
(<1<2<3<4)となって画像と数字が増えてしまいます
行いたいのは数字の部分だけが再描画されて
カウントされて<3と表示されるだけになってもらいたい


クラス1つ目

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.MouseEvent;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing....続きを読む

Aベストアンサー

>class myListener extends MouseAdapter{
>createPanel().repaint();

createPanelでパネルを新規作成してrepaintしていますから、そういった動作になると思います。
labelをクラス変数として保持して、そこに設定するのが簡単だと思います。

Qフレーム上のコンポーネントの削除について

フレーム上の表示内容を切り替えるために、
それまでフレーム上にあったチョイス(choice)を
remove(choice1)メソッドで削除して、その場所に(その上に)画像(image)を表示したいと思うのですが、
チョイスは消えて表示されなくなるのですが、
チョイスのあったところだけ画像が表示されません。
チョイスの影響を消して、普通に画像を表示するにはどうしたらよいでしょうか。よろしくお願いします。

choice1.setLayout(null);
choice1.setBounds(500,300,100,20);
のように、nullレイアウトにしてあります。

Aベストアンサー

>remove(choice1)メソッドで削除
>チョイスは消えて表示されなくなる
>チョイスのあったところだけ画像が表示されません


「『チョイス』以外にそこにまだ
不要なごみコンポーネントが追加されてるから
(つまり削除してない「何か」があるから)」。

どのコンポーネントになにをどれだけ追加(add)したのか、
自分のソースコードを
再点検しましょう。

Q生成したインスタンスを削除する方法

言語:JAVA

生成したインスタンスを削除するにはどのようにすれば良いでしょうか?

testData = new TestData();

testDataはセッション内に格納してあります。
また、testDataはNULLのままだったり、実際に値が入っていたりもします。

NULLのままだと不具合があるため、NULLの場合は、インスタンスそのものを削除してしまいたいと考えています。
初歩的な質問ですみませんが、教えてください。

よろしくお願いいたします。

Aベストアンサー

浅学なため、TestDataというクラス名と「セッション内に格納」という表現だけからどうしてHttpSessionが出てくるのか分かりませんが...

Javaでは、明示的な操作(C++のdeleteのような)によってインスタンスを削除することはできません。そのインスタンスがどこからも参照されなくなったらGCで消えます。もう要らない(消えてほしい)インスタンスを参照している変数やフィールドにはnullを代入することで参照をなくします。

testData = null;

> NULLのままだと不具合があるため、NULLの場合は、インスタンスそのものを削除してしまいたい

何がNULLだとどのように不都合なのかを説明してもらえると、別の回答がつくかもしれません。

Qボタンの複数割り当てについて

public class TestButton extends Applet implements ActionListener
{
     Button bt1,bt2,bt3;

     public void init()
     {
         bt1 = new Button("red");
         add(bt1);
         bt2 = new Button("blue");
         add(bt2);
         bt3 = new Button("yellow");
         add(bt3);
         bt1.addActionListener(this);
      }

java初心者です。アプレットで上のようにボタンを作ります。それぞれが押された時に、red,blue,yellowが表示されるようにしたいのです。ActionListenerをインプリメントしているので、

     public void actionPerformed(ActionEvent ae)

をオーバーライドする必要がありますが、そこで質問です。
ボタンを3種類別々に関連づけるには、actionPerformed内をどのように記述したらよいでしょうか?また、init内はこれだけでいいんでしょうか?
よろしくお願いします。

public class TestButton extends Applet implements ActionListener
{
     Button bt1,bt2,bt3;

     public void init()
     {
         bt1 = new Button("red");
         add(bt1);
         bt2 = new Button("blue");
         add(bt2);
         bt3 = new Button("yellow");
         add(bt3);
         bt1.addActionListener(this);
      }

java初心者です。アプレットで上のようにボタン...続きを読む

Aベストアンサー

これは色々やり方があります。
ボタンをメンバ変数として定義してActionEventの
getSource()メソッドでEventが発生したObjectと
比較するとか、getSource()で取得したオブジェクト
をButtonにキャストしてからgetLabel()でラベルの
文字列を取得し任意の文字列と比較するとか。
他にはアクションコマンドで分岐する方法もあります。

・メンバ変数の例

public class TestButton extends Applet implements ActionListener {
  Button btn1,btn2,bt3;
  public void init(){
    btn1=new Button("red");
    add(btn1);
    btn2=new Button("blue");
    add(btn2);
    btn3=new Button("yellow");
    add(btn3);
  }
  public void actionPerformed(ActionEvent e){
    Object obj=e.getSource();
    if(obj == btn1){
      // "red"の処理
    }
    else if(obj == btn2){
      // "blue"の処理
    }
    else if(obj == btn3){
      // "yellow"の処理
    }
  }
}

・ラベルで比較する例

public void acitonPerformed(ActionEvent e){
  Object obj=e.getSource();
  if(obj instanceof Button){
    Button btn=(Button)obj;
    String labStr=btn.getLabel();
    if("red".equals(labStr)){
      // "red"の処理
    }
    else if("blue".equals(labStr)){
      // "blue"の処理
    }
    else if("yellow".equals(labStr)){
      // "yellow"の処理
    }
  }
}

・アクションコマンドの例

public void actionPerformed(ActionEvent e){
  String cmdName=e.getActionCommand();
  if("red".equals(cmdName)){
    // "red"の処理
  }
  else if("blue".equals(cmdName)){
    // "blue"の処理
  }
  else if("yellow".equals(cmdName)){
    // "yellow"の処理
  }
}

制約が無ければアクションコマンドでの処理が私は好きです。

これは色々やり方があります。
ボタンをメンバ変数として定義してActionEventの
getSource()メソッドでEventが発生したObjectと
比較するとか、getSource()で取得したオブジェクト
をButtonにキャストしてからgetLabel()でラベルの
文字列を取得し任意の文字列と比較するとか。
他にはアクションコマンドで分岐する方法もあります。

・メンバ変数の例

public class TestButton extends Applet implements ActionListener {
  Button btn1,btn2,bt3;
  public void init(){
    btn1=new Bu...続きを読む

QKeyListenerの使い方について

FrameクラスのフレームにKeyListenerをaddKeyListenerで登録してキー入力を受け付けたいのですが、キーを入力してもまったく反応がありません。どうやらkeyTyped,keyPressed,keyReleasedのどのメソッドも呼び出されてないようです。クラスの概要は以下のとおりです。
class sampleFrame extends Frame implements KeyListener
{
{
addKeyListener(this);//コンストラクタ内で登録
}



で、keyPressedとうのメソッドはすべて定義しています。それから、キーを入力するとなぜか同じフレーム上のリストボックスの項目が入れ替わったりします。
どうぞよろしくお願いいたします。

Aベストアンサー

こんにちは。
おそらくフォーカスの問題だと思います。
フォーカスをフレームに設定してあげれば良いのですが、一度でも内部のコンポーネントに(クリックするなど)フォーカスを設定すると、フォーカスをフレームに再設定する仕掛けを用意しておく必要があります。
- - -
import java.awt.*;
import java.awt.event.*;

public class Test extends KeyAdapter {

Frame frame;
List list;

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

public Test() {
list = new List();
list.add("apple");
list.add("orange");
list.add("banana");
list.removeKeyListener(this);

frame = new Frame("Test");
frame.add(list);
frame.setSize(400, 300);
frame.setLocation(100, 100);
frame.addKeyListener(this);
frame.show();
frame.requestFocus(); // フレームにフォーカスを設定
}

public void keyPressed(KeyEvent e) {
System.out.println("key pressed.");
}

}

こんにちは。
おそらくフォーカスの問題だと思います。
フォーカスをフレームに設定してあげれば良いのですが、一度でも内部のコンポーネントに(クリックするなど)フォーカスを設定すると、フォーカスをフレームに再設定する仕掛けを用意しておく必要があります。
- - -
import java.awt.*;
import java.awt.event.*;

public class Test extends KeyAdapter {

Frame frame;
List list;

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

public Test() {
list = new List();
list....続きを読む

QJpanelへの描画について(初心者です)

質問1
実行した時に内容が表示されたりされなかったりします、どうしてでしょうか?
いろいろ試してみましたが分かりませんでした。
質問2
JPanelではダブルバッファリング機能が備わっているみたいですが、
という事はこのソースでもそれは行なわれているのでしょうか?

以上2点と質問が多いですがよろしくお願いします。

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

public class JFrameTest extends JFrame{
 JPanelTest panel;
 Container ct;
 public static void main(String[] args){
  new JFrameTest();
 }
 public JFrameTest(){
  super("JFrameTest");
  panel = new JPanelTest();
  ct = getContentPane();
  setSize(480,480);
  setResizable(false);
  setVisible(true);
  setDefaultCloseOperation(EXIT_ON_CLOSE);
  ct.add(panel);
 }
}

class JPanelTest extends JPanel{
 public JPanelTest(){
  setSize(480,480);
 }
 public void draw(Graphics g){
  g.drawString("Test",240,240);
 }
 public void paintComponent(Graphics g){
  super.paintComponent(g);
  draw(g);
 }
}

質問1
実行した時に内容が表示されたりされなかったりします、どうしてでしょうか?
いろいろ試してみましたが分かりませんでした。
質問2
JPanelではダブルバッファリング機能が備わっているみたいですが、
という事はこのソースでもそれは行なわれているのでしょうか?

以上2点と質問が多いですがよろしくお願いします。

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

public class JFrameTest extends JFrame{
 JPanelTest panel;
 Container ct;
 public static void main(String[] arg...続きを読む

Aベストアンサー

こんばんは。
実行した際に表示される/されない原因は、フレームをsetVisible(true);した後に、パネルをセットしているからです。
試しにsetVisible(true);とct.add(panel);の間で、
try {
Thread.sleep(100);
}
catch(Exception e) {}
というコードを入れておくと、より高い確率で表示されないようにできると思います。
きちんと表示させたい場合は、フレームを作り終わった後(JFrameTest()コンストラクタの最後で)setVisible(true);を呼んでみてください。

ダブルバッファリングについても、
public void draw(Graphics g){
g.drawString("Test",240,240);
try {
Thread.sleep(2000);
}
catch(Exception e) {}
g.drawString("Test2",240,270);
}
という内容で確認できると思います。

Q【Swing】JPanel クラス外からのremoveについて

_tonnuraと申します。どうぞよろしくお願いします。

現在、
・初期画面(Menu.java)
・イベント(ButtonClicked.java)
・パネル設定(Mondai.java)
の3つを使用して、画面を切り替えようとしています。(パネルを載せていく形です)

「Class Mondai」にて定義したパネル(p10)の部品を、フレームに載せる前にいじりたいと思っていますが、「☆」の部分で困っています。

内部で「add」「remove」する分には問題ないのですが、一旦外にでてしまうと、配列でしか「remove」できない状態です。
上記の挙動から、戻り値的には「ButtonClicked」上でコンテナ(p10)が見えていると思うのですが、配列以外(名前やID等、処理のたびに変動しないもの)で指定することはできないのでしょうか。

画面によってはループを考えていますので、必要な部分だけ追記したいのです。配列での指定ですと応用が辛いので・・。

尚、ソースが無駄に長いため 概念的な部分だけ抜き出しています。
「そもそも」な部分が多々あると思いますが、なにとぞよろしくお願いします。

■Class Menu
package test;
//フレームの定義
public class Menu extends JFrame{
    public static void main(String[] args) {
        Menu frame_m = new Menu();
        frame_m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame_m.setTitle("画面遷移テスト");
        frame_m.setBounds(10, 10, 750, 570);
        frame_m.setVisible(true);
        frame_m.setResizable(false);
    }
    Menu() {

    ~(省略)初期画面のパネル・部品・レイアウトに関する宣言~

    panel_menu.add(t_label);
    getContentPane().add(panel_menu);
    validate();
    }

■Class ButtonClicked
package test;
Class ButtonClicked implemments ActionListener{
    //フレームを格納 パネル作成時の設置先として使用
     public Menu owner;
    //パネルを格納  前パネルの削除先として使用(getContentPane)
    public Container subowner;

    public void actionPerformed(ActionEvent ae) {
            String cmd = ae.getActionCommand();

            if (cmd.equals("btn_01")) {
            //遷移画面の描写(パネルを被せる)
                Mondai obj = new Mondai();
                Container p10 = obj.drawPanel(owner);

    //Class Mondaiにて定義したパネル上のコンポーネントJButton3)を削除したい
    ☆問題の部分です(ERROR:「JButton3を解決できません」)
//               p10.remove(JButton3);
    ☆こっちだとOK (varidate後、表示されていない)
                p10.remove(3);//owner.list(System.out)参照

                owner.add(p10);
                owner.validate();
            } else if (cmd.equals("btn_b02")) {
            //別の処理hogehoge
            }
}
■Class Mondai
package test;
public Container drawPanel(Menu frame)throws Exception {

    JPanel p10 = new JPanel();

    ~(省略)遷移画面のパネル・部品・レイアウトに関する宣言~
    p10.add(JButton1);
    p10.add(JButton2);
    p10.add(JButton3);

    return p10;
}

_tonnuraと申します。どうぞよろしくお願いします。

現在、
・初期画面(Menu.java)
・イベント(ButtonClicked.java)
・パネル設定(Mondai.java)
の3つを使用して、画面を切り替えようとしています。(パネルを載せていく形です)

「Class Mondai」にて定義したパネル(p10)の部品を、フレームに載せる前にいじりたいと思っていますが、「☆」の部分で困っています。

内部で「add」「remove」する分には問題ないのですが、一旦外にでてしまうと、配列でしか「remove」できない状態です。
上記の挙動...続きを読む

Aベストアンサー

remove()で削除するには、Container内のindex値かComponent自身のインスタンスを指定する必要がありますね。質問のコードでは、JButton3(どこかで宣言した変数でしょうか?)が、何か不明だということで、エラーになっているようです。このコードの流れで解決しようとするなら、p10のComponent群を検索して、removeしたいComponent(JButton3)のインスタンスを探し出す方法が考えられます。(getComponents()でComponentの配列を取得し、各 Component の Class や label値、name 値などを使って、対象を特定すれば良いでしょう。)
ただ、一度作ったパネルから、後から部品を取り除いて体裁を整えるというのは、いかにも不自然ですよね。
おそらく私なら、Mondai.drawPanel() に一つ引数を追加して、Panelの生成時に必要な部品のみを配置するようにすると思います。(フラグの意味付けとしては、各Buttonの有無を直接指定する方法と、パネルの種類とそれぞれに必要なButtonの種類の対応表を間に挟む方法があると思います。Java的な発想に従うなら、引数でスイッチするより、それぞれのPanelの種類ごとにdrawPanelXXXX(Menu frame)のような形でメソッドを分けるのがよいかもしれません。)

...
 (~)
 if (cmd.equals("btn_01")) {
  Mondai obj = new Mondai();
  Container p10 = obj.drawPanel(owner, (Mondai.BUTTON1 | Mondai.BUTTON2));
  owner.add(p10);
  owner.validate();
  (~)
...
public class Mondai {
public static final int BUTTON1 = 1;
public static final int BUTTON2 = 2;
public static final int BUTTON3 = 4;
...

public Container drawPanel(Menu frame, int buttons) throws Exception {
 (~)
 JPanel p10 = new JPanel();
 (~)
 if ((buttons & BUTTON1) != 0) {
  p10.add(JButton1);
 }
 if ((buttons & BUTTON2) != 0) {
  p10.add(JButton2);
 }
 if ((buttons & BUTTON3) != 0) {
  p10.add(JButton3);
 }

 return p10;
}

remove()で削除するには、Container内のindex値かComponent自身のインスタンスを指定する必要がありますね。質問のコードでは、JButton3(どこかで宣言した変数でしょうか?)が、何か不明だということで、エラーになっているようです。このコードの流れで解決しようとするなら、p10のComponent群を検索して、removeしたいComponent(JButton3)のインスタンスを探し出す方法が考えられます。(getComponents()でComponentの配列を取得し、各 Component の Class や label値、name 値などを使って、対象を特定すれ...続きを読む

Qinterface,extend,implementのちがい

お世話になります、

Javaを勉強しているのですが、
interface,extend,implementの使い分けがわかりません。

私の解釈としては、
(1)interfaceは、グローバル変数の定義、グローバルメソッドの定義(実装はしない)。

(2)extendは、extendクラスを親クラスとして親クラスの機能を使用できる。

(3)implementは…,implementもextendと同じような意味だと解釈しているんですが、違う点は、implementで定義してあるメソッドは、使用しなくても、実装しなければならないという点でしょうか?

とにかくこの3つのを使い分けるコツとかあれば教えてください。
よろしくお願いします。

Aベストアンサー

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば、getStringLength()メソッドなどが
あったほうが良いでしょうか。
このgetStringLength()メソッドは、2バイト文字も1バイト文字も「1文字」
と数えてくれると言う点で、まさに、日本語クラス用のメソッドだと言えるでしょう。

例えば、Java的に記述すると、、、
class Japanese {
public int getStringLength() {
  ・・・
return strlength;
 }
 ・・・
}

class TextField {
・・・
}

class JTextField extends TextField, extends Japanese {
・・・・
}

C++ではそのように実装するでしょう。
しかし、Javaにはこのような高度な機能はありません。

そこで、生まれた苦肉の策が、「interfaceとimplements」です。

interface Japanese {
public int getStringLength(); // interfaceは実装を含まない!
                 // すなわち「実装の継承」ができるわけではない。
}

class TextField {
・・・
}

class JTextField extends TextField implements Japanese {
・・・・
public int getStringLength() {
  ・・・
return strlength; //implementsの実装を「各クラスで」実装してやる必要がある。
 }
}


結局のところ、Javaでは、複数のクラスを親クラスには持ち得ないため、継承できなかったクラスは「各クラスで実装してやる必要性」があるのです。


ではどのように使うのが効果的か?

なまえのままです。「代表的なインターフェイス」にたいしてinterfaceを使うのが良いと思います。

例えば、プレイヤー系であれば、ビデオ・コンポ・ウォークマン・などにかかわらず、
interface controlpanel {
public play();
public stop();
public next();
public back();
}
というような基本的インターフェイスを「持っているべき」です。

こうすることで、それぞれのクラス宣言の際に、これらの「インターフェイスを持っているべきであり、実装されるべきである」ということを「強く暗示」することができます。
class videoplayer extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

こうすることで、同様のクラスを作成するユーザーは、
「プレイヤー系は、4つ操作が出来るコントロールパネルをインターフェイスとして持つべきなのだな!?」という暗示を受け取り、自分のクラスでもそれを模倣するでしょう。

class mp3player extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

また、これらのクラスを使用するユーザーも、「implements controlpanel」という
表記を見て、「4つの基本操作は押さえられているのだな!」という基本中の基本動作を抑えることが出来ます。

まとめると、クラスに「こういう特徴もたしてください!」「こういう特徴持ってますよ!」という一種の暗示的警告や方向性を与えることができるわけですね。

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば...続きを読む


人気Q&Aランキング