2014-02-11 69 views
0

好吧,我已經設置了一些代碼來創建一個簡單的小覆蓋窗口,用作我正在處理的程序的警報消息。一切運行良好,但試圖再次運行它,它凍結了整個事情,迫使我通過調試器或任務管理器終止它。由於我對Java的經驗有限,我知道我做錯了什麼,我只是不確定是什麼。Java窗口脈衝推子工作一次然後休息

下面是我用它來設置我的窗口,並將其放置在右下角任務欄上面的代碼:

private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
public static JWindow alertWindow() { 
    JWindow newWin = new JWindow(); 

    JPanel panel = new JPanel(); 

    BufferedImage img = null; 
    try { 
     img = ImageIO.read(Main.class.getResource("/images/test.jpg")); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    JLabel imgLbl = new JLabel(new ImageIcon(img)); 

    panel.add(imgLbl); 
    newWin.setContentPane(panel); 
    newWin.pack(); 

    Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(newWin.getGraphicsConfiguration()); 
    int taskBar = scnMax.bottom; 
    int x = screenSize.width - newWin.getWidth(); 
    int y = screenSize.height - taskBar - newWin.getHeight(); 
    newWin.setLocation(x,y); 
    newWin.setVisible(true); 

    final PulseWindow pulseWin = new PulseWindow(newWin); 
    pulseWin.getWindow().addMouseListener(new MouseListener() { 
     @Override 
     public void mouseClicked(MouseEvent click) { 
      if(SwingUtilities.isRightMouseButton(click)) { 
       pulseWin.stopPulsing(); 
       pulseWin.destroyPulse(); 
      } else { 
       System.out.println(pulseWin.isPulsing()); 
       if(pulseWin.isPulsing()) {pulseWin.stopPulsing();} 
       else {pulseWin.startPulse();} 
      } 
     } 
     @Override 
     public void mouseEntered(MouseEvent arg0) {} 
     @Override 
     public void mouseExited(MouseEvent arg0) {} 
     @Override 
     public void mousePressed(MouseEvent arg0) {} 
     @Override 
     public void mouseReleased(MouseEvent arg0) {} 
    }); 
    pulseWin.startPulsing(); 

    return newWin; 
} 

並在下面的代碼我設置,使之脈繪製用戶注意:

import javax.swing.JWindow; 

public class PulseWindow { 

private boolean pulse = true; 
private boolean doPulse = true; 
private Float floor = 0.50f; 
private JWindow win; 

public PulseWindow(JWindow win) { 
    this.win = win; 
} 

public void startPulsing() { 
    pulse = true; 
    boolean decreasing = true; 
    double inc2 = 0.03; 
    double current = win.getOpacity(); 

    while(pulse) { 
     if(doPulse) { 
      if(decreasing) { 
       current = current - inc2; 

       if((float) current <= floor) { 
        current = floor; 
        win.setOpacity((float) current); 
        decreasing = false; 
       } else { 
        win.setOpacity((float) current); 
       } 
      } else { 
       current = current + inc2; 

       if((float) current >= 1.0f) { 
        current = 1.0; 
        win.setOpacity((float) current); 
        decreasing = true; 
       } else { 
        win.setOpacity((float) current); 
       } 
      } 
     } else { 
      current = 1.0; 
      win.setOpacity(1.0f); 
      decreasing = true; 
     } 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    win.setOpacity(1.0f); 
} 

public void destroyPulse() { 
    pulse = false; 
    win.dispose(); 
} 

public boolean isPulsing() { return doPulse; } 
public void setFloor(float floor) { this.floor = floor; } 
public void stopPulsing() { doPulse = false; } 
public void startPulse() { doPulse = true; } 
public JWindow getWindow() { return win; } 
} 

反正,就像我提到的,它工作正常第一次使用,但只要你通過關閉窗口,單擊右鍵,然後嘗試後重新運行它(無論是通過調用startPulsing()方法或通過用新的JWindow完全重新初始化整個類再次調用alertWindow()),整個程序就凍結了。任何想法,爲什麼這是?

就像我說的,我仍然是Java的一個新手,所以如果你看到其他任何我做錯了/效率低下,那麼隨時指出它,所以我可以正確地做到這一點。

編輯:

我開始認爲這個問題是JWindows,現在。我爲其他代碼設置了不同的顯示警報的方法,雖然這次不凍結,但它不能按預期工作。

public class AlertWindow extends JWindow { 

private static Border compound = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createLoweredBevelBorder()); 
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 

public AlertWindow() {  
    JPanel panel = new JPanel(); 
     panel.setBorder(compound); 
     panel.setBackground(Color.RED); 

    JLabel imgLbl = new JLabel("Enter Alert Msg Here!"); 
     imgLbl.setFont(new Font(null,Font.BOLD,16)); 

    panel.add(imgLbl); 
    setContentPane(panel); 
    pack(); 


    this.addMouseListener(new MouseListener() { 
     @Override 
     public void mouseClicked(MouseEvent click) { 
      if(SwingUtilities.isLeftMouseButton(click)) { 
       scrollOff(); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       scrollOn(); 
      } 
     } 
     @Override 
     public void mouseEntered(MouseEvent arg0) {} 
     @Override 
     public void mouseExited(MouseEvent arg0) {} 
     @Override 
     public void mousePressed(MouseEvent arg0) {} 
     @Override 
     public void mouseReleased(MouseEvent arg0) {} 
    }); 
    scrollOn(); 
} 

public void scrollOn() { 
    Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration()); 
    int taskBar = scnMax.bottom; 
    int x = screenSize.width - getWidth(); 
    int yEnd = screenSize.height - taskBar - getHeight(); 
    int yStart = screenSize.height; 
    setLocation(x,yStart); 
    setVisible(true); 
    int current = yStart; 
    while(current > yEnd) { 
     current-=2; 
     System.out.println(current); 
     setLocation(x,current); 
     try { 
      Thread.sleep(30); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
public void scrollOff() { 
    int x = screenSize.width - getWidth(); 
    int yEnd = screenSize.height; 
    int yStart = this.getBounds().y; 
    setLocation(x,yStart); 
    int current = yStart; 
    while(current < yEnd) { 
     current+=2; 
     setLocation(x,current); 
     try { 
      Thread.sleep(30); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    setVisible(false); 
} 
} 

就像脈衝窗口的問題,它的工作原理是第一次,然後打破後續使用。在這種情況下,唯一中斷的是scrollOn()命令。它在不可見的情況下滾動,然後在到達目的地後變爲可見。該位置的控制檯輸出清楚地表明它正在移動,但在停止移動之前無法看到它。

+0

想到一個念頭;這可能不是由於我重寫Java的自動垃圾收集的一些奇怪的方式,可以嗎?我試圖通過創建/初始化一個新的'PulseWindow'類來防止這些問題,但我仍然收到凍結問題。另外,我注意到凍結只發生在第二次調用'startPulsing()'時,即使該類被重新初始化。它在第一次通過時完全正常,但第二次調用導致凍結。 – DGolberg

+0

經過了一番討論後,我相信這可能是由於我使用了Runnables而不是SwingWorker線程。該程序正在使用一個用戶界面,該用戶界面包含一個系統托盤圖標。我會發布完整的代碼,但在這個時候它太大了,無論如何,我有點樂於嘗試。我稍後會發布我的發現,如果我仍然需要任何幫助解決問題。 – DGolberg

回答

0

編輯2:

再換感覺愚蠢的...我發現這個問題(實際上發現它前一段時間,但忘了更新這...)。這個問題最終導致我只使用runnable,而不是將它放在一個new Thread()對象中。出於某種原因,我認爲可運行對象創建了自己的新線程,但是一旦我找出了我的錯誤,這是一個簡單的解決方法。很顯然,我還有很長的方式學習Java去...


編輯:

好了,現在我很惱火......如果你嘗試運行它顯然它仍然打破來自某種行爲傾聽者。我最近在PulseAlert類(下圖)在調用在原來的答案在下文進一步說明的PulseWindow類的版本:

public class PulseAlert { 

private static Border compound = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), BorderFactory.createLoweredBevelBorder()); 
private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 

public void runAlert() throws InterruptedException { 
    final PulseWindow pulseWin = new PulseWindow(alertWindow()); 
    pulseWin.getWindow().addMouseListener(new MouseListener() { 
     @Override 
     public void mouseClicked(MouseEvent click) { 
      if(SwingUtilities.isRightMouseButton(click)) { 
       pulseWin.stopPulsing(); 
       pulseWin.destroyPulse(); 
      } else if(SwingUtilities.isLeftMouseButton(click) && pulseWin.isPulsing()) { 
       pulseWin.stopPulsing(); 
      } else if(SwingUtilities.isLeftMouseButton(click) && !pulseWin.isPulsing()) { 
       pulseWin.startPulsing(); 
      } 
     } 
     @Override 
     public void mouseEntered(MouseEvent arg0) {} 
     @Override 
     public void mouseExited(MouseEvent arg0) {} 
     @Override 
     public void mousePressed(MouseEvent arg0) {} 
     @Override 
     public void mouseReleased(MouseEvent arg0) {} 
    }); 
    try { 
     pulseWin.startPulse(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    while(pulseWin.pulserActive()) { 
     Thread.sleep(100); 
    } 
    System.out.println("done with second SW"); 
} 

public static JWindow alertWindow() { 
    System.out.println("Start"); 
    JWindow newWin = new JWindow(); 

    JPanel panel = new JPanel(); 
     panel.setBorder(compound); 
     panel.setBackground(Color.RED); 

    JLabel imgLbl = new JLabel("Enter Alert Msg Here!"); 
     imgLbl.setFont(new Font(null,Font.BOLD,16)); 

    panel.add(imgLbl); 
    newWin.setContentPane(panel); 
    newWin.pack(); 

    Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(newWin.getGraphicsConfiguration()); 
    int taskBar = scnMax.bottom; 
    int x = screenSize.width - newWin.getWidth(); 
    int y = screenSize.height - taskBar - newWin.getHeight(); 
    newWin.setLocation(x,y); 
    newWin.setVisible(true); 

    return newWin; 
} 
} 

而下面是我如何可以調用警報窗口 - 反反覆覆,如果我喜歡,只要它不在動作監聽器之外。

PulseAlert alertPulse = new PulseAlert(); 
alertPulse.runAlert(); 

上面的代碼完美的作品,直到放入某種如一個動作偵聽器:

trayIcon.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     try { 
      alertPulse.runAlert(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
    } 
}); 

一旦runAlert()方法是從一個動作偵聽器叫,整個事情凍結像以前一樣。直到那時運行完全正常。任何想法是什麼造成這種情況?這是Java中的錯誤還是我做錯了什麼?


原來的答案:

好吧,我覺得很愚蠢,現在。我所要解決的問題是將startPulsing()內容放入新的可運行內容中,並且所有內容都可以正常工作,並且可以根據需要多次運行。

public void startPulsing() throws Exception { 
    new Runnable() { 
     @Override 
     public void run() { 
      pulse = true; 
      win.setVisible(true); 
      boolean decreasing = true; 
      double inc = 0.05; 
      double current = win.getOpacity(); 

      while(pulse) { 
       if(doPulse) { 
        if(decreasing) { 
         current = current - inc; 

         if((float) current <= floor) { 
          current = floor; 
          win.setOpacity((float) current); 
          decreasing = false; 
         } else { 
          win.setOpacity((float) current); 
         } 
        } else { 
         current = current + inc; 

         if((float) current >= 1.0f) { 
          current = 1.0; 
          win.setOpacity((float) current); 
          decreasing = true; 
         } else { 
          win.setOpacity((float) current); 
         } 
        } 
       } else { 
        current = 1.0; 
        win.setOpacity(1.0f); 
        decreasing = true; 
       } 
       try { 
        Thread.sleep(100); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      win.setOpacity(1.0f); 
     } 
    }.run(); 
} 
+0

你可以標記你的答案是正確的 - 你得到它的代表。 – Pedantic

+0

我會一次20小時的等待通行證......感謝提醒,但!編輯:或者有沒有辦法做到這一點,而不用等我不知道? – DGolberg

+0

還是不行,因爲它只適用於選擇的實例...呃 – DGolberg