Swing переходит в состояние ожидания после блокировки разблокировки через стекло

Я испытываю странную ситуацию. При некоторых условиях (тайм-аут бездействия) мне нужно заблокировать мое окно свинга (и любые подокна), и после повторной разблокировки с помощью действительных учетных данных мне нужно разблокировать их все обратно.

Я использую стекло противника, и мои две функции, как показано ниже

Модуль главного замка

public void lock(boolean minimize) {
    if (!locked) {
        locked = true;
        lockMinimized = minimize;
        logger.debug(context + "Locking Target...");
        // Lock all frames using the AWT event dispatching thread.
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Frame[] frames = Frame.getFrames();
                Window[] subwindows;
                for (Frame frame : frames) {
                    // Lock the frame itself
                    lockWindow(frame);

                    // Lock subwindows owned by the frame
                    subwindows = frame.getOwnedWindows();
                    for (Window subwindow : subwindows) {
                        if (subwindow instanceof RootPaneContainer) {
                            lockWindow(subwindow);
                        }
                    }
                }
                //do additional stuff - lock out of process windows
                if (lockUnlockInterface != null) {
                    logger.info("calling locking for out of jvm process ");
                    lockUnlockInterface.lock();
                }
            }
        });
        logger.debug(context + "Target locked.");
    }
}

Метод дополнительной блокировки

private void lockWindow(final Window window) {
    logger.debug(context + "Locking window: " + window.getClass().toString());
    Vector exemptWindowClassNames = getExemptList();
    if (window instanceof RootPaneContainer
            && ((RootPaneContainer) window).getRootPane() != null
            && !lockedWindows.containsKey(window)
            && !(exemptWindowClassNames.contains(window.getClass().toString()))) {
        logger.debug(context + "Locking window...");
        try {
            // Create an object to store original details for the locked window.
            LockedWindow lockedWindow = new LockedWindow();
            lockedWindows.put((RootPaneContainer) window, lockedWindow);

            // Remember the original glass pane and visibility before locking.
            lockedWindow.originalGlassPane = ((RootPaneContainer) window).getGlassPane();
            lockedWindow.wasVisible = ((RootPaneContainer) window).getContentPane().isVisible();

            // Add a LockedGlassPane to the window.
            LockedGlassPane lgp = new LockedGlassPane();
            lgp.setVisible(true); //hide the contents of the window
            ((RootPaneContainer) window).setGlassPane(lgp);
            ((RootPaneContainer) window).getContentPane().setVisible(false);
            lgp.setVisible(true); //redisplays the lock message after set as glassPane.
            ((RootPaneContainer) window).getContentPane().invalidate();

            // Minimize the window (if requested), while keeping a record of
            // which windows have been minimized so that they can be restored
            // later when the TimeoutTarget is unlocked.
            if (window instanceof Frame) {
                Frame frame = (Frame) window;
                // Remember the original minimized state of the window.
                lockedWindow.minimized = (frame.getExtendedState() & Frame.ICONIFIED) != 0;
                if (lockMinimized) {
                    frame.setExtendedState(Frame.ICONIFIED);
                }
            }

            //
            //Note required now, but keeping in case the requirement changes again.
            //
            // Prevent the window from being closed while this target is
            // locked.
            // lockedWindow.windowListeners = window.getWindowListeners();
            //  for (WindowListener wl : lockedWindow.windowListeners) {
            //     window.removeWindowListener(wl);
            // }
            //if (window instanceof JFrame) {
            // JFrame jframe = (JFrame) window;
            // lockedWindow.originalDefaultCloseOperation = jframe.getDefaultCloseOperation();
            // jframe.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
            //} else if (window instanceof JDialog) {
            //  JDialog jdialog = (JDialog) window;
            // lockedWindow.originalDefaultCloseOperation = jdialog.getDefaultCloseOperation();
            // jdialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
            //}
        } catch (Exception e) {
            logger.error(context + "Failed to lock window.", e);
        }
    }
    if (exemptWindowClassNames.contains(window.getClass().toString())) {
        window.toFront();
    }
}

разблокировать основной метод

public void unlock() { locked = false; lockMinimized = false;

    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            Window[] subwindows;
            for (RootPaneContainer window : lockedWindows.keySet()) {
                // Unlock the frame itself.
                unlockWindow(window);

                // Unlock subwindows owned by the frame.
                if (window instanceof Frame) {
                    subwindows = ((Frame) window).getOwnedWindows();
                    for (Window subwindow : subwindows) {
                        if (subwindow instanceof RootPaneContainer) {
                            unlockWindow((RootPaneContainer) subwindow);
                        }
                    }
                }
            }

            lockedWindows.clear();

          //do additional stuff - lock out of process windows
            if (lockUnlockInterface != null) {
                logger.info("calling unlocking for out of jvm process ");
                lockUnlockInterface.unlock();
            }
        }
    });
}

метод дополнительной разблокировки

private void unlockWindow(RootPaneContainer window) {
    try {
        LockedWindow lockedWindow = lockedWindows.get(window);
        logger.debug(context + "Unlocking window: " + window);
        if (lockedWindow != null) {
            logger.debug(context + "Unlocking...");
            // Restore the original glasspane for the window
            if (lockedWindow.originalGlassPane != null) {
                logger.debug(context + "Reset original glass pane.");
                window.setGlassPane(lockedWindow.originalGlassPane);
            }
            //make content pane visible again.
            (window).getContentPane().setVisible(lockedWindow.wasVisible);
            (window).getRootPane().invalidate();

            // Restore (un-minimize) the window if it wasn't minimized before
            // the lock.
            if (!lockedWindow.minimized && window instanceof Frame) {
                ((Frame) window).setExtendedState(((Frame) window).getExtendedState()
                        & ~Frame.ICONIFIED);
            }
            // Restore the original default close operation from before the
            // lock, which will normally allow the window to be closed.
            if (window instanceof Window) {
                if (lockedWindow.windowListeners != null) {
                    for (WindowListener wl : lockedWindow.windowListeners) {
                        ((Window) window).addWindowListener(wl);
                    }
                }
                if (window instanceof JFrame) {
                    ((JFrame) window)
                            .setDefaultCloseOperation(lockedWindow.originalDefaultCloseOperation);
                } else if (window instanceof JDialog) {
                    ((JDialog) window)
                            .setDefaultCloseOperation(lockedWindow.originalDefaultCloseOperation);
                }
            }
            logger.debug(context + "Window has been unlocked");
        }
    } catch (Exception e) {
        logger.error(context + "Failed to unlock window.", e);
    }

}

Просто чтобы повторить еще раз Моя блокировка и разблокировка происходит успешно. Ну, разблокировка не удалась, потому что после разблокировки остается занятый курсор над моим разблокированным окном. Это так же хорошо, как ушел. Бесполезный.

Я видел из журналов, я успешно выхожу из вызова разблокировки. Тогда я не знаю, что заставляет этот занятый курсор появляться и блокировать что-либо в моем окне.

У меня тоже есть эти журналы, и они довольно хорошо

Я не уверен, что вызывает это тогда?

Возможные виновники и вещи, которые я пытался

  1. не делает недействительным в блокировке разблокировки
  2. установка стеклянной панели в ноль явно
  3. не слушаю

Все это безрезультатно, ситуация остается безрадостной.

Кто-нибудь испытал то же самое, можете дать мне указатели, пожалуйста?

У меня есть одно ограничение: я не могу оставить метод стеклопакета, чтобы сохранить однородность между приложениями, которые я должен использовать. Таким образом, я должен заставить это работать, никаких альтернатив.

ОБНОВИТЬ

@trashgod Я взял дамп потока К сожалению, не могу его прикрепить. Что мне нужно посмотреть на это? Последние три строки: "VM Thread" prio=10 tid=0x28688000 nid=0x5e58, работоспособный

"Поток периодических задач VM" prio=10 tid=0x28721c00 nid=0x2bc0, ожидание при условии

Глобальные ссылки JNI: 19887

Любая помощь в этом? На что мне стоит посмотреть? "VM Периодическая Задача Thread"?? какие конкретные состояния какие?

Как я могу получить помощь по дампу потока. Я блю не через SO, пересекаю предел char здесь.

1 ответ

Решение

Я получил решение проблемы.

Этот ответ мне очень помог. java swing очистить очередь событий Infact концепция ключа та же.

Так что для части кода я изменил модули с

lockWindow

private void lockWindow(final Window window) {
    if (window instanceof RootPaneContainer
            && ((RootPaneContainer) window).getRootPane() != null
            && !lockedWindows.containsKey(window)) {
        java.util.Timer timer = null;
        try {

            //don't do invalidate, invalidate as the first step
            //((RootPaneContainer) window).getContentPane().invalidate();

            // Create an object to store original details for the locked window.
            LockedWindow lockedWindow = new LockedWindow();
            lockedWindows.put((RootPaneContainer) window, lockedWindow);

            lockedWindow.originalGlassPane = ((RootPaneContainer) window).getGlassPane();


            //okk may be glasspane only in integrated scenario is causing the issue
            //comment it and check, we are still putting it in the map  above but its doing nothing
            /*
            // Remember the original glass pane and visibility before locking.

            //okk is this the only issue? What should be the originalGlassPane first time? null?
            lockedWindow.originalGlassPane = ((RootPaneContainer) window).getGlassPane();
            System.err.println("Original galss pane : " + ((RootPaneContainer) window).getGlassPane());

            lockedWindow.wasVisible = ((RootPaneContainer) window).getContentPane().isVisible();

            // Add a LockedGlassPane to the window.
            LockedGlassPane lgp = new LockedGlassPane();
            lgp.setVisible(true); //hide the contents of the window
            ((RootPaneContainer) window).setGlassPane(lgp);

            //don't do this stuff too
            ((RootPaneContainer) window).getContentPane().setVisible(false);

            lgp.setVisible(true); //redisplays the lock message after set as glassPane.
            */
            LockedGlassPane lgp = new LockedGlassPane();
            ((RootPaneContainer) window).setGlassPane(lgp);
            timer = switchToBusyCursor(window);

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                //do nothing
                System.err.println("Am I interrupted?");
            }
            //okk the above thing worked, it doesnt lock naturlly, now try if setting visible code is an issue?
            //great this thing works so this also is not an issue, only galsspane in SiteManager is
            lockedWindow.wasVisible = ((RootPaneContainer) window).getContentPane().isVisible();

            ((RootPaneContainer) window).getContentPane().repaint();

            // Minimize the window (if requested), while keeping a record of
            // which windows have been minimized so that they can be restored
            // later when the TimeoutTarget is unlocked.

          //don't do this stuff too - as unlock is not working investigating that
            if (window instanceof Frame) {
                Frame frame = (Frame) window;
                // Remember the original minimized state of the window.
                lockedWindow.minimized = (frame.getExtendedState() & Frame.ICONIFIED) != 0;
                if (lockMinimized) {
                    frame.setExtendedState(Frame.ICONIFIED);
                }
            }

            //
            //Note required now, but keeping in case the requirement changes again.
            //
            // Prevent the window from being closed while this target is
            // locked.
            // lockedWindow.windowListeners = window.getWindowListeners();
            //  for (WindowListener wl : lockedWindow.windowListeners) {
            //     window.removeWindowListener(wl);
            // }
            //if (window instanceof JFrame) {
            // JFrame jframe = (JFrame) window;
            // lockedWindow.originalDefaultCloseOperation = jframe.getDefaultCloseOperation();
            // jframe.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
            //} else if (window instanceof JDialog) {
            //  JDialog jdialog = (JDialog) window;
            // lockedWindow.originalDefaultCloseOperation = jdialog.getDefaultCloseOperation();
            // jdialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
            //}
        } catch (Exception e) {
            System.err.println(getThreadPrefix()  + " Failed to lock window." + e.getLocalizedMessage());
        } finally {
            switchToNormalCursorEventThread(window, timer);
        }
    }        
}

unlockWindow

private void unlockWindow(RootPaneContainer window) {
    try {
        LockedWindow lockedWindow = lockedWindows.get(window);
        //System.err.println(getThreadPrefix()  + " Unlocking window::: " + lockeWindow.isDisplayable());
        if (lockedWindow != null && ((Frame) window).isDisplayable()) {
            System.err.println(getThreadPrefix() + "Unlocking..." + lockedWindow);
            // Restore the original glasspane for the window

            //okk may be glasspane only in integrated scenario is causing the issue
            //comment it and check, we are still putting it in the map  above but its doing nothing


            //okk is this the only issue? What should be the originalGlassPane first time? null?
            if (lockedWindow.originalGlassPane != null) {
                System.err.println(getThreadPrefix() + "Reset original glass pane.");
                window.setGlassPane(lockedWindow.originalGlassPane);
                //lockedWindow.originalGlassPane.setVisible(true);
            }


            //make content pane visible again.
            //(window).getContentPane().setVisible(lockedWindow.wasVisible);

            //okk try this
            //(window).getContentPane().setVisible(true);
            //(window).getRootPane().invalidate();

            //okk the above thing worked, it doesnt lock naturlly, now try if setting visible code is an issue?
            //great this thing works so this also is not an issue
            (window).getContentPane().setVisible(lockedWindow.wasVisible);

            (window).getRootPane().repaint();

            // Restore (un-minimize) the window if it wasn't minimized before
            // the lock.
            //do this tuff anyways
            if (!lockedWindow.minimized && window instanceof Frame) {
                ((Frame) window).setExtendedState(((Frame) window).getExtendedState()
                        & ~Frame.ICONIFIED);
            }


            // Restore the original default close operation from before the
            // lock, which will normally allow the window to be closed.

            //dont do listeneres??
            if (window instanceof Window) {
                if (lockedWindow.windowListeners != null) {
                    for (WindowListener wl : lockedWindow.windowListeners) {
                        System.err.print("windowlistener is not null " + wl);
                        ((Window) window).addWindowListener(wl);
                    }
                }
                if (window instanceof JFrame) {
                    ((JFrame) window)
                            .setDefaultCloseOperation(lockedWindow.originalDefaultCloseOperation);
                } else if (window instanceof JDialog) {
                    ((JDialog) window)
                            .setDefaultCloseOperation(lockedWindow.originalDefaultCloseOperation);
                } 
            }

            //try this too
            //((RootPaneContainer)window).setGlassPane(null);

            //lockedWindows.remove(window);
          //stopEventTrap
            stopEventTrap((Frame)window);
            System.err.println(getThreadPrefix()  + " Window has been unlocked");
        }
    } catch (Exception e) {
        System.err.println(getThreadPrefix()  + " Failed to unlock window. " + e.getLocalizedMessage());
    }

}

Добавлены эти новые методы, взятые из приведенного выше ответа с модификациями, как в моем случае использования

public static java.util.Timer switchToBusyCursor(final Window frame) {
    startEventTrap(frame);
    java.util.TimerTask timerTask = new java.util.TimerTask() {

        public void run() {
            startWaitCursor(frame);
        }

    };
    final java.util.Timer timer = new java.util.Timer();
    timer.schedule(timerTask, DELAY_MS);
    return timer;
}

public static void switchToNormalCursorEventThread(final Window window, final java.util.Timer timer) {

    Runnable r = new Runnable() {

        public void run() {
            switchToNormalCursor(window, timer);
        }

    };

    javax.swing.SwingUtilities.invokeLater(r);

}

public static void switchToNormalCursor(final Window window, final java.util.Timer timer) {
    timer.cancel();
    stopWaitCursor(window);
    //stopEventTrap(window);
}

private static void startWaitCursor(Window window) {
    ((RootPaneContainer) window).getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR));
    ((RootPaneContainer) window).getGlassPane().addMouseListener(mouseAdapter);
    ((RootPaneContainer) window).getGlassPane().setVisible(true);
}

private static void stopWaitCursor(Window window) {
    ((RootPaneContainer) window).getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
    //((RootPaneContainer) window).getGlassPane().removeMouseListener(mouseAdapter);
    //((RootPaneContainer) window).getGlassPane().setVisible(false);
}

private static void startEventTrap(Window window) {
    ((RootPaneContainer) window).getGlassPane().addMouseListener(mouseAdapter);
    ((RootPaneContainer) window).getGlassPane().setVisible(true);
}

private static void stopEventTrap(Window window) {
    java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue();
    ((RootPaneContainer) window).getGlassPane().removeMouseListener(mouseAdapter);
    ((RootPaneContainer) window).getGlassPane().setVisible(false);
}

private static final java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() {
};

Я также взял threaddumps и проанализировал их, как сказал @trashgod. Я обнаружил, что это тоже правильно, ИМХО, ничего не блокирует / неправильно там. Хотя да, AWTEventQueue-0 всегда был в одной и той же точке кода.

Другие вопросы по тегам