JDesktopPane按内容设置的首选大小

And*_*son 10 java swing jscrollpane jdesktoppane preferredsize

我一直试图JDesktopPane通过可调整大小的GUI和滚动窗格来很好地工作,但是我遇到了一些麻烦.似乎除非拖动模式是大纲,否则桌面窗格将不会按预期调整大小(当内部框架被拖动超出桌面窗格的边缘时),因此不会产生滚动条.

在此输入图像描述

我在这个来源做一些非常愚蠢的事吗?我错过了一个更好的方法吗?

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

public class MDIPreferredSize {

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

            @Override
            public void run() {
                final JDesktopPane dt = new JDesktopPane() {

                    @Override
                    public Dimension getPreferredSize() {
                        Dimension prefSize = super.getPreferredSize();
                        System.out.println("prefSize: " + prefSize);
                        // inititialize the max to the first normalized bounds
                        Rectangle max = getAllFrames()[0].getNormalBounds();
                        for (JInternalFrame jif : this.getAllFrames()) {
                            max.add(jif.getNormalBounds());
                        }
                        System.out.println("maxBounds(): "
                                + max);
                        int x1 = max.width + (max.x * 2) < prefSize.width
                                ? prefSize.width
                                : max.width + (max.x * 2);
                        int y1 = max.height + (max.y * 2) < prefSize.height
                                ? prefSize.height
                                : max.height + (max.y * 2);
                        System.out.println("x,y: "
                                + x1
                                + ","
                                + y1);
                        return new Dimension(x1, y1);
                    }
                };
                dt.setAutoscrolls(true);

                int xx = 5;
                int yy = 5;
                int vStep = 10;
                int yStep = 22;
                for (int ii = 0; ii < 3; ii++) {
                    JInternalFrame jif = new JInternalFrame(
                            "Internal Frame " + (ii + 1),
                            true,
                            true,
                            true);
                    dt.add(jif);
                    jif.setLocation(xx, yy);
                    xx += vStep;
                    yy += yStep;
                    jif.setSize(200, 75);
                    jif.setVisible(true);
                }

                ComponentListener componentListener = new ComponentListener() {

                    @Override
                    public void componentResized(ComponentEvent e) {
                        e.getComponent().validate();
                    }

                    @Override
                    public void componentMoved(ComponentEvent e) {
                        e.getComponent().validate();
                    }

                    @Override
                    public void componentShown(ComponentEvent e) {
                        e.getComponent().validate();
                    }

                    @Override
                    public void componentHidden(ComponentEvent e) {
                        // do nothing 
                    }
                };
                // causes maximized internal frames to be resized..
                dt.addComponentListener(componentListener);

                final JCheckBox outLineDragMode = new JCheckBox("Outline Drag Mode");
                ActionListener dragModeListener = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (outLineDragMode.isSelected()) {
                            dt.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
                        } else {
                            dt.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
                        }
                    }
                };
                outLineDragMode.addActionListener(dragModeListener);

                JPanel gui = new JPanel(new BorderLayout());
                gui.add(outLineDragMode, BorderLayout.PAGE_START);
                gui.setBorder(new EmptyBorder(2, 3, 2, 3));
                gui.add(new JScrollPane(dt), BorderLayout.CENTER);

                JFrame f = new JFrame("DTP Preferred");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                f.setMinimumSize(f.getSize());

                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);

                printProperty("os.name");
                printProperty("java.version");
                printProperty("java.vendor");
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }

    public static void printProperty(String name) {
        System.out.println(name + ": \t" + System.getProperty(name));
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

在打印的信息中,另请参阅3个系统属性:

os.name:    Windows 7
java.version:   1.7.0_21
java.vendor:    Oracle Corporation
Run Code Online (Sandbox Code Playgroud)

这些是这里的价值观.

MouseMotionListener 固定代码

感谢Jonathan Drapeau对a的建议MouseListener,这个固定示例实际上使用a MouseMotionListener来允许在拖动时主动调整桌面窗格的大小.除了使用MouseListener导致问题(尚未知道)之外,它可能会遇到一些怪癖,如果是这样,请回到" MouseListener仅在内部帧丢弃时调整桌面窗格大小"的简单技术(仅限).

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;

public class MDIPreferredSize {

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

            @Override
            public void run() {
                final JDesktopPane dt = new JDesktopPane() {

                    @Override
                    public Dimension getPreferredSize() {
                        Dimension prefSize = super.getPreferredSize();
                        System.out.println("prefSize: " + prefSize);
                        // inititialize the max to the first normalized bounds
                        Rectangle max = getAllFrames()[0].getNormalBounds();
                        for (JInternalFrame jif : this.getAllFrames()) {
                            max.add(jif.getNormalBounds());
                        }
                        System.out.println("maxBounds(): "
                                + max);
                        int x1 = max.width + (max.x * 2) < prefSize.width
                                ? prefSize.width
                                : max.width + (max.x * 2);
                        int y1 = max.height + (max.y * 2) < prefSize.height
                                ? prefSize.height
                                : max.height + (max.y * 2);
                        System.out.println("x,y: "
                                + x1
                                + ","
                                + y1);
                        return new Dimension(x1, y1);
                    }
                };

                int xx = 5;
                int yy = 5;
                int vStep = 10;
                int yStep = 22;
                for (int ii = 0; ii < 3; ii++) {
                    JInternalFrame jif = new JInternalFrame(
                            "Internal Frame " + (ii + 1),
                            true,
                            true,
                            true);
                    dt.add(jif);
                    jif.setLocation(xx, yy);
                    xx += vStep;
                    yy += yStep;
                    jif.setSize(200, 75);
                    jif.setVisible(true);
                }

                /*final MouseListener mouseListener = new MouseAdapter() {

                    @Override
                    public void mouseReleased(MouseEvent e) {
                        dt.revalidate();
                    }
                };
                */
                final MouseMotionListener mouseMotionListener = new MouseMotionAdapter() {

                    @Override
                    public void mouseDragged(MouseEvent e) {
                        dt.revalidate();
                    }
                };
                for (JInternalFrame jif : dt.getAllFrames()) {
                    for (Component comp : jif.getComponents()) {
                        if (comp instanceof BasicInternalFrameTitlePane) {
                            //comp.addMouseListener(mouseListener);
                            comp.addMouseMotionListener(mouseMotionListener);
                        }
                    }
                }

                dt.setAutoscrolls(true);


                final JCheckBox outLineDragMode =
                        new JCheckBox("Outline Drag Mode");
                ActionListener dragModeListener = new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (outLineDragMode.isSelected()) {
                            dt.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
                        } else {
                            dt.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
                        }
                    }
                };
                outLineDragMode.addActionListener(dragModeListener);

                JPanel gui = new JPanel(new BorderLayout());
                gui.add(outLineDragMode, BorderLayout.PAGE_START);
                gui.setBorder(new EmptyBorder(2, 3, 2, 3));
                gui.add(new JScrollPane(dt), BorderLayout.CENTER);

                JFrame f = new JFrame("DTP Preferred");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                f.setMinimumSize(f.getSize());

                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);

                printProperty("os.name");
                printProperty("java.version");
                printProperty("java.vendor");
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }

    public static void printProperty(String name) {
        System.out.println(name + ": \t" + System.getProperty(name));
    }
}
Run Code Online (Sandbox Code Playgroud)

怪癖

除了使用MouseListener导致问题(尚未知道)之外,它可能会遇到一些怪癖.

那是那个..

  1. 在完全渲染模式下,只要用户拖动内部框架(甚至是GUI),桌面窗格就会动态增长.(好.)在大纲模式下,容器只会在掉落时调整大小,而不是拖动.(不太好,但至少滚动条可靠地出现/消失.)

Jon*_*eau 2

在发布后的版本中添加MouseListener到标题窗格是在每种模式下获得完全相同的行为的一种方法。JInternalFrameJDesktopPane.LIVE_DRAG_MODErevalidateJDesktopPane

            final MouseListener testList = new MouseListener() {

              @Override
              public void mouseReleased(MouseEvent e) {
                dt.revalidate();
              }

              @Override
              public void mousePressed(MouseEvent e) {
              }

              @Override
              public void mouseExited(MouseEvent e) {
              }

              @Override
              public void mouseEntered(MouseEvent e) {
              }

              @Override
              public void mouseClicked(MouseEvent e) {
              }
            };
            // causes maximized internal frames to be resized..
            dt.addComponentListener(componentListener);

            for (JInternalFrame jif : dt.getAllFrames()) {
              for (Component comp : jif.getComponents()) {
                if (comp instanceof BasicInternalFrameTitlePane) {
                  comp.addMouseListener(testList);
                }
              }
            }        

            final JCheckBox outLineDragMode = new JCheckBox("Outline Drag Mode");
            ActionListener dragModeListener = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                  if (outLineDragMode.isSelected()) {
                    dt.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
                    for (JInternalFrame jif : dt.getAllFrames()) {
                      for (Component comp : jif.getComponents()) {
                        if (comp instanceof BasicInternalFrameTitlePane) {
                          comp.removeMouseListener(testList);
                        }
                      }
                    }
                  } else {
                    dt.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
                    for (JInternalFrame jif : dt.getAllFrames()) {
                      for (Component comp : jif.getComponents()) {
                        if (comp instanceof BasicInternalFrameTitlePane) {
                          comp.addMouseListener(testList);
                        }
                      }
                    }
                  }
                }
            };
Run Code Online (Sandbox Code Playgroud)

我将它们删除,因为JDesktopPane.OUTLINE_DRAG_MODE它已经正确反应了。