Java窗口脉冲推子工作一次,然后断开
好的,我已经设置了一些代码来创建一个简单的覆盖窗口,作为我正在处理的程序的警告消息。第一次运行时一切正常,但再次尝试运行时,它会冻结整个过程,迫使我通过调试器或任务管理器终止它。我知道我做错了什么,我只是不知道是什么,因为我对Java的经验有限 下面是我用来设置窗口并将其放置在任务栏右下角的代码:Java窗口脉冲推子工作一次,然后断开,java,freeze,jwindow,Java,Freeze,Jwindow,好的,我已经设置了一些代码来创建一个简单的覆盖窗口,作为我正在处理的程序的警告消息。第一次运行时一切正常,但再次尝试运行时,它会冻结整个过程,迫使我通过调试器或任务管理器终止它。我知道我做错了什么,我只是不知道是什么,因为我对Java的经验有限 下面是我用来设置窗口并将其放置在任务栏右下角的代码: private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); public static JWi
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; }
}
就像脉冲窗口问题一样,它在第一次按预期工作,然后在后续使用中中断。在本例中,唯一中断的是scrollOn命令。它在不可见时滚动,然后在到达目的地时变为可见。该位置的控制台输出清楚地显示它正在移动,但在它停止移动之前,您无法看到它。编辑2:
然后回到感觉自己很傻。。。我发现这个问题其实是前一段时间发现的,但忘记更新这个。。。。最后的问题是,我只使用了runnable,而没有将它放在一个新的Thread对象中。出于某种原因,我认为可运行对象创建了它们自己的新线程,但一旦我发现了我的错误,就很容易解决了。显然,我在学习Java方面还有很长的路要走
编辑:
好吧,现在我很生气。。。显然,如果您试图从某种类型的动作侦听器运行它,它仍然会中断。下面是我最新版本的Pulselert类,它调用了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();
}
我突然想到一个想法;这不可能是因为我以某种奇怪的方式重写Java的自动垃圾收集,对吗?我曾试图通过创建/初始化一个新的PulseWindow类来防止此类问题,但我仍然收到冻结问题。另外,我注意到,冻结只在第二次调用startPulsing时发生,即使类被重新初始化。它在第一次运行时完全正常,但是第二次调用它导致了冻结。在混乱了一点之后,我相信这可能是因为我使用了Runnable而不是SwingWorker线程。此程序正在使用UI,该UI包含一个系统托盘图标。我会发布完整的代码,但是现在它太大了,我试着做一些事情也很开心。稍后我会发布我的发现,如果我在这个问题上仍然需要任何帮助,你可以将你的答案标记为正确-你会得到代表。我会在20小时的等待时间过后。。。不过,谢谢你的提醒!编辑:或者有没有什么方法可以不用等待就完成,我不知道?或者没有,因为它只在选定的实例中工作。。。啊
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();
}