2014-02-11 4 views
0

Хорошо, у меня есть код, который я настраиваю, чтобы создать простое небольшое оверлейное окно для использования в качестве предупреждающего сообщения для программы, над которой я работаю. Все работает отлично, первый раз пропустив, но, пытаясь снова запустить его, он замораживает все это, заставляя меня прекратить его через отладчик или диспетчер задач. Я знаю, что я делаю что-то неправильно, я просто не уверен, что из-за моего ограниченного опыта работы с 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, поэтому, если вы видите что-то еще, я делаю неправильно/неэффективно, не стесняйтесь указать на это, чтобы я мог сделать это правильно.

Edit:

Я начинаю думать, что проблема с 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

Edit 2:

И обратно к ощущению немой ... Я нашел этот вопрос (на самом деле нашел некоторое время назад, но забыл обновить это ...). Проблема закончилась тем, что я использовал только runnable и не помещал его в объект new Thread(). По какой-то причине я думал, что запущенные объекты создали свои собственные потоки, но как только я понял свою ошибку, это было простое решение. Очевидно, что я до сих пор длинные пути пойти в изучении Java ...


Edit:

Хорошо, теперь я раздражен ... видимо, до сих пор ломает, если вы попытаетесь запустить его от прослушивателя действий. Моя самая последняя версия класса 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() было загружено в новый runnable, и все это работает, и столько раз, сколько мне нужно.

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

Смежные вопросы