开发者

Does JFrame.setExtendedState(MAXIMIZED_BOTH) work with undecorated frames?

The following Swing code doesn't work correctly on my machine or my co-workers machines (all Windows XP & Java 6):

public class Test {
    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setLayout(new FlowLayout());
        frame.add(new JButton(new AbstractAction("Maximize") {
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setExtendedState((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH ? JFrame.NORMAL : JFrame.MAXIMIZED_BOTH);
            }
        }));
        frame.setUndecorated(true);
        frame.setVisible(true);
    }
}

It maximizes the window, but does not take into consideration the windows task bar (it fills the screen). If you comment out "frame.setUndecorated(true);" it seems to work correctly.

The Javadoc seems to imply this should work. Is this a bug in Java? Is it limited to a specific release, or version of Windows? Is there a workaround?

I've seen开发者_Python百科 a few workarounds, but they seem incomplete. I can't be the first person to code my own frame decorations in Java.

EDIT: After downloading the OpenJDK and digging through the native code, I found that Java is calling the win32 function SetWindowPlacement and under some conditions altering MINMAXINFO to get the right window size. I think what I was seeing was the default windows behavior for a window with no title or border (although I can't find that documented anywhere). I've found that calling JFrame.setMaximizedBounds() provides the bounds used to alter the win32 MINMAXINFO structure. So by altering my action performed and using the window size suggested by camickr as my MaximizedBounds, I get a bit closer:

GraphicsConfiguration graphicsConfiguration = frame.getGraphicsConfiguration();
frame.setMaximizedBounds(graphicsConfiguration.getBounds());
frame.setExtendedState((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH ? JFrame.NORMAL : JFrame.MAXIMIZED_BOTH);

Now the maximize window no longer hides the menubar. But.. now I have another problem. I can't maximize from a secondary monitor. The frame just disappears.

I'm adding some win32 tags in hopes of getting a C++ programmer who recognizes this problem.

SOLUTION: I apparently can't answer my own question yet, so I'll just put my solution here. I had to use a Sun class, and I haven't tested it on any platforms other than Windows, but so far this seems to be working well with multiple monitors, and multiple taskbar configurations:

GraphicsConfiguration config = frame.getGraphicsConfiguration();
Rectangle usableBounds = SunGraphicsEnvironment.getUsableBounds(config.getDevice());
frame.setMaximizedBounds(new Rectangle(0, 0, usableBounds.width, usableBounds.height));
frame.setExtendedState((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH ? JFrame.NORMAL : JFrame.MAXIMIZED_BOTH);


Interesting. When I try it it seems to happen in two steps. First expands to fill the space above the task bar, then a split second later it covers the task bar. I have no idea why.

Anyway for a workaround you can use:

GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle bounds = env.getMaximumWindowBounds();
System.out.println("Screen Bounds: " + bounds );

to manually set the bounds of your frame when you want to maximize it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜