2011-01-28 5 views
1

私は本当に自分の質問を語る良い方法を見つける必要があります。 基本的には、Webページから情報を取り出し、画面全体にうまく表示するプログラムを作成しました。メインメソッドを小さなメソッドで待つようにする(java)

ユーザーがプログラムを閉じると、実際にはプログラムが閉じられます。

また、情報が更新されているかどうかを定期的にチェックする別の方法もあります。 残念ながら、私が問題にしているのは、それが速くループするということです。私はそれが40秒ごとに情報をチェックしたいだけです。

私が試したのは、メソッド自体とプログラムのメインに待機(1000,1000)を挿入したことです。どちらもIllegalMonitorStateExceptionの原因となります。

スレッドを正しく待機させる正しい方法ですか?それとも良い方法がありますか? 注:私が持っている唯一のスレッドはメインです。 UPDATES

FOR

MAIN

class Marquee 
{ 
public static void main(String[] args) throws InterruptedException 
{ 
    MyFrame frame = new MyFrame(); 
    frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); 
    frame.setVisible(true); 
    frame.setAlwaysOnTop(true); 
    frame.setBackground(Color.BLACK); 
    frame.setResizable(true); 


    while(true) 
    { 
     // this doesnt work 
     frame.wait(1000,1000); 
     frame.notifyAll(); 

     frame.checkForNewUpdate(); 
     System.out.println(" ____________________________next line _______________________________"); 

    } 
} 
} 

CHECK

public String[] checkForNewUpdate() 
{ 
    //setVisible(true); 
    String tempUpdate = getEngineersUpdate(); 

    if (latestUpdate[0] != tempUpdate) 
    { 
     // do nothign 
     setVisible(false); 
    } 
    else if(latestUpdate[0]==tempUpdate) 
    { 
     latestUpdate[0] = tempUpdate; 
     //show the page again 
     setVisible(true); 
    } 
    else if(latestUpdate[0]!= "NULL") 
    { 
     // do nothing 
     //latestUpdate[0] = tempUpdate; 
    } 
    else 
    { 
     latestUpdate[0] = tempUpdate; 
    } 
    return latestUpdate; 
} 

1:時間のギャップを作るために他の方法があります:私はこの例外

2を取得するために、間違って何をしていますメソッド内で

3:これらのメソッドを別のスレッドに入れなければならないのですか?リクエストによって何


// my constructor which I failed to mention has a timer in it. only i dont know hwo to use it 

class MyFrame extends JFrame implements ActionListener 
{ 
private ActionListener listener; 
private Timer t1; 
private String [] latestUpdate = new String[1]; 


public MyFrame() 
{ 
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();// gets the maximum size of the screen 
    setSize(d.width,(d.height/100)*10);//sets it to max. need to change this 

    // this shit find the max size of screen and puts it bottom left 
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
    GraphicsDevice defaultScreen = ge.getDefaultScreenDevice(); 
    Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds(); 
    int x = (int)rect.getMinX(); 
    int y = (int)rect.getMaxY()-getHeight(); 
    setLocation(x,y-30); 
    setTitle("ALERT::OUTAGE"); 
    MyPanel panel = new MyPanel(); 
    add(panel); 
    listener = this; 
    t1 = new Timer(50,listener); 
    t1.start(); 
} 

を言っていないしてください、ここでgetEngineersUpdate()である

public String getEngineersUpdate() //gets data from page and sets it to string. 
{ 
    String update = "blank"; 

    final WebClient webClient = new WebClient(); 
    webClient.setJavaScriptEnabled(false);// javascript causes some serious problems. 
    webClient.setCssEnabled(false); 
    String forChecking; 

    HtmlPage page; 

    try 
    { 

     URL outageURL = new URL("file:\\C:\\Users\\0vertone\\Desktop\\version control\\OUTAGE\\Outages.html"); //local drive at home 


     page = webClient.getPage(outageURL); 


     //All this crap can be gone if we just give the table an id 
     Object[] dates = page.getByXPath("//span[@id='date']/text()").toArray(); 
     Object[] sites = page.getByXPath("//span[@id='site']/text()").toArray(); 
     Object[] issues = page.getByXPath("//span[@id='issue']/text()").toArray(); 
     System.out.println("" + dates[0].toString()); 
     System.out.println("" + sites[0].toString()); 
     System.out.println("" + issues[0].toString()); 

     update = (dates[0].toString() + " " + sites[0].toString() + " " +issues[0].toString()); 
     forChecking = dates[0].toString(); 




     /**some examples of the getCellAt() method*/ 
     //update = table.getCellAt(0,0).asText(); // This returns DATE/Time 
     //update = table.getCellAt(1,0).asText(); // This return the actual date 
     //update = table.getCellAt(0,1).asText(); // This returns, SITE/Sector 
     //update = table.getCellAt(1,1).asText(); // This returns the actual site issue 

    } 
    catch (FailingHttpStatusCodeException a) 
    { 
    System.out.println("Failing HTTP Status Execution"); 
    a.printStackTrace(); 
    } 
    catch (MalformedURLException b) 
    { 
    System.out.println("Malformed URL"); 
    b.printStackTrace(); 
    } 
    catch (IOException c) 
    { 
    System.out.println("IO PROBLEMS!"); 
    c.printStackTrace(); 
    } 
webClient.closeAllWindows(); 
return update; 
} 
+2

GUIに関連するすべてのコールは、Swingイベントディスパッチスレッド(EDT)で発生する必要があります。 SwingUtilities.invokeLaterを見たり、詳細をWeb検索したりしてください。あなたは1つのスレッドだけを持っているように見えますが、EDTはGUIを作成することによって起動されているので、実行しています。また、==を使用して文字列を比較し、代わりにstring.equals(otherString)を使用します。 –

+0

あなたはスイングを使用しているので、メインはあなたが持っている唯一のスレッドではありません。少なくともイベントディスパッチスレッドがあります –

答えて

0
  1. 私はあなたのJFrameにwait()を呼び出すことはできませんと思うが、私はわかりません。
  2. あなたはwait()を呼び出す必要があります。 (下記の例)
  3. Thread.sleep(1000l)は、それがスレッドで実行されている場合、使用していますが、更新情報をチェックするスレッドを作成した場合それは、はるかに良いデザインだろうクラスのTimer
  4. を見ることができます。表示する新しい日付について何らかのイベントリスナーでGUI(JFrame)に通知することができます。

TimerCallableをご覧ください。

+1

wait()は任意のオブジェクトに対して機能しますが、wait()へのすべての呼び出しは同期ブロック内で行われなければなりません:synchronized(object){object.wait(); } –

+0

私はちょうどそこに入れたMyFrameのコンストラクタでタイマーを実際に定義しました。しかし、私はそれを使用する方法を知りませんでした。私はまだいない。 – OVERTONE

0

別のスレッドを作成する必要があります。このスレッドからcheckforNewUpdateメソッドを呼び出す必要があります。また、checkforNewUpdateメソッド内でUIを更新するためにSwingUtilities.invokeLaterメソッドを使用することも忘れないでください。ここにコードの一部があります。

public class Marque   { 

    private JFrame frame; 
    class CheckForUpdate implements Runnable { 

     public void run() { 
      while(true) { 
       checkForNewUpdate(); 
       try { 
        Thread.sleep(40000); 
       } catch (InterruptedException e1) { 
        e1.printStackTrace(); 
        throw new RuntimeException(e1); 
       }      } 

     } 

     public String[] checkForNewUpdate()  { 
      //your code 
      // user interface interaction code 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        frame.setVisible(true); 
       } 
      }); 

     } 
    } 

    public Marque() { 
     frame = new JFrame(); 
     //....frame related code 
     new Thread(new CheckForUpdate()).start(); 


    } 
    public static void main(String[] arg) { 
     Marque marque = new Marque(); 


    } 
+0

これを私のコードと組み合わせようとするのは難しいでしょう。いくつかの部分については、私はあなたのやり方を理解しています。私は他の方法もありますので、私は病気だけでそれを回避する必要がありますので、私も仕事をしようとしています。 – OVERTONE

1

コードを意図したとおりに変更するように変更しました。私はgetEngineersUpdate()が何をしているのかはっきりしていないので、それがうまくいくかどうかは確かではありませんが、私はあなたにスタートを与えました。私はそれを扱う方法の2つのオプションをコメントに説明と共に含めました。コンストラクタ内でタイマーを適切に使用する方法も見ることができます。最後に、私はあなたの完全なコードを持っていないので、私はそれをシミュレートするために一緒にリグを作り直さなければならなかった。

class Marquee { 
    public static void main(String[] args) throws InterruptedException { 
     MyFrame frame = new MyFrame(); 
     frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); 
     frame.setVisible(true); 
     frame.setAlwaysOnTop(true); 
     frame.setBackground(Color.BLACK); 
     frame.setResizable(true); 
    } 
} 



class MyFrame extends JFrame { 
    private String [] latestUpdate = new String[1]; 
    private static final int DISPLAY_TIME = 3000; 
    private Timer displayTimer; 

    /* 
    * Option #1: 
    * Ideally, you'd have the thread that generates the "Engineers Update" messages call this 
    * method. If you can't make this event based, then you should use option #2 
    */ 
    public void newUpdate(String message) { 
     setVisible(true); 
     // change this to whatever you need to. 
     text.setText(message); 
     displayTimer.restart(); 
    } 

    // I used this to test it 
    private JTextField text; 

    public MyFrame() { 
     // gets the maximum size of the screen 
     Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); 
     //sets it to max. need to change this 
     setSize(d.width, (d.height/100) * 10); 

     // this shit find the max size of screen and puts it bottom left 
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice defaultScreen = ge.getDefaultScreenDevice(); 
     Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds(); 
     int x = (int) rect.getMinX(); 
     int y = (int) rect.getMaxY() - getHeight(); 
     setLocation(x, y - 30); 
     setTitle("ALERT::OUTAGE"); 

     //MyPanel panel = new MyPanel(); 
     //add(panel); 
     text = new JTextField("Initial Text"); 
     add(text); 

     // this creates a timer that when it goes off, will hide the frame 
     displayTimer = new Timer(DISPLAY_TIME, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       setVisible(false); 
      } 
     }); 
     // sets the timer not to repeat 
     displayTimer.setRepeats(false); 

     //This code is for option #2: 
     updateTimer = new Timer(UPDATE_INTERVAL, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       checkForNewUpdate(); 
      } 
     }); 
     updateTimer.start(); 
    } 

    // This is for option #2 
    private static final int UPDATE_INTERVAL = 1000; 
    private Timer updateTimer; 

    /* 
    * Option #2: 
    * Not ideal, but this should work. 
    */ 
    public String[] checkForNewUpdate() { 
     // I don't know how getEngineersUpdate() works 
     // which would have made it much easier to help you. 
     String tempUpdate = getEngineersUpdate(); 

     // String comparison doesn't work like this in java. 
     // you also had a sleeping NullPointerException here 
     if (!tempUpdate.equals(latestUpdate[0])) { 
      // this is when you have a new update, correct? 
      newUpdate(tempUpdate); 
      latestUpdate[0] = tempUpdate; 
     } else if (tempUpdate.equals(latestUpdate[0])) { 
      // it's the same update as last time, so do nothing 
     } else if (tempUpdate.equals("NULL")) { 
      // You need to handle this according to what getEngineersUpdate() does 
     } 
     return latestUpdate; 
    } 

    // This code is rigged to show how it would work 
    private static int i = 0; 
    private String getEngineersUpdate() { 
     // 1 in 6 chance of returning "NULL" 
     if (Math.random() * 6 - 1 < 0) 
      return "NULL"; 

     // probability of 1 in 4 of generating a new update 
     if(Math.random() * 4 - 1 < 0) 
      return "UPDATE #"+i++; 
     else 
      return "UPDATE #"+i; 
    } 
} 
+0

getEngineersUpdateは、Webページから取得した後に文字列を返します。 – OVERTONE

+0

実際にここで何が起こっているのか分かりやすくなっています。それに感謝します。なぜあなたはmath.randomを持っているのか興味があります。イベント駆動型のものではそれほど素晴らしいことではないことについて、私は謝罪します。基本的には:get engineersUpdateは、混乱の原因となる多くのコードであるhttpウェブページから文字列を返します。更新を確認してgetEngineersupdateを実行し、最近更新されたかどうかをチェックします。更新されていれば、ページ全体にきれいなグラフィックがメッセージとともに表示されます。私はこれを行うためにアクションリスナーを持つフレームとパネルを作成しました – OVERTONE

+1

知識が不足していることをお詫び申し上げます。 math.random()はそこにコードの "ランダムな"テストを作成します。イベントドリブンになるようにアーキテクチャを変更することはできません(ウェブサイトから引っ張っているため)。 – SEK

関連する問題