【问题标题】:Why jframe hides taskbar when maximized?为什么jframe在最大化时隐藏任务栏?
【发布时间】:2011-06-21 09:13:34
【问题描述】:

我在我的 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();
    }
}

【问题讨论】:

标签: java swing jframe taskbar


【解决方案1】:

这是一个已知错误:http://bugs.sun.com/bugdatabase/view_bug.do?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);
}
}

【讨论】:

  • 为什么方法是同步的
  • 因为可以从两个不同的线程调用最大化帧。如果一个线程设置了 maxBounds 字段,而另一个线程在 setExtendedState 方法的中间(例如),你会得到奇怪的结果...
  • 顺便说一句,这不是我的代码......它是从上面链接中的答案之一复制而来的。
  • Swing 代码无论如何都应该从 EDT 执行。所以synchronized关键字可以去掉。
  • @Fortega:还有什么关于为什么将光标更改为<->
【解决方案2】:

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

  • Rectangle 不需要保存。
  • 代码未考虑双屏配置。特别是,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) 开始),而不是虚拟屏幕:

  • 它将设置为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]) 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]
  • 在右侧屏幕上最大化(“screen=1”)将打印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]

【讨论】:

    【解决方案3】:

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

    编辑

    也可以查看setExtendedState

    【讨论】:

      【解决方案4】:

      从 Fortega 回答开始,即使添加了 125% 的屏幕尺寸,您也可以使其工作

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-13
        • 2012-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多