【问题标题】:Debug SplashScreen from Eclipse without generating the Jar从 Eclipse 调试 SplashScreen 而不生成 Jar
【发布时间】:2011-10-17 21:19:30
【问题描述】:

我在网上搜索过,但找不到这个问题的答案:

我需要调试根据您正在访问的模块更改 SplashScreen 的应用程序的功能。

我确实知道代码:

SplashScreen splash = SplashScreen.getSplashScreen();

当你通过时可以用来获取实例:

  • 从命令行启动:java -splash:path/image.gif 类文件
  • 清单中的初始图像:splashscreen-image: img/SplashNomina.gif

当我尝试通过从 Eclipse 中的 VM args 传递 -splash 值来运行应用程序时,它仍然不起作用。

实际上是否可能,因为 SplashScreen.getSplashScreen() 始终为 NULL。 我一直在尝试通过但没有成功:

  • -splash:image.gif
  • -Dsplash=image.gif

现在我看到这个 Splash api 有很多限制,因为它总是需要传递一个参数。我认为能够在运行时传递参数会更加灵活:(

任何帮助将不胜感激!

【问题讨论】:

  • 您是否在 Run Configuration 中尝试过 VM Arguments
  • 是的,我已经尝试从那里实际传递参数。似乎问题在于 -splash:image 参数依赖于位于同一目录中的文件,我试图将图像包含在 Jar 文件中。
  • 对不起,我看错了。您也可以试试这个utility 来验证SplashScreen-Image 属性原位

标签: java eclipse debugging swing splash-screen


【解决方案1】:

好吧,伙计们,我决定走我独立的路,因为 Splash 类太单一,所以我把我的类放在这里:

import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class SplashWindow extends JFrame {

  private static final long serialVersionUID = 9090438525613758648L;

  private static SplashWindow instance;

  private boolean paintCalled = false;

  private Image image;

  private SplashWindow(Image image) {
    super();
    this.image = image;
    JLabel label = new JLabel();
    label.setIcon(new ImageIcon(image));
    this.add(label);    
    this.setUndecorated(true);
    this.setAlwaysOnTop(true);
    this.pack();
    this.setLocationRelativeTo(null);

  }

  public static void splash(URL imageURL) {
    if (imageURL != null) {
      splash(Toolkit.getDefaultToolkit().createImage(imageURL));
    }
  }

  public static void splash(Image image) {
    if (instance == null && image != null) {
      instance = new SplashWindow(image);
      instance.setVisible(true);

      if (!EventQueue.isDispatchThread() && Runtime.getRuntime().availableProcessors() == 1) {

        synchronized (instance) {
          while (!instance.paintCalled) {
            try {
              instance.wait();
            } catch (InterruptedException e) {
            }
          }
        }
      }
    }
  }

  @Override
  public void update(Graphics g) {
    paint(g);
  }

  @Override
  public void paint(Graphics g) {
    g.drawImage(image, 0, 0, this);
    if (!paintCalled) {
      paintCalled = true;
      synchronized (this) {
        notifyAll();
      }
    }
  }

  public static void disposeSplash() {
    instance.setVisible(false);
    instance.dispose();
  }
}

希望它对某人有所帮助;)

【讨论】:

    【解决方案2】:

    好吧,我也被这个咬了。

    我构建了一个可运行的 jar 带有清单条目

    SplashScreen-Image: MyGraphic.jpg
    

    它按预期工作。

    在 Eclipse 中,将 VM arg 指定为

    -splash:MyGraphic.jpg
    

    没有这样的运气

    SplashScreen.getSplashScreen() 返回 null。

    原因是 JDK(至少 1.6)中 SplashScreen.getSplashScreen() 的脑死实现。我想。如果不深入了解本机代码在做什么,就很难说清楚。但是,这是来自 java.awt.SplashScreen 的这个方法。我不确定它是否被调用,但研究它确实为我提供了在 Eclipse 中使用它所需的基本线索:

    public synchronized URL getImageURL() throws IllegalStateException {
        checkVisible();
        if (imageURL == null) {
            try {
                String fileName = _getImageFileName(splashPtr);
                String jarName = _getImageJarName(splashPtr);
                if (fileName != null) {
                    if (jarName != null) {
                        imageURL = new URL("jar:"+(new File(jarName).toURL().toString())+"!/"+fileName);
                    } else {
                        imageURL = new File(fileName).toURL();
                    }
                }
            }
            catch(java.net.MalformedURLException e) {
                // we'll just return null in this case
            }
        }
        return imageURL;
    }
    

    请注意,对于文件(即命令行而不是 jar 启动),它不会执行 getResource() 来获取 URL,而是打开相对于 CWD 的文件。由于 Eclipse 运行配置默认从项目的根目录运行,因此答案是将路径指定为相对路径,而不是期望类路径查找。

    因此,由于我是使用 maven 构建的,所以我的图像位于 src/main/resources/MyGraphic.jpg。将此指定为命令行参数:即

    -splash:src/main/resources/MyGraphic.jpg 
    

    允许它在 Eclipse(或者,我猜,任何命令行)中工作

    我不确定为什么会这样,因为 getSplashScreen() 不会调用 getImageURL 方法,但它确实有效。

    对我来说,这对于 Sun/Oracle 来说有点脑残。他们可以很容易地使用类似的东西进行类路径查找 imageURL = getResource(filename) 但他们没有。

    简短的回答是,启动画面命令行语法是指相对于当前工作目录的文件名,而不是相对于类路径。

    【讨论】:

    • 对此进行了很好的分析。感谢您为解释此事所做的努力,如果没有您的回答,您仍然会一头雾水。 :)
    【解决方案3】:

    我在 3 年后回答,但我遇到了同样的问题,我试图解决。 我找到了解决方案,我认为它对每个人都有用。

    您必须创建一个启动配置,在 VM 参数 中指定参数 -splash:image.gif。这个参数是指项目的根目录(不是/bin或/src)。所以你必须把你的图片和 /bin 和 /src 放在同一级别(或者你可以在 -splash 选项中指定不同的路径)。

    当您从“export”导出可运行 JAR 并指定您之前创建的启动配置时,它会显示“不能包含 VM 参数,您必须从命令行指定”(并且它不包含您的 image.gif在根中)。 因此,如果您想使用您的启动图像有一个可运行的 jar,您可以参考 stackoverflow 上的另一个主题,我不再找到该主题。有人回答说最好的解决方案是 FatJar。您可以进行如下操作:导出 > 其他 > fat jar 导出器。勾选“选择清单文件”,指定包含“SplashScreen-Image: splash.gif”的 MANIFEST.MF(如果您不知道如何创建,请取消选中此复选框,使用默认创建一个 jar,修改创建的包括它)。在导出的下一页中,请务必使用“添加目录”按钮将您的图像包含在 jar 中(它包含指定到项目根目录的目录的内容,因此请注意清单中的目录)。 它对我有用。

    因此,如果您想使用 eclipse 运行,请将启动图像添加到根目录并在 VM 参数中指定 -splash:image.gif。如果您想导出 JAR,FatJar 插件可以按照我的说明为我工作。

    希望对你有帮助:)

    (对不起我的英语,我不是英语:P)

    【讨论】:

    • 非常感谢您的回答,这是否是 3 年前的问题并不重要,因为有些人可能刚刚遇到这个问题,您的贡献非常有价值! :)
    猜你喜欢
    • 2012-09-12
    • 1970-01-01
    • 2021-10-14
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    相关资源
    最近更新 更多