在Linux上全屏Java——如何覆盖任务栏?

13

我在 "openSUSE 11.4 (x86_64)" 上运行Java应用程序的全屏模式时遇到了问题。我正在使用Java 1.6.0_26-b03。

我尝试运行了两个全屏应用程序示例:

  1. 来自Oracle网站的示例:显示模式测试(Display Mode Test)
  2. Codealchemists下载的JDarkRoom.jar(简单文本编辑器)。

在这两种情况下,Linux任务栏都会出现在应用程序上方。可能与系统设置/配置有关?

5个回答

18
你应该能够使用GraphicsDevice.setFullScreenWindow (window)来实现真正的全屏。然而,由于最流行的Java运行时存在一些bug,这可能在运行某些“损坏”的1.6 = Java 6系列版本的系统上无法正常工作。我还没有进行全面的测试,所以可能补丁还没有传播到普通用户中。

https://bugs.java.com/bugdatabase/view_bug?bug_id=7057287

背景/理论

好的,这里有太多的信息,但是帮助不够... 这是为什么这个事情没有正确运作的一些原因...

没有 Linux 桌面 基于 Linux 的操作系统在 PC 类型的机器上,以及其他的 Unix 系统(部分例外是 MacOSX),通常使用 X 窗口系统(也称为 X11)。在 X 窗口系统中,你有一个 X 服务器(通常类似于“视频驱动程序”)和连接到它的客户端,往往是从同一台机器(回环)连接。
窗口的布局和位置由一个特殊的客户端程序,称为窗口管理器,控制。它负责装饰窗口(例如绘制标题栏或调整大小的手柄)和定位它们。
你的程序将是一个 X 客户端。它可以请求在屏幕上的特定位置或特定大小进行放置,但不能强制要求。各种窗口管理器更或少倾向于满足你的要求。 除此之外,大多数桌面都很友好 (有时候) 现在,迄今为止,大多数 Linux 桌面使用 Gnome 桌面,其次是 K 桌面,还有一些其他桌面在相当广泛的使用中。好在这两个桌面环境(以及其他一些如 XFCE 适用于低端 PC)都符合 FreeDesktop.org 窗口管理器提示标准。
(超级简化版:)通常,屏幕的一个或多个边缘会有面板。通常只有一个面板,位于顶部,但有很多变种。这些面板区域不被视为“屏幕的一部分”,因此窗口管理器会告诉你的应用程序:“不,那在你被允许操作的区域之外;这个屏幕不是 1920×1080,只有 1890×1080。”当然,这可能与你编写应用程序时预期的完全不同,你可能在我的上网本上,物理屏幕是 800×480,但假装只有 780×480。
对于 99% 的应用程序来说,这很好。窗口不会挡住面板,所以你总是可以访问面板上的关键控件,比如静音或切换到另一个程序等。
这些“提示”允许你请求对待你的顶级窗口进行特殊处理。例如,你可以请求没有标题栏,或者是一个简化的“调色板”类型的标题栏;你可以请求在窗口列表、任务栏、活动总览或其他用于显示活动窗口的界面中跳过你的应用程序;或者,你可以请求真正的全屏,将其他所有内容都挤到一边,甚至包括面板。
规范在这里:http://standards.freedesktop.org/wm-spec/wm-spec-latest.html

而失败:

基本上,Sun/Oracle(或者Red Hat,他们抄袭了Sun/Oracle,或者可能是IBM,因为他们可能也做了同样的事情,但我没有看到有人对他们抱怨)没有正确遵循窗口管理器提示规范...

尽管如此,我确实看到一些关于这是否是K Desktop Environment的窗口管理器(KWin)的错误(具体来说)的抱怨,因为显然这个错误只在K中出现,而不在Gnome、XFCE和其他桌面环境中出现。

解决方法

除了修补您的Java运行时(和/或您的客户端),唯一真正的解决方法就是使用特定于平台的Java库(也许使用反射获取底层的AWT对象...呃...)并自己设置正确的窗口提示。

是的,这很糟糕...


11

关于 bgroenks 方法的精确说明:
在 Ubuntu 14.10 (Unity) 上,使用 java7 和 java8 可以正常工作。

但是:您必须设置 frame.setResizable(true);,否则它不会起作用。

请注意:全屏模式仅适用于 JFrame(不适用于 JDialog 或 JWindow)。

这里有一个示例代码: 它取代了 setVisible(true)

/**
 * @param frame
 * @param doPack
 * @return device.isFullScreenSupported
 */
static public boolean fullScreen(final JFrame frame, boolean doPack) {

    GraphicsDevice device = frame.getGraphicsConfiguration().getDevice();
    boolean result = device.isFullScreenSupported();

    if (result) {
        frame.setUndecorated(true);
        frame.setResizable(true);

        frame.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent arg0) {
                frame.setAlwaysOnTop(true);
            }

            @Override
            public void focusLost(FocusEvent arg0) {
                frame.setAlwaysOnTop(false);
            }
        });

        if (doPack)
            frame.pack();

        device.setFullScreenWindow(frame);
    }
    else {
        frame.setPreferredSize(frame.getGraphicsConfiguration().getBounds().getSize());

        if (doPack)
            frame.pack();

        frame.setResizable(true);

        frame.setExtendedState(Frame.MAXIMIZED_BOTH);
        boolean successful = frame.getExtendedState() == Frame.MAXIMIZED_BOTH;

        frame.setVisible(true);

        if (!successful)
            frame.setExtendedState(Frame.MAXIMIZED_BOTH);
    }
    return result;
}

敬礼,Stéphane。


我成功地使其工作,而无需使用setResizable(true)和焦点侦听器。唯一遇到的问题是更改显示模式,通过使用DisplayMode.BIT_DEPTH_MULTIDisplayMode.REFRESH_RATE_UNKNOWN解决了这个问题。使用Java 8和Kubuntu 15.10。 - code_dredd
Smillien的方法对我在Ubuntu 16.04和Unity DE上起作用。 - Prime624

6

我知道这个问题有点老,但我正在寻找同样的答案。

经过很多实验,我想出了一个好的解决方案:

GraphicsDevice d = GraphicsEnvironment
    .getLocalGraphicsEnvironment().getDefaultScreenDevice();
if (d.isFullScreenSupported()) {
    frame.setUndecorated(true);
    frame.setResizable(false);
    frame.addFocusListener(new FocusListener() {

        @Override
        public void focusGained(FocusEvent arg0) {
            frame.setAlwaysOnTop(true);
        }

        @Override
        public void focusLost(FocusEvent arg0) {
            frame.setAlwaysOnTop(false);
        }
    });
    d.setFullScreenWindow(frame);
} else {
    frame.setVisible(true);
}

焦点监听器是为了使用户可以在不立即强制重新聚焦窗口的情况下ALT-TAB或META-D离开窗口。

这在我使用KDE 4的Linux Mint 15系统上运行良好。我还使用NVIDIA X-Server。

希望这能帮到你们!如果对你有用,请告诉我!


这种方法在我的Ubuntu 16.04和Unity桌面环境中不起作用。 - Prime624

2

以上方法都对我没有用,我使用的是XUbuntu。但我刚刚尝试使用JWindow而不是JFrame,它奏效了!这真是太令人沮丧了,希望对你有用。哦,我应该提一下,我还没有看过API,并且我对JWindow类并不熟悉,因此我不确定JWindow和JFrame之间的区别究竟是什么。祝好运。


1

我使用了 Oracle Java 版本 1.6.0_31 和 1.6.0_26 并启用了全屏模式。在 Ubuntu 上,我遇到了一些窗口没有显示在任务栏上面的问题。但是,我通过这个小代码示例成功解决了这个问题。

// Create a window for full-screen mode; add a button to leave full-screen mode
GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().
                    getDefaultScreenDevice(); 
                    //or initialize this for a specific display
Frame frame = new Frame(gs.getDefaultConfiguration());
Window win = new Window(frame);
Canvas c = new Canvas();
c.setBackground(Color.RED);
win.add(c);
win.show();  //or setVisible(true);

// Enter full-screen mode
gs.setFullScreenWindow(win);
win.validate();

行之有效的窍门是先使窗口可见,然后将窗口置于全屏模式。在显示窗口之前设置全屏模式会导致任务栏出现在窗口上方。


定义您的 gs 对象会更有帮助和完整。 - Roy Hinkley

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