如何在 JFrame 可见后调用 setUndecorated() 方法?

22
在我的Swing应用程序中,我希望能够在不重新创建整个框架的情况下切换装饰和无装饰的功能。然而,API不允许我在窗体可见后调用setUndecorated()
即使我调用了setVisible(false)isDisplayable()仍然返回true。API说使框架不可显示的唯一方法是重新创建它。然而,我不想为了关闭一些标题栏而重新创建框架。
我正在制作一个可以在全屏和窗口模式之间切换的应用程序;它应该能够在保持状态等的同时切换。
如何在窗体可见后实现这一点?
7个回答

31

你尝试过调用Frame.dispose()然后再进行更改吗?我自己没有尝试过,但这有可能有效。

如果不行的话,你可以将frame作为该类中不重要的一部分,只与必要的最高级面板或面板之间保持最小的联系,并将它们移动到新的frame中。所有子元素都会跟随移动。


2
这是一个惊人而简单的解决方案,非常感谢。我做了这个:dispose();'setUndecorated(true); setExtendedState(JFrame.MAXIMIZED_BOTH); setVisible(true);' - maq
1
这应该是被接受的答案,因为它不会每次创建一个新的JFrame。 - PaulProgrammerNoob

19
你无法做到这一点,这是我尝试实现相同功能时的经验。
但是,如果你的整个用户界面都在一个面板中,并且该面板在你的框架中,你可以创建一个新的框架并将该面板添加到该框架中。这不需要太多工作。
类似于下面的代码:
// to start with
JPanel myUI = createUIPanel();
JFrame frame = new JFrame();
frame.add(myUI);

// .. and later ...

JFrame newFrame = new JFrame();
newFrame.setUndecorated();
newFrame.add(myUI);

在Swing中,面板(以及任何组件的实例)一次只能在一个框架中,因此当您将其添加到新框架时,它立即停止在旧框架中。


5
调用dispose()释放本地窗口资源,然后您可以编辑诸如undecorated等属性。使用pack()重新创建窗口资源,然后只需调用setVisible(true),一切都可以正常工作(位置和所有组件不会被更改)。 - Thomas
1
正如Thomas所描述的那样,这是可能的,请参见https://dev59.com/lYbca4cB1Zd3GeqPWX75 - Christian Hujer

14

调用dispose()释放本地窗口资源,然后您可以编辑诸如undecorated之类的属性。最后只需调用setVisible(true)重新创建窗口资源,一切都能正常工作(位置和所有组件不会更改)。

dispose();
setUndecorated(true/false);
setVisible(true);

13
请查看此链接https://tvbrowser.svn.sourceforge.net/svnroot/tvbrowser/trunk/tvbrowser/src/tvbrowser/ui/mainframe/MainFrame.java 在方法switchFullscreenMode()中:
dispose();
...
setFullScreenWindow(...);
setUndecorated(true/false);
setBounds(mXPos, mYPos, mWidth, mHeight);
...
setVisible(true);

实际上,有很多其他的东西可以隐藏各种侧面板,如果鼠标触摸到侧面,它们会重新出现。

还要注意,您必须明确设置边界。Window.setExtendedState(MAXIMIZED_BOTH)在dispose()的及时邻近处干扰严重,因为它们都依赖于操作系统的多个本机事件,如果窗口在那一刻不可显示,则这些事件将丢失。

我不建议直接采用默认屏幕:

GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

而不是使用 JFrame,应该使用屏幕:

setBounds(getGraphicsConfiguration().getBounds());
getGraphicsConfiguration().getDevice().setFullScreenWindow(this);

虽然它现在相同,但将来可能会改变。

这对我来说完美地运作了,而且比经常创建新框架的代码更简单。您关于边界和使用当前屏幕的框架的评论特别有帮助。我还在将其转换为全屏之前获取窗口的边界,这样当我退出全屏时就可以将其恢复到相同的位置和大小。 - dimo414

3

尝试:

dispose();
setUndecorated(true);
setVisible(true);

请查看。希望能有所帮助!


2

好的,您需要不同的框架实例。您可能能够在不重新创建框架的情况下移动框架的内容。关键是使您的代码不依赖于特定的框架。这是任何情况下的基本良好实践。


那是我考虑过的,但我正在寻找另一种选择。 - Lucky

1

以下是如何使用代码使 ALT + Enter 进入全屏模式而不带有工具栏,并在显示标题栏和开始栏时最小化:

public class myTest extends JFrame{
 //Your codes...
     //if "ALT" key on hold and "Enter" key pressed with it
     if (evt.isAltDown() && evt.getKeyCode() == evt.VK_ENTER) {    
         //if the JFrame has Title bar
         if (isUndecorated()) {
             //this will dispose your JFrame
             dispose();
             //here to set it with no Title bar
             setUndecorated(false);
             pack();
             setLocationRelativeTo(null);
             //as you dispose your JFrame, you have to remake it Visible..
             setVisible(true);
          } else {
             dispose();
             setUndecorated(true);
             setExtendedState(MAXIMIZED_BOTH);
             setVisible(true);
        }
    }
//your codes
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接