Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
646 views
in Technique[技术] by (71.8m points)

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

It's the original image: enter image description here

I use java.awt.Graphics.fillRect(int x, int y, int width, int height) to add a coloured rectangle on the image.

Graphics imageGraphics = image.createGraphics();
Color color = new Color(0,0,0,100);
imageGraphics.setColor(color);
imageGraphics.fillRect(0, 0, 800, 600);

So the image has been inverted and looks like this: enter image description here After that,I want to clear the black transparent rectangle partly and show the original image. imageGraphics.clearRect(100,100,100,100); But the effect is like this:

enter image description here

What my requirement is: enter image description here

I want to know why it doesn't work and is there any other way to realize it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...