DragTabFrame zamyka się niekonsekwentnie

Poniższy kod powinien działać trochę jak interfejs wielu dokumentów (MDI), który możesz zobaczyć w przeglądarce, takiej jak FF, IE lub Chrome. Prezentuje „dokumenty” (czarny buforowany obraz jako spacer) w panelu z zakładkami, dzięki czemu można je przeciągać z panelu do nowego (lub istniejącego) okna według wyboru użytkownika.

Ale miał problemy z zamknięciem ramek, gdy nie mają już żadnych kart, a także zamknięcie maszyny JVM, gdy nie ma już żadnych widocznych okien. jamyśleć Naprawiłem je, sprawdzając za pomocąTimer wDragTabManager:

Sprawdza otwarte ramki dla wystąpieńDragTabFrameJeśli go znajdzie, sprawdź liczbę kart. Jeśli 0 ramka jest niewidoczna i usunięta.Jeśli nie znajdzie żadnych widocznych ramek, kończyTimer aby zezwolić JRE na wyjście.

Tak przynajmniej ma działać. Wydaje się, że działa tutaj niezawodnie i nie widziałem „pustej ramki lub maszyny wirtualnej, której nie udało się zamknąć” na kilka testów. Czy działa tak, jak jest reklamowany dla innych, czy też muszę patrzeć dalej?

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class DragTabFrame extends JFrame {

    private JTabbedPane tabbedPane = new JTabbedPane();
    private final static DragTabManager dragTabManager = new DragTabManager();

    final MouseAdapter ma = new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent e) {
            JComponent c = (JComponent) e.getSource();
            dragTabManager.setCurrentComponent(c);
            DragTabFrame dtf = (DragTabFrame)c.getTopLevelAncestor();
            dragTabManager.setCurrentFrame(dtf);
            JTabbedPane tp = dtf.getTabbedPane();
            int index = tp.indexOfComponent(c);
            if (index<0) index = 0;
            String title = tp.getTitleAt(index);
            dragTabManager.setCurrentTitle(title);
        }

        @Override
        public void mousePressed(MouseEvent e) {
            JComponent c = (JComponent) e.getSource();
            DragTabFrame dtf = (DragTabFrame)c.getTopLevelAncestor();
            dragTabManager.setCurrentComponent(c);
            dragTabManager.setCurrentFrame(dtf);
            JTabbedPane tp = dtf.getTabbedPane();
            int index = tp.indexOfComponent(c);
            if (index<0) index = 0;
            String title = tp.getTitleAt(index);
            dragTabManager.setCurrentTitle(title);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            JComponent c = (JComponent) e.getSource();
            if (c.getTopLevelAncestor().getBounds().contains(e.getLocationOnScreen())) {
                // do nothing, the drop point is the same frame
            } else {
                DragTabFrame dtf = getTargetFrame(e.getLocationOnScreen());
                if (dtf == null) {
                    dtf = new DragTabFrame();
                    dtf.init();
                    dtf.setLocation(e.getLocationOnScreen());
                } else {
                    DragTabFrame fromFrame = dragTabManager.getCurrentFrame();
                    fromFrame.removeTabComponent(c);
                    JTabbedPane tp = fromFrame.getTabbedPane();
                    if (tp.getTabCount() == 0) {
                        fromFrame.setVisible(false);
                        fromFrame.dispose();
                    } 
                }
                dtf.addTabComponent(dragTabManager.getCurrentTitle(), c);
                dtf.pack();
                dtf.setVisible(true);
            }
        }
    };

    public JTabbedPane getTabbedPane() {
        return tabbedPane;
    }

    public DragTabFrame getTargetFrame(Point p) {
        Frame[] frames = Frame.getFrames();
        for (Frame frame : frames) {
            if (frame instanceof DragTabFrame
                    && frame.getBounds().contains(p)) {
                return (DragTabFrame) frame;
            }
        }

        return null;
    }

    public void init() {
        // the GUI as seen by the user (without frame)
        JPanel gui = new JPanel(new BorderLayout());
        gui.setBorder(new EmptyBorder(2, 3, 2, 3));
        gui.add(tabbedPane, BorderLayout.CENTER);
        add(gui);

        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        // See https://stackoverflow.com/a/7143398/418556 for demo.
        setLocationByPlatform(true);
    }

    public void addTabComponent(String name, Component c) {
        tabbedPane.addTab(name, c);
        c.addMouseListener(ma);
        c.addMouseMotionListener(ma);
    }

    public void removeTabComponent(Component c) {
        tabbedPane.remove(c);
        c.removeMouseListener(ma);
        c.removeMouseMotionListener(ma);
    }
    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {

                DragTabFrame dtf = new DragTabFrame();
                dtf.init();
                BufferedImage bi = new BufferedImage(
                        200, 40, BufferedImage.TYPE_INT_RGB);
                for (int ii = 1; ii < 4; ii++) {
                    JLabel l = new JLabel(new ImageIcon(bi));
                    dtf.addTabComponent("Tab " + ii, l);
                }
                dtf.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                dtf.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}

class DragTabManager {
    private DragTabFrame currentFrame;
    private JComponent currentComponent;
    private String currentTitle;
    private Timer timer;

    public DragTabManager() {
        ActionListener actionListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                Frame[] frames = Frame.getFrames();
                if (frames.length==0) {
                    timer.stop();
                }
                System.out.println("frames.length: " + frames.length);
                boolean allInvisible = true;
                for (Frame frame : frames) {
                    if (frame instanceof DragTabFrame) {
                        DragTabFrame dtf = (DragTabFrame)frame;
                        if (dtf.isVisible()) {
                            allInvisible = false;
                        }
                        if (dtf.getTabbedPane().getTabCount()==0) {
                            dtf.setVisible(false);
                            dtf.dispose();
                        }
                    }
                }
                if (allInvisible) {
                    timer.stop();
                }
            }
        };
        timer = new Timer(200,actionListener);
        timer.start();
    }

    /**
     * @return the currentFrame
     */
    public DragTabFrame getCurrentFrame() {
        return currentFrame;
    }

    /**
     * @param currentFrame the currentFrame to set
     */
    public void setCurrentFrame(DragTabFrame currentFrame) {
        this.currentFrame = currentFrame;
    }

    /**
     * @return the currentComponent
     */
    public JComponent getCurrentComponent() {
        return currentComponent;
    }

    /**
     * @param currentComponent the currentComponent to set
     */
    public void setCurrentComponent(JComponent currentComponent) {
        this.currentComponent = currentComponent;
    }

    /**
     * @return the currentTitle
     */
    public String getCurrentTitle() {
        return currentTitle;
    }

    /**
     * @param currentTitle the currentTitle to set
     */
    public void setCurrentTitle(String currentTitle) {
        this.currentTitle = currentTitle;
    }
}
Naprawić

Zgodnie z sugestiami wodpowiedź DSquare, tutaj jest stałe źródło, z kilkoma innymi poprawkami.

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class DragTabFrame extends JFrame {

    private JTabbedPane tabbedPane = new JTabbedPane();
    private final static DragTabManager dragTabManager = new DragTabManager();
    final MouseAdapter ma = new MouseAdapter() {

        @Override
        public void mousePressed(MouseEvent e) {
            JComponent c = (JComponent) e.getSource();
            DragTabFrame dtf = (DragTabFrame) c.getTopLevelAncestor();
            dragTabManager.setCurrentComponent(c);
            dragTabManager.setCurrentFrame(dtf);
            JTabbedPane tp = dtf.getTabbedPane();
            int index = tp.indexOfComponent(c);
            String title = tp.getTitleAt(index);
            dragTabManager.setCurrentTitle(title);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            JComponent c = (JComponent) e.getSource();
            if (c.getTopLevelAncestor().getBounds().contains(
                    e.getLocationOnScreen())) {
                // do nothing, the drop point is the same frame
            } else {
                DragTabFrame dtf = getTargetFrame(e.getLocationOnScreen());
                if (dtf == null) {
                    dtf = new DragTabFrame();
                    dtf.init();
                    dtf.setLocation(e.getLocationOnScreen());
                }
                DragTabFrame fromFrame = dragTabManager.getCurrentFrame();
                fromFrame.removeTabComponent(c);
                JTabbedPane tp = fromFrame.getTabbedPane();
                if (tp.getTabCount() == 0) {
                    fromFrame.setVisible(false);
                    fromFrame.dispose();
                }
                dtf.addTabComponent(dragTabManager.getCurrentTitle(), c);
                dtf.pack();
                dtf.setVisible(true);
            }
        }
    };

    public JTabbedPane getTabbedPane() {
        return tabbedPane;
    }

    public DragTabFrame getTargetFrame(Point p) {
        Frame[] frames = Frame.getFrames();
        for (Frame frame : frames) {
            if (frame instanceof DragTabFrame
                    && frame.getBounds().contains(p)) {
                return (DragTabFrame) frame;
            }
        }

        return null;
    }

    public void init() {
        // the GUI as seen by the user (without frame)
        JPanel gui = new JPanel(new BorderLayout());
        gui.setBorder(new EmptyBorder(2, 3, 2, 3));
        gui.add(tabbedPane, BorderLayout.CENTER);
        add(gui);

        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        // See https://stackoverflow.com/a/7143398/418556 for demo.
        setLocationByPlatform(true);
    }

    public void addTabComponent(String name, Component c) {
        tabbedPane.addTab(name, c);
        c.addMouseListener(ma);
        c.addMouseMotionListener(ma);
    }

    public void removeTabComponent(Component c) {
        tabbedPane.remove(c);
        c.removeMouseListener(ma);
        c.removeMouseMotionListener(ma);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {

                DragTabFrame dtf = new DragTabFrame();
                dtf.init();
                BufferedImage bi = new BufferedImage(
                        200, 40, BufferedImage.TYPE_INT_RGB);
                for (int ii = 1; ii < 4; ii++) {
                    JLabel l = new JLabel(new ImageIcon(bi));
                    dtf.addTabComponent("Tab " + ii, l);
                }
                dtf.pack();
                dtf.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

class DragTabManager {

    private DragTabFrame currentFrame;
    private JComponent currentComponent;
    private String currentTitle;

    /**
     * @return the currentFrame
     */
    public DragTabFrame getCurrentFrame() {
        return currentFrame;
    }

    /**
     * @param currentFrame the currentFrame to set
     */
    public void setCurrentFrame(DragTabFrame currentFrame) {
        this.currentFrame = currentFrame;
    }

    /**
     * @return the currentComponent
     */
    public JComponent getCurrentComponent() {
        return currentComponent;
    }

    /**
     * @param currentComponent the currentComponent to set
     */
    public void setCurrentComponent(JComponent currentComponent) {
        this.currentComponent = currentComponent;
    }

    /**
     * @return the currentTitle
     */
    public String getCurrentTitle() {
        return currentTitle;
    }

    /**
     * @param currentTitle the currentTitle to set
     */
    public void setCurrentTitle(String currentTitle) {
        this.currentTitle = currentTitle;
    }
}

questionAnswers(1)

yourAnswerToTheQuestion