如何将 "proper" 图像(不是图标)添加到我的 JFrame/JPanel/JComponents (Swing) (Kotlin)

How can I add "proper" images (not Icons) to my JFrame/JPanel/JComponents (Swing) (Kotlin)

语言:科特林, GUI 库:Swing, IDE:IntelliJ IDEA

我知道有类似措辞的问题,但请注意,我想向包含其他组件的任何类型的 JComponent 添加多张图像,而不仅仅是一张图像。例如,我不关心将图像添加到 JLabel,我已经知道该怎么做。我想知道如何将图像添加到 JFrame、JPanel、Container 等;所有包含其他组件(并具有 add(Component) 功能)的东西。最后,我不希望将图像添加到没有文本的 JLabel,然后将其添加到容器中。我只想使用图像 class 或像 BufferedImage 或 URL.

这样的子集

我希望能够从 Container class、jFrame.add(component) 调用 add() 方法,例如,其中 component 是某种图像。我希望这会导致图像显示在屏幕上。 ImageIcon class 不是组件,因此不能单独输入。我想我必须创建某种从 Component 或 JComponent 扩展的自定义图像 class,但我不知道我必须重写什么才能在添加到另一个 JComponent 时在屏幕上显示图像.对此有多种解决方案,但需要澄清的是,我不希望在我添加 JLabel 或 JButton 或仅包含图标的地方使用某种 "middle man"。反正我不想显示图标,我想在屏幕上的任何地方显示全尺寸图像。我将提供一个可能的示例,说明我希望最终结果是什么样子。

class MyApp() {

    fun init() {
        var jFrame = JFrame()
        jFrame.add(Image("filepath/image.png"))
        //Some other JFrame boiler plate
        jFrame.isVisible = true
    }

}

fun main() {
    MyApp().init()
}

不清楚的部分是图像 class,以及它是否是继承 JImage 的自定义 class,或者一些已经定义的 class 或我不知道的方法。我知道 ImageIO 和 BufferedImage 和 ImageIcon,但是 none 它们直接进入这个方法,因为它们不继承 Component 或 JComponent。

编辑:

我尝试使用 Camickr 的第二种解决方案,但没有用。我将 post 代码看是否犯了一个简单的错误。

import java.awt.Image as AWTImage
import java.awt.Image.*
//Including these imports as I used name alias so I had to say what it was from.

open class JImage(var point: Point = Point(0, 0), image: AWTImage): JComponent() {
    var image: ImageIcon = ImageIcon(image)

    override fun paintComponent(g: Graphics?) {
        super.paint(g)
        g?.drawImage(image.image, point.x.toInt(), point.y.toInt(), null)
    }
}

class SplashScreen(image: JImage): Frame() {

    init {
        //jFrame.isUndecorated = true
        jFrame.add(image)
    }
}

class MyApp {

    fun init() {
        var jFrame = SplashScreen(JImage(image = ImageIO.read(Loader().getClassLoader().getResourceAsStream("resources/images/splashscreen/SplashScreen.png"))).getScaledInstance(Size(1000, 1000*3/5)))
        jFrame.isVisible = true
    }
}

fun main() {
    MyApp().init()
}

最终编辑:

好的,所以我在尝试这个解决方案时确实犯了一个简单的错误。我覆盖了 paintComponent() 但随后在其中调用了 super.paint()。此外,我意识到我不必使用 ImageIcon class,反正我也不想这样做。这是我想出的图像 class。

open class JImage(var point: Point = Point(0, 0), var image: AWTImage): JComponent() {

    fun getScaledInstance(size: Size, scalingMethods: ScalingMethods = ScalingMethods.DEFAULT): JImage {
        val scale: Int = when(scalingMethods) {
            ScalingMethods.DEFAULT -> SCALE_DEFAULT
            ScalingMethods.FAST -> SCALE_FAST
            ScalingMethods.AREA_AVERAGING -> SCALE_AREA_AVERAGING
            ScalingMethods.REPLICATE -> SCALE_REPLICATE
            ScalingMethods.SMOOTH -> SCALE_SMOOTH
        }
        return JImage(point, image.getScaledInstance(size.width.toInt(), size.height.toInt(), scale))
    }

    override fun paintComponent(g: Graphics?) {
        super.paintComponent(g)
        g?.drawImage(image, point.x.toInt(), point.y.toInt(), null)
    }
}

I want to know how to add an image to a JFrame, JPanel, Container, etc.

您不会将图像添加到 JFrame、JPanel 等。正如您所说,图像不是组件。您将图像添加到 JLabel 并将标签添加到面板。这是以实际大小显示图像的最简单、更直接的方法。

不知道 Kotlin 是否有任何不同,但另一种选择是通过覆盖 paintComponent(…) 方法并使用 Graphics.drawImage(…) 方法,然后将面板添加到框架中。阅读 Custom Painting 上的 Swing 教程,了解绘画基础知识。

您还可以查看 Background Panel 将图像绘制为面板背景的示例。图片可以是:

  1. 按实际尺寸绘制
  2. 缩放以填充面板
  3. 平铺填充面板 请注意,不应在 paintComponent() 方法中读取图像,因为绘画代码应该是高效的。