内部内容在 JScrollPane 中显示然后消失
Inner content showing then disappearing in JScrollPane
我的问题与带有内部 JPanel
的 JScrollPane
有关。我尝试在 JPanel
上画画,但它出现的时间非常短暂,然后消失,直到我手动移动 HorizontalScrollBar
,然后再次出现并保持稳定。为了避免手动干预(或在实际代码中难以管理的 HorizontalScrollBar.setValue
),我在 JPanel
、Viewport
上尝试了 validate/revalidate
(以及更多),但没有成功。 JScrollPane
和 JFrame
.
下面的(非常)简化的代码重现了这个问题。可能很明显,但我看不到。
public class Main {
private JFrame mainPane;
private RenderZone renderZone = new RenderZone();
private JScrollPane renderScrollPane = new JScrollPane(renderZone,
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main window = new Main();
window.mainPane.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Main() {
initialize();
}
private void initialize() {
mainPane = new JFrame();
mainPane.setPreferredSize(new Dimension(1024, 768));
mainPane.setSize(new Dimension(1024, 768));
mainPane.setLocation(new Point(200, 200));
mainPane.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SpringLayout springLayout = new SpringLayout();
springLayout.putConstraint(SpringLayout.NORTH, renderScrollPane, 0, SpringLayout.NORTH, mainPane.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, renderScrollPane, 0, SpringLayout.WEST, mainPane.getContentPane());
springLayout.putConstraint(SpringLayout.SOUTH, renderScrollPane, 0, SpringLayout.SOUTH, mainPane.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, renderScrollPane, 0, SpringLayout.EAST, mainPane.getContentPane());
mainPane.getContentPane().setLayout(springLayout);
mainPane.getContentPane().add(renderScrollPane);
}
public class RenderZone extends JPanel {
private static final long serialVersionUID = -8240875812801921009L;
private BufferedImage image = null;
private BufferedImage sub = null;
public RenderZone() {
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(1124, 768));// added 100 for test purpose
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);// pour repeindre la panel à chaque fois
Graphics2D g2 = (Graphics2D)this.getGraphics();
if(image==null) {
try {
image = ImageIO.read(RenderZone.class.getResourceAsStream("TestImage0.png"));
sub = image.getSubimage(0, 0, 1024, 768);
} catch (IOException e) {}
}
if( sub!=null)g2.drawImage(sub, 0, 0, null);
g2.dispose();
}
}
}
代码有几处错误,这是修复后的代码。解释见代码下方的要点
public class RenderZone extends JPanel {
private static final long serialVersionUID = -8240875812801921009L;
private BufferedImage image = null;
private BufferedImage sub = null;
public RenderZone() {
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(1124, 768));// added 100 for test purpose
image = new BufferedImage(2000, 1000, BufferedImage.TYPE_INT_RGB);
sub = image.getSubimage(0, 0, 1024, 768);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);// pour repeindre la panel à chaque fois
if (sub != null) {
g.drawImage(sub, 0, 0, this);
}
}
}
好的..
Graphics2D g2 = (Graphics2D)this.getGraphics();
当您已经有了一个有效的 Graphics
实例时,很难确定为什么您认为这是个好主意。但基本上,使用提供的 Graphics
实例。
ImageIO.read(..);
读取图像 不是 应该在任何绘画方法中完成的事情。它应该在 class 的构造函数中加载一次。
sub = image.getSubimage(0, 0, 1024, 768);
同样,并不是每次调用 paint 时你都想做的事情,事实上,在照片编辑软件中以合适的尺寸创建图像会更优化,而且只是加载 裁剪后的 图像。
} catch (IOException e) {}
不要忽略异常!他们告诉我们究竟出了什么问题。除非实现日志记录,否则至少调用 Throwable.printStackTrace()
if( sub!=null)g2.drawImage(sub, 0, 0, null);
因为每个JComponent
都是一个ImageObserver
,所以应该是
if( sub!=null)g2.drawImage(sub, 0, 0, this);
还有一些可疑但不属于当前问题的部分,因此它们没有改变:
// pour repeindre la panel à chaque fois
.. 法语的代码注释(仅供人类使用)有什么意义?请用英文放置代码注释(针对此站点)。否则它们就是噪音。
this.setPreferredSize(new Dimension(1124, 768));
可能最好覆盖 getPreferredSize()
和 return 一个基于 sub
图像大小(如直接从中获取的数字)的值。
mainPane.setPreferredSize(new Dimension(1024, 768));
这比 mainPane.pack();
更好。后者不是猜测,将考虑子组件的首选大小。
我的问题与带有内部 JPanel
的 JScrollPane
有关。我尝试在 JPanel
上画画,但它出现的时间非常短暂,然后消失,直到我手动移动 HorizontalScrollBar
,然后再次出现并保持稳定。为了避免手动干预(或在实际代码中难以管理的 HorizontalScrollBar.setValue
),我在 JPanel
、Viewport
上尝试了 validate/revalidate
(以及更多),但没有成功。 JScrollPane
和 JFrame
.
下面的(非常)简化的代码重现了这个问题。可能很明显,但我看不到。
public class Main {
private JFrame mainPane;
private RenderZone renderZone = new RenderZone();
private JScrollPane renderScrollPane = new JScrollPane(renderZone,
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main window = new Main();
window.mainPane.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Main() {
initialize();
}
private void initialize() {
mainPane = new JFrame();
mainPane.setPreferredSize(new Dimension(1024, 768));
mainPane.setSize(new Dimension(1024, 768));
mainPane.setLocation(new Point(200, 200));
mainPane.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SpringLayout springLayout = new SpringLayout();
springLayout.putConstraint(SpringLayout.NORTH, renderScrollPane, 0, SpringLayout.NORTH, mainPane.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, renderScrollPane, 0, SpringLayout.WEST, mainPane.getContentPane());
springLayout.putConstraint(SpringLayout.SOUTH, renderScrollPane, 0, SpringLayout.SOUTH, mainPane.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, renderScrollPane, 0, SpringLayout.EAST, mainPane.getContentPane());
mainPane.getContentPane().setLayout(springLayout);
mainPane.getContentPane().add(renderScrollPane);
}
public class RenderZone extends JPanel {
private static final long serialVersionUID = -8240875812801921009L;
private BufferedImage image = null;
private BufferedImage sub = null;
public RenderZone() {
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(1124, 768));// added 100 for test purpose
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);// pour repeindre la panel à chaque fois
Graphics2D g2 = (Graphics2D)this.getGraphics();
if(image==null) {
try {
image = ImageIO.read(RenderZone.class.getResourceAsStream("TestImage0.png"));
sub = image.getSubimage(0, 0, 1024, 768);
} catch (IOException e) {}
}
if( sub!=null)g2.drawImage(sub, 0, 0, null);
g2.dispose();
}
}
}
代码有几处错误,这是修复后的代码。解释见代码下方的要点
public class RenderZone extends JPanel {
private static final long serialVersionUID = -8240875812801921009L;
private BufferedImage image = null;
private BufferedImage sub = null;
public RenderZone() {
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(1124, 768));// added 100 for test purpose
image = new BufferedImage(2000, 1000, BufferedImage.TYPE_INT_RGB);
sub = image.getSubimage(0, 0, 1024, 768);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);// pour repeindre la panel à chaque fois
if (sub != null) {
g.drawImage(sub, 0, 0, this);
}
}
}
好的..
Graphics2D g2 = (Graphics2D)this.getGraphics();
当您已经有了一个有效的Graphics
实例时,很难确定为什么您认为这是个好主意。但基本上,使用提供的Graphics
实例。ImageIO.read(..);
读取图像 不是 应该在任何绘画方法中完成的事情。它应该在 class 的构造函数中加载一次。sub = image.getSubimage(0, 0, 1024, 768);
同样,并不是每次调用 paint 时你都想做的事情,事实上,在照片编辑软件中以合适的尺寸创建图像会更优化,而且只是加载 裁剪后的 图像。} catch (IOException e) {}
不要忽略异常!他们告诉我们究竟出了什么问题。除非实现日志记录,否则至少调用Throwable.printStackTrace()
if( sub!=null)g2.drawImage(sub, 0, 0, null);
因为每个JComponent
都是一个ImageObserver
,所以应该是if( sub!=null)g2.drawImage(sub, 0, 0, this);
还有一些可疑但不属于当前问题的部分,因此它们没有改变:
// pour repeindre la panel à chaque fois
.. 法语的代码注释(仅供人类使用)有什么意义?请用英文放置代码注释(针对此站点)。否则它们就是噪音。this.setPreferredSize(new Dimension(1124, 768));
可能最好覆盖getPreferredSize()
和 return 一个基于sub
图像大小(如直接从中获取的数字)的值。mainPane.setPreferredSize(new Dimension(1024, 768));
这比mainPane.pack();
更好。后者不是猜测,将考虑子组件的首选大小。