【问题标题】:Inner content showing then disappearing in JScrollPane内部内容在 JScrollPane 中显示然后消失
【发布时间】:2018-07-07 12:04:34
【问题描述】:

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

下面的(非常)简化的代码重现了该问题。可能很明显,但我看不到。

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

【问题讨论】:

    标签: java swing jpanel jscrollpane


    【解决方案1】:

    代码有一些问题,这里是固定代码。解释见代码下方的点。

    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 repeindre la panel à chaque fois 法语中的代码注释(仅供人类使用)有什么意义?请用英文输入代码 cmets(用于本网站)。否则它们就是噪音。
    2. this.setPreferredSize(new Dimension(1124, 768)); 可能最好覆盖 getPreferredSize() 并根据 sub 图像的大小(如直接从中获得的数字)返回一个值。
    3. mainPane.setPreferredSize(new Dimension(1024, 768)); 这比mainPane.pack(); 更好。后者不是猜测,而是考虑子组件的首选大小。

    【讨论】:

    • 坦克很多!!有用。作为记录,请注意故障部分是 Graphics2D g2。使用常规图形解决了这个问题,而无需更改任何其他内容。现在我必须在代码的其他地方创建具有厚度的多线(这部分已从简化版本中删除)。无论如何,这很棒。再次感谢(我也可以用多种嘈杂的方式说出来 ;-))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多