2014-02-11 6 views
0

좋아, 내가 작업중인 프로그램에 대한 경고 메시지로 사용할 간단한 작은 오버레이 창을 만들기 위해 몇 가지 코드를 설치했습니다. 모든 것이 처음부터 끝까지 잘 작동하지만 다시 실행하려고하면 디버거 또는 작업 관리자를 통해 종료하도록 모든 것을 고정시킵니다. 나는 내가 뭔가 잘못하고있는 것을 안다. 자바에 대한 제한된 경험으로 인해 나는 무엇을 확신 할 수 없다. 나는 그것이 그릴 펄스 있도록 설정을했습니다 코드 아래Java Window pulse-fader가 한 번 작동하면 깨집니다.

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에 대한 약간의 초보자입니다. 그래서 내가 잘못하고/비능률적으로하고있는 것을 보게되면, 올바르게 지적 할 수 있도록 자유롭게 지적하십시오.

편집 :

나는이 문제가 지금 JWindow의 함께 생각하기 시작하고있다. 경고를 표시하는 다른 방법에 대한 일부 다른 코드를 설정하고이 시간을 고정하지 않지만 의도 한대로 작동하지 않습니다. 그냥 깜박이는 창 문제 같은

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

생각이 떠올랐다. 자바의 자동 가비지 콜렉션을 재정의하는 이상한 방법 때문이 아닌가? 나는 새로운 PulseWindow 클래스를 생성/초기화함으로써 그러한 문제를 방지하려고 노력했지만, 여전히 동결 문제가 발생합니다. 또한, 클래스가 다시 초기화 되더라도'startPulsing()'이 호출 된 두 번째에만 고정이 발생한다는 것을 알았습니다. 처음에는 완전히 정상적으로 작동하지만 두 번째 호출은 정지 상태입니다. – DGolberg

+0

조금 더 주위를 어지럽히고 난 후에, 나는 그것이 SwingWorker 쓰레드보다는 Runnables를 사용하는 것이 원인이라고 생각한다. 이 프로그램은 UI 작업을하고 UI에는 시스템 트레이 아이콘이 포함되어 있습니다. 나는 전체 코드를 게시 하겠지만,이 시간에는 너무 큽니다. 어쨌든 재미있는 일을 좀하고 있습니다. 나중에 발견 한 내용을 게시하고, 여전히 문제에 대한 도움이 필요한지 여부를 알려 드리겠습니다. – DGolberg

답변

0

편집 2 :

그리고 다시 바보 같은 느낌 ... 나는 문제가 (실제로 몇 시간 전에 그것을 발견하지만,이 업데이트 깜빡 ...) 발견했다. 문제는 내가 runnable만을 사용하고 new Thread() 오브젝트 안에 배치하지 않는다는 것이 었습니다. 어떤 이유에서 나는 runnable 객체가 자신의 새 스레드를 만들었다 고 생각했지만, 일단 실수를 알게되면 쉽게 해결할 수있었습니다. 물론 나는 아직도 자바 학습에 갈 길이 방법을 ...이


편집 :

좋아, 지금은 당신이 그것을 실행하려고하면 분명히 여전히 나누기 ... 짜증 해요 어떤 종류의 액션 리스너로부터. 아래에서 더 원래의 대답에 표시된 PulseWindow 클래스로 호출 PulseAlert 클래스 (아래)의 내 최신 버전의 아래

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(); 

어떤 종류 등의 액션 청취자에 배치 될 때까지 위의 코드는 완벽하게 작동 다음 runAlert() 방법은 액션 리스너에서 호출되면 이전에했던 것처럼

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

, 모든 것이 정지 . 그때까지는 완벽하게 실행됩니다. 이 문제의 원인은 무엇입니까? 이 버그는 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