从 Eclipse 调试 SplashScreen 而不生成 Jar

Posted

技术标签:

【中文标题】从 Eclipse 调试 SplashScreen 而不生成 Jar【英文标题】:Debug SplashScreen from Eclipse without generating the 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 属性原位 【参考方案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,您可以参考 *** 上的另一个主题,我不再找到该主题。有人回答说最好的解决方案是 FatJar。您可以进行如下操作:导出 > 其他 > fat jar 导出器。勾选“选择清单文件”,指定包含“SplashScreen-Image: splash.gif”的 MANIFEST.MF(如果您不知道如何创建,请取消选中此复选框,使用默认创建一个 jar,修改创建的包括它)。在导出的下一页中,请务必使用“添加目录”按钮将您的图像包含在 jar 中(它包含指定到项目根目录的目录的内容,因此请注意清单中的目录)。 它对我有用。

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

希望对你有帮助:)

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

【讨论】:

非常感谢您的回答,这是否是 3 年前的问题并不重要,因为有些人可能刚刚遇到这个问题,您的贡献非常有价值! :)

以上是关于从 Eclipse 调试 SplashScreen 而不生成 Jar的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Eclipse 调试 hadoop mapreduce 作业?

从 IntelliJ 调试 Eclipse Wildfly

无法直接从 Eclipse 到设备调试 android 应用程序

如何从 Eclipse 运行和调试 JBoss EAP 6?

如何从 Eclipse 调试木兰花模块应用程序?

如何从插件访问 Eclipse Java 调试器?