時限タイマーを作ってみよう6
最初は「できない」とか「ボツ」と思っても、少し日にちが経つと
「こうすればできるかも」とうまく行く方法に気づいたりします。
毎度、管理人イガジーです。
という訳で、時限タイマーなのですが、メッセージを出す窓を
FrameからDialogにすることにします。
プロトタイピングの時には「Dialogだと親窓にひっぱられて
一緒に最小化されるからボツ」と判断したのですが、あらためて
試してみると大丈夫でした(^^;)
MsgBoxをモーダルなDialogにすると、メッセージ(MsgBox/TimeBox)が
出た状態では設定窓で操作できなくなるので、昨日の問題点のいくつかが
解消できます。
※ モーダル(modal)(なダイアログ)というのは、
親より手前(上)に表示されそのダイアログを消すまで、親の窓が
アクティブにならないという挙動です。
Dialogにするにはclass MsgBox extends Dialog {
として、コンストラクタを
public MsgBox(Frame own, String message) {
super(own,"Information",true);
とします。
own が窓の親ですね。trueは、modal=trueの指定です。
MsgBoxを継承している TimeBox もコンストラクタを次のようにします。
public TimeBox(Frame own, String message) {
super(own, message);
new する際には
tmsg=new TimeBox(f,null);
alart=new MsgBox(f,"1以上の数字を入力してください");
になります。
次にキャンセル処理ですが、タイマーをスタートしたら[Start]ボタンを
[Cancel]ボタンに変更してしまうことにします。
Button の表示ラベルは、button.setLabel(“表示文字列”); で設定できます。
# JButtonの場合は、jbutton.setText(“表示文字列”); です。
ActionListenerは
startbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int dt=0;
try {
dt=Integer.parseInt(delay.getText().trim());
} catch (NumberFormatException e1) {
dt=0;
}
if (dt<1) alart.visible();
else {
if (timer==null) {
tmsg.lb.setText(msg.getText());
if (unit.getSelectedIndex()==1) dt*=1000; // second
else dt*=60000; // minute
timer=new Timer();
timer.schedule(new TimerProc(), dt);
f.setExtendedState(Frame.ICONIFIED);
startbtn.setLabel("Cancel");
}else{
timer.cancel();
timer=null;
startbtn.setLabel(" Start ");
}
}
}
});
と、timer動作中の処理を追加します。
f.setExtendedState(Frame.ICONIFIED);
は、設定窓を最小化する(タスクバーに入れる)処理です。
時間が来て、TimeBoxを表示したら
f.setExtendedState(Frame.NORMAL);
で、元に戻します。
TimeBoxを表示した時や、キャンセルした時には
startbtn.setLabel(" Start ");
として、startbtnの表示文字列(ラベル)を
“Start”に戻します。
ここまでの全コードは次のようになります。
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Point;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;
public class VTimer5 {
Frame f;
MsgBox alart;
TimeBox tmsg;
TextField msg,delay;
Button startbtn;
Choice unit;
Timer timer=null;
VTimer5(){
f=new Frame("Set Timer 5");
f.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent arg0) {
System.exit(0);
}
});
tmsg=new TimeBox(f,null);
alart=new MsgBox(f,"1以上の数字を入力してください");
f.setLayout(new GridLayout(2,1));
Panel p0=new Panel();
p0.add(new Label("表示文"));
msg=new TextField("時間です",20);
p0.add(msg);
Panel p1=new Panel();
delay=new TextField(" 3",3);
p1.add(delay);
unit=new Choice();
unit.add("分後");
unit.add("秒後");
p1.add(unit);
startbtn=new Button(" Start ");
startbtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int dt=0;
try {
dt=Integer.parseInt(delay.getText().trim());
} catch (NumberFormatException e1) {
dt=0;
}
if (dt<1) alart.visible();
else {
if (timer==null) {
tmsg.lb.setText(msg.getText());
if (unit.getSelectedIndex()==1) dt*=1000; // second
else dt*=60000; // minute
timer=new Timer();
timer.schedule(new TimerProc(), dt);
f.setExtendedState(Frame.ICONIFIED);
startbtn.setLabel("Cancel");
}else{
timer.cancel();
timer=null;
startbtn.setLabel(" Start ");
}
}
}
});
p1.add(startbtn);
p1.add(new Label(" ")); // スペーサ
Button btn_end=new Button("End");
btn_end.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
p1.add(btn_end);
f.add(p0);
f.add(p1);
f.setSize(280,120);
f.setVisible(true);
}
class MsgBox extends Dialog {
private static final long serialVersionUID = 1L;
Label lb;
Button btn;
MsgBox md;
public MsgBox(Frame own, String message) {
super(own,"Information",true);
md=this;
this.addWindowListener(new WindowAdapter(){
@Override
public void windowClosing(WindowEvent arg0) {
md.setVisible(false);
}
});
lb=new Label(message); // for message
lb.setFont(new Font(Font.DIALOG,Font.PLAIN,18));
lb.setAlignment(Label.CENTER);
this.add(lb,BorderLayout.CENTER);
btn=new Button(" OK ");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
md.setVisible(false);
}
});
Panel p2=new Panel();
p2.add(btn);
this.add(p2,BorderLayout.SOUTH);
this.setSize(340,140);
}
Point scenter(Dimension fsz) {
Dimension screensize=Toolkit.getDefaultToolkit().getScreenSize();
int x=(screensize.width-fsz.width)/2;
int y=(screensize.height-fsz.height)/2;
Point pos=new Point(x,y);
return pos;
}
void visible() {
Point cpos=scenter(md.getSize());
cpos.y-=40;
md.setLocation(cpos);
md.setVisible(true);
}
}// MsgBox
class TimeBox extends MsgBox {
private static final long serialVersionUID = 1L;
Label tm;
public TimeBox(Frame own, String message) {
super(own, message);
this.setTitle("The Time");
tm=new Label();
tm.setFont(new Font(Font.MONOSPACED,Font.BOLD,24));
tm.setForeground(Color.BLUE);
tm.setAlignment(Label.CENTER);
this.add(tm,BorderLayout.NORTH);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
f.setExtendedState(Frame.NORMAL);
}
});
}
void visibletime(){
Calendar cc=new GregorianCalendar();
int hh=cc.get(Calendar.HOUR_OF_DAY);
int mm=cc.get(Calendar.MINUTE);
tm.setText(String.format("%02d:%02d", hh,mm));
visible();
}
}
class TimerProc extends TimerTask {
@Override
public void run() {
timer=null;
startbtn.setLabel(" Start ");
tmsg.visibletime();
}
}
public static void main(String[] args) {
new VTimer5();
}
}
これで一応完成としても良いでしょうか?
ご意見等はメールフォームからお気軽にお寄せください。
この記事へのコメントはこちら