我一直在努力驯服
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); 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 https://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)); } }
编辑
在打印的信息中,还可以看到3个系统属性:
os.name: Windows 7 java.version: 1.7.0_21 java.vendor: Oracle Corporation
这些是这里的价值观.
MouseMotionListener固定代码
感谢Jonathan Drapeau对MouseListener的建议,这个固定的例子实际上使用了一个MouseMotionListener来允许在拖动时主动调整桌面窗格.除了使用引起问题的MouseListener(还没有知道)之外,它可能会受到一些怪癖,如果是这样,可以回到“内部帧丢弃”(“MouseListener only”)上“调整桌面窗格大小”的简单技术.
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,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),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,// 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)); } }
怪癖
It might suffer some quirks beyond use of a
MouseListener
that cause problems (none yet known).
那就是..
>在完全呈现模式下,只要用户拖动内部框架(甚至GUI),桌面窗格将动态增长. (好.)在轮廓模式下,容器只能调整大小,而不是拖动. (不太好,但至少滚动条出现/消失可靠.)
解决方法
在JDesktopPane.LIVE_DRAG_MODE中,在JInternalFrame标题窗格中添加一个MouseListener,以便在发布后重新验证JDesktopPane是一种在每种模式下获得完全相同的行为的方式.
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); } } } } } };
我在JDesktopPane.OUTLINE_DRAG_MODE中删除它们,因为它已经正确响应了.