在多显示器上居中Java启动画面

3

我正在使用SplashScreen类为Java应用程序创建启动画面。问题在于,在多监视器系统上的位置是未定义的。文档中指出,“多监视器系统上的位置未指定 - 它取决于平台和实现”。该应用程序仅在多监视器平台上使用,并且我希望确保它始终居中于其中一个屏幕。有没有办法实现这一点?该应用程序将仅在Linux上使用,因此平台在各处都相同。


内置的启动画面是在“Java虚拟机(JVM)启动之前”显示的。您无法改变它的位置。btad给出了一个合理的答案,但请注意我的评论。 - kdgregory
5个回答

5
这是一个JavaFX中等效的启动画面示例。然而,这个启动画面基本上是一个Java Swing小应用程序,由JavaFX调用并显示给用户,使用进度条和已加载内容的标题来模拟Eclipse和Netbeans的启动画面。

以下是链接:http://0divides0.wordpress.com/2011/03/17/splash-screen-with-javafx/

你需要获取代码并将其中在Java Swings中编写的启动画面代码分离出来并用于自己的项目。

这是一个定制的Java Swing启动画面。因此,为了居中显示启动画面,它使用了传统功能。

 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
 Dimension labelSize = l.getPreferredSize();
 setLocation(screenSize.width / 2 - (labelSize.width / 2), screenSize.height / 2 - (labelSize.height / 2));

1

那就不要使用Java 6中内置的启动画面。使用您的UI工具包创建自己的启动画面,并通过计算其大小和可用屏幕的大小来手动定位窗口。


我已经尝试过这个方法,只要在创建GUI的其余部分之前,在单独的线程中加载启动画面,它就能正常工作。然而,加载GUI的代码的最后一行却破坏了这个方法。我调用KeyboardFocusManager.getCurrentKeyboardFocusManager() .setGlobalCurrentFocusCycleRoot(pane); 将"pane"设置为焦点循环根节点,这是必须的。但是,一旦将这行代码添加到我的GUI构建代码的末尾,启动画面只会显示为一个灰色的方块。这就是为什么我转向使用SplashScreen类的原因(我想这应该是最佳实践)。 - Bulgur
1
我认为在使用内置的启动画面时,你是无法绕过它的。这是一个在所有操作系统上工作的Java解决方案互操作性的缺点之一。但你有考虑过使用SwingUtilities.invokeAndWait()来序列化GUI的创建和处理,以便提前设置启动画面吗?还有一些教程可用于创建基于AWT/Swing等的启动画面。 http://www.javaworld.com/javaworld/javatips/jw-javatip104.html http://www.randelshofer.ch/oop/javasplash/javasplash.html 等等。 - b_erb
首先:不要在单独的线程中管理Swing组件。它们只能从事件分派线程更新,你可能正因为这个原因而得到灰色的框框。 - kdgregory
第二点:启动画面的目的是为了覆盖应用程序的启动时间。在Java被用于小程序时代,通过56k调制解调器下载类文件占据了大部分的启动时间。在那个时代,加载一个启动画面在JVM之前是非常合理的。而在今天的世界中,更加合理的做法是在应用程序启动时立即创建一个自定义的无装饰启动窗口;基本的Swing类加载时间只需要几分之一秒。 - kdgregory

0
另一个示例代码:
 // Get the size of the screen
 Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
 // Determine the new location of the window
 int w = login.getSize().width;
 int h = login.getSize().height;
 int x = (dim.width-w)/2;
 int y = (dim.height-h)/2;
 // Move the window
 setLocation(x, y);
 setVisible(true);

1
不需要计算那么多。一旦JWindow或无装饰的JFrame被打包,调用setLocationRelativeTo(null)将使其居中显示在第一个屏幕上。 - Queeg

0
一个在屏幕上居中显示框架的不同解决方案:
    GraphicsConfiguration c = frm.getGraphicsConfiguration();
    Rectangle in = c.getBounds();

    int center_x = in.x + in.width / 2;
    int center_y = in.y + in.height / 2;

    frm.setLocation(center_x - frm.getWidth()/2, center_y - frm.getHeight()/2);

使用接受的解决方案时,我遇到了一个问题,即窗口显示在我的两个屏幕边缘,也就是两个屏幕的中心位置。

我曾经遇到过完全相同的问题。但是没有必要计算那么多。一旦JWindow或者无装饰的JFrame被打包,调用setLocationRelativeTo(null)将会使其居中显示在第一个屏幕上。 - Queeg

0

在Java的上下文中可能没有定义,但在显示服务器的上下文中肯定有定义。

对于Linux / X11来说,重要的是XInerama是否启用。这个X扩展使应用程序能够了解组成桌面的物理显示器。

验证XInerama是否启用的一种快速方法是尝试将窗口最大化到多监视器目标系统上。如果启用了XInerama,则窗口应该只会最大化到活动监视器的尺寸,而不是整个屏幕表面。

当启用XInerama时,启动应用程序时的闪屏将居中显示在活动监视器上。

如果你只关注确保应用程序的闪屏正确定位,你很快就会得到其他多监视器问题的反馈,比如任务栏跨越所有屏幕或窗口最大化跨越所有屏幕等。


这是不正确的。根据您的测试,我的桌面上启动画面是居中显示的,而且在两个屏幕上各占50%的位置。 - Queeg
问题主要出在JDK上,启动画面的居中位置不正确,但是调用JFrame.setLocationRelativeTo(null)方法可以将其定位在第一个屏幕的中心位置。 - Queeg

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