How to properly refresh image in JFrame?

前端 未结 2 837
无人及你
无人及你 2021-01-26 03:17

This is a problem that disturbs me for few hours now and I\'m not able to find a solution by myself...

I\'ve found similar topics all around the net, but I couldn\'t fin

2条回答
  •  花落未央
    2021-01-26 03:38

    This is what I came up with:

    private static class MyJPanel extends JPanel {
        private Image img = null;
    
        public MyJPanel() {}
    
        public void setImage(Image value) {
            if (img != value) {
                Image old = img;
                this.img = value;
                firePropertyChange("image", old, img);
                revalidate();
                repaint();
            }
        }
    
        public Image getImage() {
            return img;
        }
    
        @Override
        public Dimension getPreferredSize() {
            return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this));
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
    
                int width = getWidth();
                int height = getHeight();
                double scaleFactor = getScaleFactorToFit(new Dimension(img.getWidth(this), img.getHeight(this)), getSize());
                int x = (int) ((width - (img.getWidth(this) * scaleFactor)) / 2);
                int y = (int) ((height - (img.getHeight(this) * scaleFactor)) / 2);
    
                AffineTransform at = new AffineTransform();
                at.translate(x, y);
                at.scale(scaleFactor, scaleFactor);
                g2d.setTransform(at);
                g2d.drawImage(img, 0, 0, this);
                g2d.dispose();
            }
        }
    
        public double getScaleFactor(int iMasterSize, int iTargetSize) {
            return (double) iTargetSize / (double) iMasterSize;
        }
    
        public double getScaleFactorToFit(Dimension original, Dimension toFit) {
            double dScale = 1d;
            if (original != null && toFit != null) {
                double dScaleWidth = getScaleFactor(original.width, toFit.width);
                double dScaleHeight = getScaleFactor(original.height, toFit.height);
                dScale = Math.min(dScaleHeight, dScaleWidth);
            }
            return dScale;
        }
    }
    
    private static class MyJFrame extends JFrame implements Runnable {
        private BufferedImage img = null;
        private MyJPanel panel = null;
    
        public MyJFrame(BufferedImage image, String title) {
            super(title);
            img = image;
        }
    
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {}
    
            panel = new MyJPanel();
            panel.setImage(img);
    
            setLayout(new BorderLayout());
            add(BorderLayout.CENTER, panel);
            setLocation(200, 200);
            setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            pack();
            setVisible(true);
        }
    
        public void changeImage(BufferedImage image) {
            if ((panel != null) && (panel.getImage() != image)) panel.setImage(image);
        }
    }
    

    It's pretty much straightforward copy-paste from example that @MadProgrammer provided.

    The only thing left is EDT usage, which is rather magic for me. I'm still invoking this code using dirty way:

    MyJFrame mjf = null;
    javax.swing.SwingUtilities.invokeLater(mjf = new MyJFrame(buffer, "RDP"));
    ...
    mjf.changeImage(buffer);
    

    My question is: how do I use changeImage method with EDT?

提交回复
热议问题