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()メソッドを呼び出すか、クラス全体を完全に再初期化するかによって) new 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() コマンドだけです。表示されていない間はスクロールし、目的地に到達すると表示されます。位置のコンソール出力は、移動していることを明確に示していますが、移動が止まるまで見ることはできません。

4

1 に答える 1

0

編集2:

そして、ばかげた気分に戻ります...問題を見つけました(実際には少し前に見つけましたが、これを更新するのを忘れていました...)。new Thread()問題は、実行可能ファイルのみを使用し、オブジェクト内に配置しなかったことです。何らかの理由で、実行可能なオブジェクトが独自の新しいスレッドを作成すると考えていましたが、自分の間違いを理解すると、簡単に修正できました。明らかに、Java の学習にはまだ長い道のりがあります...


編集:

わかりました、今はイライラしています...何らかのアクションリスナーから実行しようとすると、まだ壊れているようです。さらに下の元の回答に示されている 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();

上記のコードは、次のようなアクション リスナーに配置されるまで問題なく動作します。

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();
}
于 2014-02-12T21:15:24.033 に答える