- PR -

アラーム機能付タイマーを複数個作りたいのですが。

1
投票結果総投票数:7
Windows 7 100.00%
  • 投票は恣意的に行われます。統計的な調査と異なり、投票データの正確性や標本の代表性は保証されません。
  • 投票結果の正当性や公平性について、@ITは一切保証も関与もいたしません。
投稿者投稿内容
amap
会議室デビュー日: 2004/05/09
投稿数: 17
投稿日時: 2004-05-09 18:15
アマチュアです。
初めて投稿します。
java SWTを使用して、
上記の理由で、下記の用に書いたのですがうまくいきません。
対策についてご教示頂ければ幸いです。
Timerクラス、ScheduleメソッドやTimerTaskクラスも利用したのですがうまくいかず、
困ってしまいました。

/*
* Alarm05.java
* 作成日: 2004/05/05 10:12:27
* 作成者: amap
*/

import java.text.DateFormat;
import java.text.Format;
import java.util.Date;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;


public class Alarm05 {
/*インスタンス変数*/
public static Display display;
public static Shell mainShell;
public static Shell[] subShell;
public static GridLayout gridLayout;
public static GridData gridData;
public static Text mtext1;
public Text mtext2;
final static int Max = 2;

    /*タイマー複数個作成メソッド*/
public static void makeSubShell (int n, Text txt) {
int i;
for(i=0;i<n;i++) {
subShell[i] = new Shell(mainShell);
subShell[i].setBounds(20+100*i,20+90*i,200,100);
subShell[i].setText("サブウィンドウ" + (i+1));
subShell[i].setLayout(gridLayout);
mtext1 = new Text(subShell[i],SWT.BORDER + SWT.H_SCROLL + SWT.V_SCROLL);
mtext1.setLayoutData(gridData);
redraw_mtext1();
txt = new Text(subShell[i],SWT.BORDER + SWT.H_SCROLL + SWT.V_SCROLL);
subShell[i].pack();
subShell[i].open();
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
      e.printStackTrace();
  }
     }
     }

    /*コンストラクタ*/
Alarm05() {
         display = new Display();
mainShell = new Shell(display,SWT.DIALOG_TRIM);
mainShell.setText("メインフレーム 現在の時間");
mainShell.setBounds(400,5,200,100);
mainShell.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
mainShell.open();

Rectangle rect1 = display.getBounds();
Rectangle rect2 = display.getClientArea();
/*ウィンドウの表示様式設定。*/
gridLayout = new GridLayout();
gridLayout.numColumns = 2;
gridLayout.marginHeight = 5;
gridLayout.marginWidth = 5;

gridData = null;
gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.widthHint = 200;

int i;
subShell = new Shell[Max];
makeSubShell (Max, mtext2);

UpdateAlarm05 uA05 = new UpdateAlarm05();
display.asyncExec(uA05);
}
    
    /*現在日付時刻取得*/
private static String getNow() {
Date now = new Date();
Format fmt = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.LONG);
Format fmt_date = DateFormat.getDateInstance(DateFormat.FULL);
String day1 = fmt_date.format(now);
Format fmt_time = DateFormat.getTimeInstance(DateFormat.LONG);
String hourmin2 = fmt_time.format(now);
String hourmin1 = hourmin2.substring(0,8);
String s = "本日は、"+ day1 + "です。\\n時刻は、"+ hourmin1 + "です。";//ラインセパレーターに\\nを使用しています。
mtext1.setText(s);
return s;
}

         /*現在日付時刻表示を更新*/
public static void redraw_mtext1(){
mtext1.setText(getNow());
}

    /*アラームタイマウィンドウを順に表示*/
class UpdateAlarm05 implements Runnable {
public void run() {
while(true) {
redraw_mtext1();
subShell[1].update();
subShell[1].pack();
subShell[1].open();
}
}
}

    /*メイン関数*/
public static void main(String[] args) {
Alarm05 a = new Alarm05();
}
}
amap
会議室デビュー日: 2004/05/09
投稿数: 17
投稿日時: 2004-05-09 18:53
amapです。
以前、そう、30年くらい前になりますか。
NHK教育テレビでコンピュータプログラミング講座とかいう番組がありました。
その中の一つに、フォートランで家電製品の電源を順にいれて家事を行ってみようというものがあり、興味深く見ておりました。
その時の印象が今でも強く残っていて、おじさんなんですが、
趣味のプログラミングを始めました。
作ろうとしたアプリケーションは、現在日付日時を表示するテキストフィールドと
アラーム時刻を設定できるテキストフィールドを持つようにします。
ボタンでアラーム時刻を設定し、その時刻になるとアラームを出力します。
このウィンドウは、上限までは、いくつも作成できるようにします。
個々の目的で何個もアラーム時刻を設定し、そのアラームを鳴らしてみたいと思いました。
夢なのですが、USBなどのデバイスで複数個のリレー等を制御し、操作できればいいなと思っております。
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2004-05-10 13:52
こんにちは、Wataです。
java.util.Timerの使い方は、以下のようになります。
コード:
import java.text.DateFormat;
import java.util.*;

public class TimerSample {
   public static void main(String[] args) {
      Timer timer = new Timer();
      timer.schedule(new TimerTask() {
         public void run() {
            System.out.println(
               DateFormat.getDateTimeInstance().format(
                  new Date()));
         }
      }, 0, 1000);
   }
}



ちなみに、SWTで現在時刻を(一度だけ)表示するには以下のようにします。
コード:
import java.text.DateFormat;
import java.util.Date;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.*;

public class ShellSample {
   private final Shell shell;

   public static void main(String[] args) {
      Display display = new Display();
      ShellSample main = new ShellSample(display);
      Shell shell = main.open();

      // イベントディスパッチ処理のため、ループさせる。
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
   public ShellSample(Display display) {
      shell = new Shell(display, SWT.TITLE | SWT.CLOSE);
      shell.setText("SimpleShell");
      shell.setLayout(new FillLayout());
      Label label = new Label(shell, SWT.BORDER);
      label.setText(DateFormat.getDateTimeInstance().format(new Date()));
   }
   private Shell open() {
      shell.pack();
      shell.open();
      return shell;
   }
}


これらを組み合わせて頑張ってみてください。
amap
会議室デビュー日: 2004/05/09
投稿数: 17
投稿日時: 2004-05-11 22:57
Wataさん、
アドバイス誠に有難うございます。
基本に戻って、こつこつと作っていきます。

反省:
Javaのマルチスレッドについて調べなおし、
また、クラス間やスレッド間の通信について
記憶クラス(スコープ)等を勉強しなおし
デバッグを繰り返し、期待通りのプログラムを
作っていきたいと思います。
amap
会議室デビュー日: 2004/05/09
投稿数: 17
投稿日時: 2004-05-16 21:01
amapです。
日曜プログラマーです。
パソコンもMacの時は独身で金銭に余裕もあり、コードウォリアーを使い、VAIOノート(CPU:266MHz、Windows98SE )でVisual C++6.0に換え、ADSLを導入してEclipseとなりました。

今は自作パソコンでCPU:2.6GHzの中古Celeronに512MBメモリー、Windows XPで快適になりましたが、Visual C++6.0がインストールできなくなり、C#に換えるのもコストもかかりEclipseならば、マルチプラットフォームで、(実は、LinuxのFedora Core 1では、Eclipse2.1.3-gtkを使っています。)インターネットに強く、Eclipseに統一しました。

Visual C++では、MDI( Multi Document Interface )という仕組みがあって、親ウィンドウの中に子ウィンドウを複数個表示できました。
 また、親ウィンドウから、複数個あるうちの各々の子ウィンドウの要素にアクセスするといったクラス間通信を行うには、(1)子クラスにポインタを保持する外部変数を用意して、子クラスのコンストラクタで、このポインタに、自分自身のポインタを設定する。(2)親クラスでは、そのポインタを外部(extern)宣言して、このポインタを使う。事ができたのですが。

 そこで、Java-Eclipse( SWT )では、どのようにしているのでしょうか? 親ウィンドウにも、子ウィンドウにもスレッドをインスタンスとして持たせ、各スレッドでイベント待ち状態にしておくのでしょうか。プロではなく、我流でしか勉強してないため基本的な事が理解できてないので論理的な矛盾が多々あるかもしれません。御教授を御願いいたします。

/*
* 2004/05/15 11:17:37
* Alarm01-v2.1.3
* amap
*/

//_/_/ Alarm01.java //_/_/
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Alarm01 {
/*インスタンス変数*/
private static Display display;//描画用でアプリに一つ。
private static int MAX = 3;
private static Shell mainShell;//ユーザーへの情報提示用。アプリに一つ
private static MainMyThread mainMyThread;
private static MyShell[] subShells;//個別用でアプリに複数。

/*コンストラクタ*/
Alarm01() {
//今は保留。
}

/*メイン関数*/
public static void main(String args[]) {
Alarm01 a = new Alarm01();
display = new Display();
mainShell = new Shell(display);
mainShell.setText("メインウィンドウ");
mainShell.setBounds(350,20,200,100);
/*子ウィンドウの作成*/
subShells = new MyShell[MAX];
a.makeSubShellMax();

mainMyThread = new MainMyThread(mainShell);
/*メインウィンドウ待期のループ*/
a.mainShellClose();
}

/*プライベートメソッド*/
private void mainShellClose() {
mainShell.open();
//メインウィンドウのクローズボタンが押されたら、表示終了。
while(!mainShell.isDisposed()) {
display.readAndDispatch();
display.sleep();
}
display.dispose();
}
private void makeSubShellMax(){
//子ウィンドウを最大個数作る。
int i;
for(i=0;i<MAX;i++){
subShells[i] = new MyShell(mainShell);
}
}
}

//_/_/ MyShell.java //_/_/
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class MyShell extends Shell implements Runnable {
public Shell shell;
public MyShell() {
shell = this.getShell();
}
//MyShellでは、親shellにmainShellを持つよう引数に指定する事を想定。
     public MyShell(Shell s) {
shell = new Shell(s);
}

    //runの最中はモニターのロックを一旦かけて、
    //wait(将来コメントを取って有効にする予定)でロックをはずして
    //他の子ウィンドウオブジェクトからのnotifyAllを待つ仕様。
public synchronized void run() {
System.out.println("MyShellのrun内");
setBounds(20,20,200,100);
setText("サブウィンドウ");
open();
             //try-wait(1000);追加処理;-catchブロック
//例外処理;
/*子ウィンドウのクローズボタンが押されたら、終了。*/
while(!shell.isDisposed()) {
Display disp = shell.getDisplay();
disp.readAndDispatch();
}
             //子ウィンドウ破棄。(旨く作動するか不明。)
shell.dispose();
notifyAll();
}

}

Consoleに下記の様に表示されました。
org.eclipse.swt.SWTException: Subclassing not allowed
at org.eclipse.swt.SWT.error(SWT.java:2330)
at org.eclipse.swt.SWT.error(SWT.java:2260)
at org.eclipse.swt.widgets.Widget.error(Widget.java:385)
at org.eclipse.swt.widgets.Decorations.checkSubclass(Decorations.java:249)
at org.eclipse.swt.widgets.Shell.<init>(Shell.java:242)
at org.eclipse.swt.widgets.Shell.<init>(Shell.java:237)
at org.eclipse.swt.widgets.Shell.<init>(Shell.java:190)
at org.eclipse.swt.widgets.Shell.<init>(Shell.java:128)
at MyShell.<init>(MyShell.java:9)
at Alarm01.makeSubShellMax(Alarm01.java:52)
at Alarm01.main(Alarm01.java:31)
Exception in thread "main"

デバッグしてみると、
MyShell(Shell).<init>(Display, Shell, int, int) line: 242から、
次のDecolations.classの下記メソッドに入ったところで、
protected void checkSubclass () {
if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
Expressionsビューでは、
"isValidSubclass" <error(s) during the evaluation>となり、
Variablesビューでは、
this= MyShell (id=21)
MyShell {*Disposed*}
となり、SWT.classのpublic static void error (int code, Throwable throwable)メソッドで、
/* SWT Errors (non-fatal) */ の ERROR_THREAD_INVALID_ACCESS (int) 22が帰ってきます。
amap
会議室デビュー日: 2004/05/09
投稿数: 17
投稿日時: 2004-05-16 22:48
amapです。

追伸、インスタンス変数のMainMyThreadクラスは、
下記の様に実態の無いものです。run関数のコメントアウトした部分は、
/*メインウィンドウ待期のループ*/ 用に考えたものでしたが、
メイン関数(メインスレッド)で、mainShellClose();と同じものです。
コメントアウトしたことを忘れてしまい、投稿文に記載しませんでした。
すいません。

//_/_/ MainMyThread.java //_/_/
import org.eclipse.swt.widgets.Shell;

public class MainMyThread extends Thread {
private Shell shellForSave;
MainMyThread() {
shellForSave = null;
}
MainMyThread(Shell shell) {
shellForSave = shell;
}
public synchronized void run() {
/*
shellForSave.setBounds(400,20,200,100);
shellForSave.setText("メインウィンドウ");
for (;;) {
try {
wait(5000);
} catch (InterruptedException e) {
}
shellForSave.open();
}

while(!shellForSave.isDisposed()) {
shellForSave.getDisplay().readAndDispatch();
shellForSave.getDisplay().sleep();
}
shellForSave.dispose();
}
*/
}
}
amap
会議室デビュー日: 2004/05/09
投稿数: 17
投稿日時: 2004-05-17 23:44
amapです。
Java初心者です。
ヒデミさんの
「件名:Strutsを基礎から勉強したいです。関連HP教えてもらいますか。」の質問に対する
カーニーさんのコメントを読ませて頂いたところ、

http://www.techscore.com/tech/Java/main.html
の御指摘があり、

その中の細目に、
16章 内部フレームとデスクトップペイン
16.1.javax.swing.JInternalFrame, javax.swing.JDesktopPane
というJavaの講義実習が記載されていました。

説明文は、
「JInternalFrame」と「JDesktopPane」はJavaで、マルチドキュメントインターフェースを提供するコンポーネントです。「JDesktopPane」が仮想デスクトップコンポーネントで、「JInternalFrame」が内部フレームの役割を果たします。
多いに求めるものと関連があります。VisualC++6.0でのMDI(Multi Document Interface)が可能となる期待でいっぱいです。SWTでのやり方も調べてみます。
勉強になります。ヒデミさん、カーニーさん、各スレッドの皆さん有難うございます。
1

スキルアップ/キャリアアップ(JOB@IT)