アプリ版:「スタンプのみでお礼する」機能のリリースについて

始めて投稿させていただきます。

現在、javaアプリケーションのswingを利用し、ボタンを押したら画像が表示され、ウエイトの時間を過ぎると自動的に画像が消え、またボタンが表示され・・・を繰り返すプログラムを作っています。

ですが、色々なサイトを拝見させていただき、修正を加えたのですが思うように動いてくれません。
そこで、皆様のお知恵を拝借出来ればと思い投稿させていただきました。

下記にソースコードを記載しております。
すべてのソースコードを記載しておりますので長くなっております。

また最終的には、50個前後のボタン、画像の拡大等を行う予定です。

長文になりますがアドバイスをいただけましたら幸いです。

-----------以下ソースコード--------------------

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

class Test extends JPanel implements ActionListener{
static JFrame frame = new JFrame();
JButton bt1;
JButton bt2;
JPanel pn1 = new JPanel();
Dimension dim = this.getToolkit().getScreenSize();
int eventNo = -1;

public Test() {
frame.setTitle("これ");
frame.setUndecorated(true);
frame.setBounds(0, 0, 640, 480);
btStart();
pn1.setLayout(new FlowLayout());
frame.add(pn1);
frame.setVisible(true);
}

public void btStart(){
bt1 = new JButton("テスト");
bt2 = new JButton("終了");
pn1.add(bt1);
pn1.add(bt2);
bt1.addActionListener(this);
bt2.addActionListener(this);
}

// ボタン消去メソッド
public void btFormat(){
frame.remove(pn1);
bt1 = null;
bt2 = null;
}

public void actionPerformed(ActionEvent e){
if(e.getActionCommand() == "テスト"){eventNo = 1;}
if(e.getActionCommand() == "終了"){eventNo = 46;}
repaint();
}

public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
if(eventNo == 46){
System.exit(0);
}else if(eventNo == -1){
g2.clearRect(0, 0, 640, 480);
}else if(eventNo >= 0){
eventNo = -1;
btFormat();
try{
g2.drawImage(ImageIO.read(new File("./image/001.jpg")), 0, 0, this);
frame.add(this);
sleep(100);
g2.clearRect(0, 0, 640, 480);
btStart();
pn1.setLayout(new FlowLayout());
frame.add(pn1);
}catch(Exception e){
System.out.println(e);
}
}
}

// ウェイトを掛けるメソッド
public synchronized void sleep(long msec) {
for(int i=0; i<=msec; i++){
try {
wait(1);
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) {
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { System.exit(0); }
});
frame.getContentPane().add( new Test() );
}
}

A 回答 (5件)

要確認事項がいくつかあります。



・JButton#getActionCommand() の戻り値は、setText()の値になるのか
・「repaint()がpaintComponent()を呼ばなくなりました」はどのように確認をしましたか?
 (本当に呼ばれていないのか)
・Testのインスタンスのコンポーネントはframeの中でどんなサイズになっているか。
(0×0になっていませんか?)



しかし、それ以前にプログラムの作りが悪いです。

・アクションの度に、コンポーネントを削除/追加を行うのはどうでしょうか。
・処理の中でframeを直接操作していますが、これもどうかと思います。
・コンポーネントの用途に一貫性がないように感じます。
・以上のことが原因となってデバッグがしにくくなっています。



ひとつの案として次のような構造に変えてみてはどうでしょうか。

・アプリケーションクラスとしてJPanelを継承したものを用意する
・このクラスの中に
  ・画像表示用コンポーネント
  ・ボタン等を表示するコンポーネント(UIコンポーネント)
 を表示させる。

 その際、画像とボタンを同時に表示したくないのであれば、
 このクラスのレイアウトにはjava.awt.CardLayoutを使ってください。
 このレイアウトでは、任意のコンポーネントだけを表示させることができます。

・UIコンポーネントには、addActionListenerメソッドを作ります。
 実装は、各ボタンに対しaddActionListenerを発行するだけでいいかと思います。
 また、各ボタンのコマンドはsetActionComanndで設定してください。
 さらに、コマンド文字列はUIコンポーネント内でpublicで定数として定義します。


・アプリケーションクラスでは、ActionListenerを実装します。
 処理内容は、

  ・IMAGE/画像を表示(同時にボタンを非表示)する (実際はCardLayoutの切り替え)
  ・EXIT/アプリケーションを終了させる
  ・FADEOUT/画像を非表示(同時にボタンを表示)する(実際はCardLayoutの切り替え)



・sleepとしてやっていたことは、javax.swing.Timerを使用します。
 これを使うと、指定した時間が経過したときにイベントが発生し呼び出されます。
 呼び出されたときに、アプリケーションクラスのactionPerformを呼び出します。
 このときのコマンドは「FADEOUT」です。


・画像表示はJLabelを使えば簡単です。





 以上の構造をまとめると、



 ・画像ボタンを押した場合

  UIコンポーネント -> APクラス-> 画像表示コンポーネント

 
 ・画像表示時間が経過した場合

  タイマークラス -> APクラス-> 画像表示コンポーネント


 ・終了ボタンを押した場合

  UIコンポーネント -> APクラス

 となります(実際にはAPクラスはCardLayoutを操作するだけで、画像コンポーネントは操作しません)





最後にAPクラスをFrameに張り付ければ終了です。


このような構造にしておくと、例えば1つのウインドウに今回の機能と、他のものを同時に表示したい
などという際に、簡単に実装可能です。
(ちゃんとするなら、「終了処理」も少し工夫したほうがいいですが・・)



以上、ひとつの案としてどうぞ。
    • good
    • 0
この回答へのお礼

ご指導ありがとうございます。

ご回答いただいた意見を参考にもう一度1から(使える部分はそのまま使いますが・・・)作りなおしてみます。

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

お礼日時:2011/09/23 04:01

文字列の比較は == ではなく equals メソッドを利用しましょう。

    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ご指摘の通りactionPerformedメソッド内の比較を

if(e.getActionCommand().equals("テスト")){eventNo = 1;}
if(e.getActionCommand().equals("終了")){eventNo = 46;}

とさせていただいたのですが、次はrepaint()が同クラス内のpaintComponent()を呼ばなくなりました。

そこで以前の状態に戻し、再コンパイルしたところ、同じくrepaint()がpaintComponent()を呼ばなくなりました。

一応、文字の比較で==を使った場合とequalsを使った場合で変数eventNoの違いを確認しましたが、両方とも押されたボタンで代入される値を持っていました。

他に何か気がついた事などあればご教授下さい。

お礼日時:2011/09/22 15:36

失敬。

前の回答は Thread#sleep(long) かとおもったら自作メソッドだったorz
    • good
    • 0

sleep(100);


表示は 100ミリ秒(1/10秒)の間なのでひとまずこれを伸ばしてください。
    • good
    • 0

> 思うように動いてくれません。



想定と結果を書いてください。

この回答への補足

説明が足らず失礼いたしました。

想定は画面が表示されたら複数のボタンが表示され、ボタンを押したらボタンをすべて消し、押したボタンに対応する画像を表示し、ウエイトをかけ、ウエイトが終了したら画像を消し、最初の複数のボタンを表示し、またボタンを押したら対応するボタンが表示されるというのを繰り返そうと思っております。

ですが、結果として最初のボタンは表示されるのですが、画像が表示されず、ボタンも残ったままになってしまいます。

分かりにく表現かも知れませんがよろしくお願いします。

補足日時:2011/09/21 16:20
    • good
    • 0

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