应用程序的部分神秘地无法重新绘制

时间:2013-12-07 16:35:54

标签: java swing panel jscrollpane repaint

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

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

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

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

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

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

I move the scroll-bar, the image is not properly repainted

Now I resize the application itself by a tiny amount, everything is correctly repainted

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)
  }

}

1 个答案:

答案 0 :(得分:2)

滚动窗格的工作原理基于添加到滚动窗格的组件的首选大小。您正在进行自定义绘制,但未为组件提供首选大小。

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

无论如何,只需使用JLabel显示图像并将标签添加到滚动窗格。标签将根据图像的大小自动确定其自身的首选大小。