为什么 jframe 最大化时会隐藏任务栏?

发布于 2024-11-16 07:48:18 字数 668 浏览 2 评论 0原文

我在 jFrame 中使用 setUndecorated(true);getRootPane().setWindowDecorationStyle(JRootPane.FRAME); 。这很好用,但现在当我最大化框架时,它会遍布整个窗口,甚至任务栏也不可见。我该怎么做才能使框架不隐藏任务栏?

此外,当我多次最大化最小化框架时,光标会更改为此 <-> ,通常用于当光标位于框架边框上时更改框架大小。为此我能做些什么吗?


然后一个小代码就可以重现这个事情:

import javax.swing.JFrame;
import javax.swing.JRootPane;
public class Demo extends JFrame {
    public Demo() {
        setSize(250,125);
        setUndecorated(true);
        getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
        setVisible(true);
    }
    public static void main(String[] args) {
        new Demo();
    }
}

I'm using setUndecorated(true); and getRootPane().setWindowDecorationStyle(JRootPane.FRAME); in my jFrame. This works great but now when I maximized my frame it spreads all over the window even taskbar is not visible. What can I do to make frame not to hide taskbar?

Also when I maximize minimize my frame multiple times the cursor is changed to this <-> which is generally used change size of frame when cursor is on the border of frame. Is there anything I can do for this?


A small code then can reproduce the thing:

import javax.swing.JFrame;
import javax.swing.JRootPane;
public class Demo extends JFrame {
    public Demo() {
        setSize(250,125);
        setUndecorated(true);
        getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
        setVisible(true);
    }
    public static void main(String[] args) {
        new Demo();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枯寂 2024-11-23 07:48:18

这是一个已知错误: https://bugs.java.com/bugdatabase/view_bug? bug_id=4737788

引用此链接:

解决方法是子类化 JFrame 并
重写 setExtendedState 方法,
捕获之前的任何最大化事件
它们发生并设置最大值
框架的边界适当
在调用超类之前
setExtendedState 方法。

import java.awt.*;
import javax.swing.*;

public class PFrame extends JFrame
{
private Rectangle maxBounds;

public PFrame()
{
    super();        
    maxBounds = null;
}

//Full implementation has other JFrame constructors

public Rectangle getMaximizedBounds()
{
    return(maxBounds);
}

public synchronized void setMaximizedBounds(Rectangle maxBounds)
{
    this.maxBounds = maxBounds;
    super.setMaximizedBounds(maxBounds);
}

public synchronized void setExtendedState(int state)
{       
    if (maxBounds == null &&
        (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH)
    {
        Insets screenInsets = getToolkit().getScreenInsets(getGraphicsConfiguration());         
        Rectangle screenSize = getGraphicsConfiguration().getBounds();
        Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, 
                                    screenInsets.top + screenSize.y, 
                                    screenSize.x + screenSize.width - screenInsets.right - screenInsets.left,
                                    screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top);
        super.setMaximizedBounds(maxBounds);
    }
    
    super.setExtendedState(state);
}
}

This is a known bug: https://bugs.java.com/bugdatabase/view_bug?bug_id=4737788

Quote from this link:

A workaround is to subclass JFrame and
override the setExtendedState method,
catching any maximize events before
they happen and setting the maximum
bounds of the frame appropriately
before calling the superclass's
setExtendedState method.

import java.awt.*;
import javax.swing.*;

public class PFrame extends JFrame
{
private Rectangle maxBounds;

public PFrame()
{
    super();        
    maxBounds = null;
}

//Full implementation has other JFrame constructors

public Rectangle getMaximizedBounds()
{
    return(maxBounds);
}

public synchronized void setMaximizedBounds(Rectangle maxBounds)
{
    this.maxBounds = maxBounds;
    super.setMaximizedBounds(maxBounds);
}

public synchronized void setExtendedState(int state)
{       
    if (maxBounds == null &&
        (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH)
    {
        Insets screenInsets = getToolkit().getScreenInsets(getGraphicsConfiguration());         
        Rectangle screenSize = getGraphicsConfiguration().getBounds();
        Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, 
                                    screenInsets.top + screenSize.y, 
                                    screenSize.x + screenSize.width - screenInsets.right - screenInsets.left,
                                    screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top);
        super.setMaximizedBounds(maxBounds);
    }
    
    super.setExtendedState(state);
}
}
莫多说 2024-11-23 07:48:18

Fortega 的答案有效,但是,某些部分是不需要的(或者 Java 8 不再需要):

  • 不需要保存 矩形。
  • 该代码未考虑双屏配置。特别是,如果窗口更改屏幕,GraphicsConfiguration 将发生更改。
  • 据我测试,唯一需要的重写是 setExtendedState。

当考虑双屏配置时,至少在 Windows 上,以下代码无法按预期工作:

Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, 
                                    screenInsets.top + screenSize.y, 
                                    screenSize.x + screenSize.width - screenInsets.right - screenInsets.left,
                                    screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top);

在以下双屏设置中:

  • 左屏幕 1920x1080(不是主屏幕),位置:-1920, 0
  • 右屏幕 1920x1080(主),位置:0, 0

maxBounds 将包含负 x (-1920),但setMaximizedBounds 不知何故期望屏幕空间中的坐标(其中 (x,y)(0,0) 开始),而不是虚拟坐标screen:

  • 它将设置为 setMaximizedBounds(x=-1920,y=0,width=1920,height=1050)
  • Windows 将在左侧屏幕上看到窗口(因为我每个屏幕都有一个任务栏 )屏幕上仅显示窗口)但是该窗口不会显示在屏幕上,因为它超出了范围。
  • 如果屏幕的分辨率,或更糟糕的是其比例因子(对于笔记本电脑,Windows 10 将应用比例因子,例如:25%,使屏幕“不那么”1920x1080),则上述代码不适用。例如,如果我的配置有 3 个屏幕,其中最右边是主屏幕,则窗口在左侧和中间屏幕上的显示效果会很差。我认为我没有在下面的代码中解决这个问题。

以下代码适用于具有双屏幕的 Windows:

  @Override
  public synchronized void setExtendedState(final int state) {
    if ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
      final GraphicsConfiguration cfg = getGraphicsConfiguration();
      final Insets screenInsets = getToolkit().getScreenInsets(cfg);
      final Rectangle screenBounds = cfg.getBounds();
      final int x = screenInsets.left + screenBounds.x * 0;
      final int y = screenInsets.top + screenBounds.y * 0;
      final int w = screenBounds.width - screenInsets.right - screenInsets.left;
      final int h = screenBounds.height - screenInsets.bottom - screenInsets.top;
      final Rectangle maximizedBounds = new Rectangle(x, y, w, h);

      System.out.println("cfg (" + cfg + ") screen.{bounds: " + screenBounds + ", insets: " + screenInsets + ", maxBounds: " + maximizedBounds);

      super.setMaximizedBounds(maximizedBounds);
    }
    super.setExtendedState(state);
  }

在简单的 JFrame 上:

  • 最大化左侧屏幕(“screen=0”)将打印 cfg (D3DGraphicsConfig[dev=D3DGraphicsDevice[screen= 0],pixfmt=0]) 屏幕。{边界: java.awt.Rectangle[x=-1920,y=0,width=1920,height=1080],插图:java.awt.Insets[top=0,left=0,bottom=30,right=0],maxBounds:java.awt.Rectangle[x=0,y=0,width=1920,height=1050]< /code>
  • 在右侧屏幕上最大化(“screen=1”)将打印 cfg (D3DGraphicsConfig[dev=D3DGraphicsDevice[screen=1],pixfmt=0]) screen.{bounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1080],插图:java.awt .Insets[顶部=0,左侧=0,底部=30,右侧=0],最大边界: java.awt.矩形[x=0,y=0,宽度=1920,高度=1050]

Fortega answer worked however, some part is not needed (or no longer needed with Java 8):

  • The Rectangle does not need to be saved.
  • The code does not take into account dual screen configuration. In particular, the GraphicsConfiguration will change if the window change screen.
  • As far as I tested, the only required override is setExtendedState.

When factoring dual screen configuration, at least on Windows, the below code does not work as intended:

Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, 
                                    screenInsets.top + screenSize.y, 
                                    screenSize.x + screenSize.width - screenInsets.right - screenInsets.left,
                                    screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top);

On the following dual screen set up:

  • Left screen 1920x1080 (not primary), position: -1920, 0
  • Right screen 1920x1080 (primary), position: 0, 0

The maxBounds will contains negative x (-1920) but the setMaximizedBounds is somehow expecting a coordinate in the screen space (where (x,y) starts at (0,0)) , not the virtual screen:

  • It will set to setMaximizedBounds(x=-1920,y=0,width=1920,height=1050)
  • Windows will see the window on the left screen (because I have one taskbar per screen showing only window on that screen) however the window won't be shown on the screen because it is off bounds.
  • If the resolution of the screen, or worse, its scale factor (with a laptop, Windows 10 will apply a scale factor, ex: 25%, making the screen "not so" 1920x1080), then the above code does not adapt. For example, if my configuration have 3 screens with the right most being the primary, the window will badly display on the left and middle screen. I don't think I fixed this in the below code.

The following code work on Windows, with dual screen:

  @Override
  public synchronized void setExtendedState(final int state) {
    if ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
      final GraphicsConfiguration cfg = getGraphicsConfiguration();
      final Insets screenInsets = getToolkit().getScreenInsets(cfg);
      final Rectangle screenBounds = cfg.getBounds();
      final int x = screenInsets.left + screenBounds.x * 0;
      final int y = screenInsets.top + screenBounds.y * 0;
      final int w = screenBounds.width - screenInsets.right - screenInsets.left;
      final int h = screenBounds.height - screenInsets.bottom - screenInsets.top;
      final Rectangle maximizedBounds = new Rectangle(x, y, w, h);

      System.out.println("cfg (" + cfg + ") screen.{bounds: " + screenBounds + ", insets: " + screenInsets + ", maxBounds: " + maximizedBounds);

      super.setMaximizedBounds(maximizedBounds);
    }
    super.setExtendedState(state);
  }

On a simple JFrame:

  • Maximizing on the left screen ("screen=0") will print cfg (D3DGraphicsConfig[dev=D3DGraphicsDevice[screen=0],pixfmt=0]) screen.{bounds: java.awt.Rectangle[x=-1920,y=0,width=1920,height=1080], insets: java.awt.Insets[top=0,left=0,bottom=30,right=0], maxBounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1050]
  • Maximizing on the right screen ("screen=1") will print cfg (D3DGraphicsConfig[dev=D3DGraphicsDevice[screen=1],pixfmt=0]) screen.{bounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1080], insets: java.awt.Insets[top=0,left=0,bottom=30,right=0], maxBounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1050]
乖乖 2024-11-23 07:48:18

也许您可以设置jFrame的最大尺寸并根据屏幕尺寸进行限制。

编辑

另请查看 设置扩展状态

Maybe you can set the maximum size of the jFrame and restrict it according to the screen size.

EDIT

Also check out setExtendedState

负佳期 2024-11-23 07:48:18

从 Fortega 答案开始,即使添加 125% 屏幕尺寸,您也可以使其正常工作

Rectangle screenSize = getGraphicsConfiguration().getBounds();
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
screenSize.setSize(new Dimension(gd.getDisplayMode().getWidth(), gd.getDisplayMode().getHeight()));
......

Starting from Fortega answer, you can make it work even with 125% screen sizi adding

Rectangle screenSize = getGraphicsConfiguration().getBounds();
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
screenSize.setSize(new Dimension(gd.getDisplayMode().getWidth(), gd.getDisplayMode().getHeight()));
......
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文