【问题标题】:Parts of Application mysteriously fail to repaint部分应用程序神秘地无法重新绘制
【发布时间】:2013-12-07 16:35:53
【问题描述】:

我已经做了几个小时了,但没有取得任何进展。

我有一个非常简单的应用程序,它从磁盘加载一个大 (2000x2500px) 图像。

它加载到一个 JPanel 中,该 JPanel 包含在 JScrollPanel 中,而 JScrollPanel 又包含在最外面的 JPanel 中。

这段代码在 Scala 中,但对于 Java 开发人员来说应该很容易阅读。

当我移动滚动条时,应用程序会打印出正在重新绘制的指示,但图像部分是空白的。当我调整应用程序窗格的大小时,一切都正确绘制。

这是一个错误还是我错过了一些非常基本的东西?

import java.awt._
import java.util.Date
import javax.imageio.ImageIO
import javax.swing._

object DisplayAnImage {
  def main(args: Array[String]) = {
    val rackStream = DisplayAnImage.getClass.getResourceAsStream("racks.jpg")
    val bi = ImageIO.read(rackStream)
    val outerMost = new  JFrame("Image display")
    outerMost.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
    outerMost.setLayout(new BorderLayout())

    val imagePane = new JPanel(true) {
      val c = new Canvas() {
        override def paint(g: Graphics): Unit = {
          println(s"drawing the image ${new Date()}")
          g.drawImage(bi, 0, 0, null)
        }
      }
      c.setSize(bi.getWidth, bi.getHeight)
      this.add(c)
    }

    val scroller = new JScrollPane(imagePane)
    scroller.setAutoscrolls(true)

    outerMost.add(scroller, BorderLayout.CENTER)
    outerMost.pack()
    outerMost.setSize(300, 300)
    outerMost.setVisible(true)
  }

}

解决方案

感谢 camackr - 我将代码修改为以下,它更简单并且可以完美运行。

import java.awt._
import javax.imageio.ImageIO
import javax.swing._

object DisplayAnImage {
  def main(args: Array[String]) = {
    val rackStream = DisplayAnImage.getClass.getResourceAsStream("racks.jpg")
    val bi = ImageIO.read(rackStream)
    val outerMost = new  JFrame("Image display")
    outerMost.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
    outerMost.setLayout(new BorderLayout())

    val imagePane = new JPanel(true) {
      val jl = new JLabel() {
        override def paintComponent(g: Graphics): Unit = {
          g.drawImage(bi, 0, 0, null)
        }
        this.setPreferredSize(new Dimension(bi.getWidth,bi.getHeight))
      }
      this.add(jl)
    }

    val scroller = new JScrollPane(imagePane)
    scroller.setAutoscrolls(true)
    outerMost.add(scroller, BorderLayout.CENTER)
    outerMost.pack()
    outerMost.setSize(300, 300)
    outerMost.setVisible(true)
  }

}

【问题讨论】:

    标签: java swing panel jscrollpane repaint


    【解决方案1】:

    滚动窗格的工作基于添加到滚动窗格的组件的首选大小。您正在进行自定义绘画,但没有为您的组件提供首选尺寸。

    你为什么要做定制绘画?为什么要使用画布?为什么要覆盖paint(),自定义绘画是在使用Swing时通过覆盖paintComponent()来完成的。

    无论如何,只需使用 JLabel 来显示图像并将标签添加到滚动窗格。标签会根据图片的大小自动确定自己喜欢的大小。

    【讨论】:

    • 可以给出一个花哨的答案,但这主要是因为我在 10 年前做 AWT,然后在 6 年前读了一本 Swing 书,而且 API 非常庞大! ;-)
    • @binarytemple_picsolve,是的,而且 Swing 中有很多不同之处。您应该保留指向Swing Tutorial 的链接。
    • 感谢您的帮助,这真的让我很伤心。看了一下链接,很好的参考。我现在要去做 SplitPane 的事情了。
    猜你喜欢
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 2010-12-14
    • 2021-11-02
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多