8

我将 sbt 用于一个简单的小型 GUI 项目,该项目从src/main/scala/resources. 起初,一切正常,我可以compilepackage, 和run. 生成的 jar 和 class 文件中都有资源文件夹。然后我执行clean命令。我重新运行compileand package,突然应用程序崩溃了。我检查了生成的jar和classes,发现这次resources没有复制文件夹。

现在运行应用程序可以让我NullPointerException指向加载资源的行(图标)。

我没有更改 sbt 构建文件或项目中的任何内容。只需运行clean并重新运行compilepackage. 我不知道从哪里开始寻找问题。我应该从哪里开始寻找?我究竟做错了什么?

编辑(最小的例子)

该项目是来自 typesafe 的 g8 ( https://github.com/typesafehub/scala-sbt.g8 ) 的标准 Scala 模板。这是我的Build.Scala

import sbt._
import sbt.Keys._

object ObdscanScalaBuild extends Build {
  val scalaVer = "2.9.2"

  lazy val obdscanScala = Project(
    id = "obdscan-scala",
    base = file("."),
    settings = Project.defaultSettings ++ Seq(
      name := "project name",
      organization := "thesis.bert",
      version := "0.1-SNAPSHOT",
      scalaVersion := scalaVer,
      // add other settings here

      // resolvers

      // dependencies
      libraryDependencies ++= Seq (
        "org.scala-lang" % "scala-swing" % scalaVer,
        "org.rxtx" % "rxtx" % "2.1.7"
      )
    )
  )
}

它以前可以很好地构建代码。这是项目代码目录结构:

在此处输入图像描述

它工作正常,首先在 jar 中输出这个目录:

在此处输入图像描述

突然之间,当我通过 sbt 控制台执行cleanandcompile命令时,它不再复制 jar 或类目录(目标内部)中的资源目录。我现在无法将资源目录复制到目标,除非恢复以前的版本并再编译一次。我通过 Windows 的历史备份恢复以前的版本。

够清楚吗?我需要补充什么吗?

编辑:

将文件移动到 后src/main/resources,编译后的文件现在包含资源。但是现在,我不能在eclipse中运行它。这是我的代码:

object ControlPanelContent {
  val IconPath = "/icons/"
  val DefaultIcon = getClass.getResource(getIconPath("icon"))

  def getImage(name: String) = {
    getClass.getResource(getIconPath(name))
  }

  def getIconPath(name: String) = {
    IconPath + name + ".png"
  }
}

case class ControlPanelContent(title: String, iconName: String) extends FlowPanel {
  name = title
  val icon: ImageIcon = createIcon(iconName, 64)

  val pageTitle = new Label(title)

  protected def createIcon(name: String, size: Int): ImageIcon = {
    val path: Option[URL] = Option(ControlPanelContent.getImage(name))

    val img: java.awt.Image = path match {
      case Some(exists) => new ImageIcon(exists).getImage
      case _            => new ImageIcon(ControlPanelContent.DefaultIcon).getImage
    }
    val resizedImg = img.getScaledInstance(size, size, Image.SCALE_SMOOTH)
    new ImageIcon(resizedImg)
  }
}

TLDR 版本是这样的,我猜:

getClass.getResource("/icons/icon.png")

如果我从sbt console命令中调用,它会起作用。这是我从以下位置调用代码时的结果sbt console

scala> getClass.getResource("/icons/icon.png")
res0: java.net.URL = file:/project/path/target/scala-2.9.2/classes/icons/icon.png

运行时会出现以下异常:

Caused by: java.lang.NullPointerException
    at javax.swing.ImageIcon.<init>(Unknown Source)
    at thesis.bert.gui.ControlPanelContent.createIcon(ControlPanel.scala:54)
    at thesis.bert.gui.ControlPanelContent.<init>(ControlPanel.scala:33)
    at thesis.bert.gui.controls.DTC$.<init>(Diagnostics.scala:283)
    at thesis.bert.gui.controls.DTC$.<clinit>(Diagnostics.scala)
    ... 60 more

编辑 2:它现在可以工作了。我刚刚从 Eclipse 中删除了该项目,重新运行sbt eclipse,它神奇地工作。不知道为什么(也许是缓存?)。

4

1 回答 1

8

资源的 SBT 约定是将它们放入src/main/resources/,而不是src/main/scala/resources/. 尝试将您的resources文件夹上移一级。然后应该包含它的内容,这意味着您将在生成的 jar 文件中获取iconsindicator文件夹(直接在根级别,而不是在resources文件夹中)。

如果您将资源放在 scala 中,我认为它只复制已编译的文件(即.class由 scala 编译产生的文件)。

如果它不能解决您的问题,您可以发布用于加载资源的代码行吗?

于 2012-11-25T19:35:57.240 回答