How to draw graphics outside of the paint() functi

2019-07-15 07:02发布

I would like to be able to paint Images onto a JFrame, but whenever I want (not in the JFrame.paint method.

For the project I am working on, I have a class Bullseye extends BufferedImage, and am trying to put it onto a JFrame:

class DrawingFrame extends JFrame {
    public void drawImage(Image img, int x, int y) {
        getGraphics().drawImage(img,x,y,null);
        repaint();
    }
}

class Main {
    public static void main(String[] args) {
        DrawingFrame frame = new DrawingFrame();
        Bullseye bullseye = new Bullseye(20,20); //width,height

        // later
        frame.setVisible(true);
        frame.drawImage(bullseye,10,20);
        frame.drawImage(bullseye,20,20);
        frame.drawImage(bullseye,30,20);
    }
}

However, nothing shows up. After some research, apparently this doesn't work because the changes to the graphics object get cleared when I repaint().

How can I do this? Is this even the right approach?

5条回答
聊天终结者
2楼-- · 2019-07-15 07:14

I think you take the problem backwards. In Swing, all drawing operations should be done within the paint() method.

What you can do is to store the image you want to draw as attribute in your class, then, in your pain method, draw the image wherever you want. For example:

class MyFrame extends JFrame {

    Image image;

    public void paint(Graphics g) {
        super.paint(g);
        if (image != null) {
            g.drawImage(image, /* ... */);
        }
    }

    public void setImage(Image image) {
        this.image = image;
        repaint();
    }

}

And in your other class:

myFrame.setImage(myImage);
查看更多
祖国的老花朵
3楼-- · 2019-07-15 07:15

Drawing to the screen in Java is (almost) always done in paint(). What you need for your class is:

class DrawingFrame extends JFrame {

    private Image bullseye = new Bullseye(20,20); //width,height


    public void paint(Graphics g) {
        g.drawImage(bullseye,10,20);
        g.drawImage(bullseye,20,20);
        g.drawImage(bullseye,30,20);
    }

}

class Main {
    public static void main(String[] args) {
        DrawingFrame frame = new DrawingFrame();

        // later
        frame.setVisible(true);
    }
}

If you need to turn on the drawing of bullseyes at a specific time, create a flag on the DrawingFrame object, and set it when you need them. You will need to call repaint() when the flag is set.

查看更多
We Are One
4楼-- · 2019-07-15 07:19

Create a Graphics Object in your class, for which it must have global, not just method-local existence.

public class Graphics2D freefrompaint = null;  

Then also have a boolean for flow-of-control purposes:

private boolean heypaintreturnnow = false;

and override subject Swing Component superclass' update method() asfollows:

public void update(Graphics g) { 
    if (heypaintreturnnow) return;  
    freefrompaint = (Graphics2D)g;  
    heypaintreturnnow = true; /*and if you want, do => super.update(?) once, or once after boolean hereof is set to false by your code. */

Update() clears the all color in an offscreen graphics data buffer to the current background color of the GraphicsObject. And, you must also know the exact three methods done inside Swing Components' paint():

(1) it calls its very own paintComponent(),here is where actual painting of such Component is delegated to;

(2) the method painting its borders; and then last is the painting of its child Component. One last very important and inevitable thing: use a class, nested, named or anonymous, with this overriden Container methods. And pass that class to JFrame's setContentPane(Container actualgraphicsreference) method; this is a must. I hope that I have made my explanatory and informative approach unambiguous. Self-explanatorily, you may now use freefrompaint to paint beyond, and the Operating System's call to your Frame's repaint() will not invoke a "twin Graphics" default raster-clearing operation, which now you have suppressed in going to code as I above instructs and recommends to you. Thank you for an expressive opportunity.

查看更多
Explosion°爆炸
5楼-- · 2019-07-15 07:21

How about creating a offscreen image to paint on while outside of actual paint, and then the actual paint just paints the offscreen image to actual graphics? A kinda double buffering?

查看更多
Summer. ? 凉城
6楼-- · 2019-07-15 07:32

Custom painting should RARELY ever be done in the paint() method, especially the paint() method of a JFrame. Custom painting is done by overriding the paintComponent() method of a Swing component, generally a JComponent or JPanel. Read the section from the Swing tutorial on Custom Painting for more information and working examples.

However, im this case you don't event need to do any custom painting. You just create an ImageIcon and add the Icon to a JLabel, then you add the JLabel to a panel. Read the section from the Swing tutorial on How to Use Icons for working examples.

If you can't find the appropriate layout manager to use you can also use absolute positioning. Again you will find a section in the tutorial on using layout managers that explains this in more detail.

查看更多
登录 后发表回答