2011-01-28 2 views
1

) 내 질문에 더 좋은 방법을 찾아야합니다. 기본적으로 웹 페이지에서 정보를 가져 와서 화면 전체에 멋지게 표시하는 프로그램을 만들었습니다.작은 방법으로 주 방법 대기 (

사용자가 프로그램을 닫으면 실제로 프로그램이 숨겨집니다.

또 다른 방법으로 정보가 계속 업데이트되는지 확인합니다. 불행히도 문제는 인스턴트 메시지를 보내는 것이 빠르고, 단지 40 초마다 정보를 확인하기를 원합니다.

내가 시도한 것은 메서드 자체와 프로그램의 메인에 대기 (1000,1000)를 삽입하는 것이 었습니다. 그러나 이들 모두는 IllegalMonitorStateException의 원인이됩니다.

스레드를 올바르게 대기시키는 올바른 방법입니까? 또는 더 좋은 방법이 있습니까? 참고 : 내가 가지고있는 유일한 스레드는 기본입니다. UPDATES

에 대한

주요

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와 관련된 모든 호출은 스윙 이벤트 발송 스레드 (EDT)에서 발생해야합니다. SwingUtilities.invokeLater를 보거나 웹 검색을 통해 자세한 내용을 확인하십시오. 비록 당신이 단지 하나의 스레드를 가지고있는 것처럼 보일지라도 EDT는 GUI를 생성함으로써 시작될 때 실행 중이다. ==를 사용하여 문자열을 비교하고 대신 string.equals (otherString)을 사용하십시오. –

+0

스윙을 사용하므로 메인이 유일한 스레드가 아닙니다. 최소한 이벤트 디스패치 스레드가 있습니다 –

답변

0
  1. 나는 당신이 JFrame의에 대기()를 호출 할 수 없습니다 생각하지만, 나는 확실하지 않다 .
  2. snychronized-block 내에서 wait()으로 전화해야합니다. (아래 예)
  3. Thread.sleep(1000l)
  4. 그것이 스레드에서 실행되는 경우, 사용,하지만 당신은 업데이트를 확인 스레드를 만드는 경우, 클래스 Timer
  5. 그것은 더 나은 디자인이 될 것입니다 찾을 수 있습니다. 표시 할 새 날짜에 대한 일종의 이벤트 리스너를 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 가지 옵션을 설명에 포함 시켰습니다. 생성자에서 Timer를 올바르게 사용하는 방법을 볼 수도 있습니다.마지막으로, 전체 코드가 없기 때문에 시뮬레이션을 위해 무언가를 조합해야했습니다.

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는 웹 페이지에서 가져온 후에 문자열을 반환합니다. – OVERTONE

+0

실제로 여기에서 무슨 일이 일어나는지보기가 쉽습니다. 많이 고마워. 왜 수학을 가지고 있는지 궁금 해서요. 거기에 랜덤. 그리고 나는 이벤트 쫓기 물건으로 위대한 그 같은 멍청한 녀석이되어 사과드립니다. 기본적으로 : engineersUpdate는 http 웹 페이지에서 문자열을 반환합니다. 혼란을 일으킬 수있는 많은 코드입니다. 업데이트 확인은 getEngineersupdate를 실행하고 최근에 업데이트되었는지 여부를 확인합니다. 업데이트 된 경우 페이지 전체에 깔끔한 그래픽이 메시지와 함께 표시됩니다. 이 작업을 수행 할 수있는 액션 수신기가있는 프레임과 패널을 만들었습니다. – OVERTONE

+1

지식 부족으로 사과하지 마십시오. math.random()은 코드에 대한 "임의"테스트를 작성합니다. 이벤트 주도형으로 아키텍처를 변경할 수는 없다는 점은 중요합니다 (웹 사이트를 사용하고 있기 때문에). – SEK

관련 문제