5

以下のコードは、FF、IE、Chrome などのブラウザで見られるマルチ ドキュメント インターフェイス (MDI) と少し似た動作をするはずです。ユーザーの選択により、ペインから新しい (または既存の) ウィンドウにドラッグできるように、タブ付きペインに「ドキュメント」 (スペーサーとしての黒いバッファリングされた画像) を表示します。

しかし、タブがなくなるとフレームを閉じたり、表示されるウィンドウがなくなったときに JVM を閉じたりするという問題がありました。の aをチェックして修正したと思いますTimerDragTabManager

  • 開いているフレームをチェックして、DragTabFrame
  • 見つかった場合は、タブ数をチェックします。0 の場合、フレームは非表示に設定され、破棄されます。
  • 表示されているフレームのインスタンスが見つからない場合はTimer、JRE を終了できるように終了します。

少なくとも、それが機能するはずの方法です。ここでは確実に動作しているようで、かなりの数のテストで「空のフレームまたは VM がシャットダウンに失敗する」ことはありませんでした。他の人に宣伝されているように機能しますか、それともさらに調べる必要がありますか?

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;
    }
}

修理

DSquareの回答の提案に従って、ここに固定ソースがあり、他にもいくつかの調整があります。

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;
    }
}
4

1 に答える 1

7

タイマーを無効にすると、最後のタブを新しい(既存のない)フレームにドラッグしたときに矛盾が見つかりました。これは、else の配置が不適切で、元のフレームのチェックとクローズを行うコードを実行できなかったことが原因でした。私はこのように変更しましたが、タイマーなしでこれまでのところ動作します:

    @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 DragTabManager() {
    /* unused actionlistener code here */

    //timer = new Timer(200,actionListener);
    //timer.start();
}

あなたが言及したJVMの問題を閉じることについては知りませんが、他に問題があるはずはないと思います。

于 2013-09-03T09:25:35.357 に答える