java - 内部内容在 JScrollPane 中显示然后消失

标签 java swing jpanel jscrollpane

我的问题与带有内部 JPanelJScrollPane 有关。我尝试在 JPanel 上绘图,但它会短暂出现然后消失,直到我手动移动 Horizo​​ntalScrollBar,然后再次出现并保持稳定。为了避免手动干预(或在实际代码中很难管理的 Horizo​​ntalScrollBar.setValue),我在 上尝试了 validate/revalidate (以及更多),但没有成功。 JPanelViewportJScrollPaneJFrame

下面的(非常)简化的代码重现了该问题。可能是显而易见的东西,但我看不到。

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

好的..

  1. Graphics2D g2 = (Graphics2D)this.getGraphics(); 当您已经拥有有效的 Graphics 实例时,很难确定为什么您认为这是一个好主意。但基本上,使用提供的 Graphics 实例。
  2. ImageIO.read(..); 读取图像应该在任何绘制方法中完成。它应该在类的构造函数中加载一次。
  3. sub = image.getSubimage(0, 0, 1024, 768); 再说一次,您不想每次调用 Paint 时都执行此操作,事实上,它会更优化在照片编辑软件中创建正确尺寸的图像,然后加载裁剪图像。
  4. } catch (IOException e) {} 不要忽略异常!他们准确地告诉我们出了什么问题。除非实现了日志记录,否则至少要调用 Throwable.printStackTrace()
  5. if( sub!=null)g2.drawImage(sub, 0, 0, null); 因为每个 JComponent 都是一个 ImageObserver,应该是
    if( sub!=null)g2.drawImage(sub, 0, 0, this);

还有一些可疑的事情,但它们不是当前问题的一部分,因此它们没有改变:

  1. //pour reeindre la panel à chaque fois .. 法语中的代码注释(仅供人类使用)的意义是什么?请用英文填写代码注释(针对本网站)。否则它们就是噪音。
  2. this.setPreferredSize(new Dimension(1124, 768)); 可能最好重写 getPreferredSize() 并根据 (如直接从图像获取的数字。
  3. mainPane.setPreferredSize(new Dimension(1024, 768)); 这比 mainPane.pack(); 更好。后者不是猜测,并且将考虑子组件的首选大小。

关于java - 内部内容在 JScrollPane 中显示然后消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51223037/

相关文章:

java - 第二次设置JPanel对象的背景

java - 将 JPanel 添加到 JScrollPane

java - 调整 JFrame 大小以适应调整大小的 JPanel

java - 用 Java 创建可执行安装程序

java - 是否可以参数化 @BeforeEach,即根据每个 @Test 给出的参数调用不同的 @BeforeEach?

java - 生成对象的所有设置/获取

java - 在java struts中动态更改表页面大小

java - JComboBox 在单击之前不显示

java - 如何更新 JTable 中 DefaultTableModel 的行?

java - 使用数据库数据自动/手动设置列宽 JTable