How to disable java.awt.Graphics.fillRect(int x, int y, int width, int height)'s effect?

前端 未结 3 777
一生所求
一生所求 2020-12-21 18:13

It\'s the original image: \"enter

I use java.awt.Graphics.fillRect(int x, int y, int

3条回答
  •  梦毁少年i
    2020-12-21 18:49

    Remember, painting is destructive. It might be possible to use AlphaComposite to achieve this result, but a simpler solution might be to simple constructive a compound shape and paint that instead.

    The following example creates two Rectangles, one been the area we want to fill and one been the area we want to show, the second is then subtracted from the first (to create the window) and then the result is painted on top of the image

    Clipped

    import java.awt.AlphaComposite;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.geom.Area;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class ShowArea {
    
        public static void main(String[] args) {
            new ShowArea();
        }
    
        public ShowArea() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private BufferedImage img;
    
            public TestPane() {
                try {
                    img = ImageIO.read(new File("sample.png"));
                    Rectangle bounds = new Rectangle(0, 0, img.getWidth(), img.getHeight());
                    Rectangle clip = new Rectangle(150, 10, 100, 100);
    
                    Area area = new Area(bounds);
                    area.subtract(new Area(clip));
    
                    Graphics2D g2d = img.createGraphics();
                    g2d.setColor(Color.BLACK);
                    g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                    g2d.fill(area);
                    g2d.dispose();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
    
            @Override
            public Dimension getPreferredSize() {
                return img == null ? new Dimension(200, 200) :  new Dimension(img.getWidth(), img.getHeight());
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - img.getWidth()) / 2;
                int y = (getHeight() - img.getHeight()) / 2;
                g2d.drawImage(img, x, y, this);
                g2d.dispose();
            }
    
        }
    
    }
    

    If I were doing some kind of paint program, I would do this all within the paintComponent method or in some way that it didn't effect the original image, otherwise you've basic destroyed the image until you re-load it

    Another solution might be to take a copy of the original area you want to keep and repaint it back on top after, for example...

    img = ImageIO.read(new File("sample.png"));
    // This is the portion of the image we want to save...
    BufferedImage cutout = img.getSubimage(150, 10, 100, 100);
    // This is the area we want to paint over...
    Rectangle bounds = new Rectangle(0, 0, img.getWidth(), img.getHeight());
    
    Graphics2D g2d = img.createGraphics();
    g2d.setColor(Color.BLACK);
    // Save the current Composite so we can reset it...
    Composite comp = g2d.getComposite();
    // Apply the composite and fill the area...
    g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
    g2d.fill(area);
    // Reset the composite 
    g2d.setComposite(comp);
    // Draw the part of the image we saved previously...
    g2d.drawImage(cutout, 150, 10, this);
    g2d.dispose();
    

提交回复
热议问题