简体   繁体   English

如何在JFrame中的paint()函数之外绘制图形

[英]How to draw graphics outside of the paint() function in a JFrame

I would like to be able to paint Image s onto a JFrame , but whenever I want (not in the JFrame.paint method. 我希望能够将Image绘制到JFrame ,但每当我想要时(不是在JFrame.paint方法中)。

For the project I am working on, I have a class Bullseye extends BufferedImage , and am trying to put it onto a JFrame : 对于我正在进行的项目,我有一个class Bullseye extends BufferedImage ,并且我试图将它放到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() . 经过一些研究,显然这不起作用,因为当我repaint()时, graphics对象的更改被清除。

How can I do this? 我怎样才能做到这一点? Is this even the right approach? 这甚至是正确的方法吗?

I think you take the problem backwards. 我认为你倒退了问题。 In Swing, all drawing operations should be done within the paint() method. 在Swing中,所有绘图操作都应该在paint()方法中完成。

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

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: 并覆盖主题Swing Component超类'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. Update()将屏幕外图形数据缓冲区中的所有颜色清除为GraphicsObject的当前背景颜色。 And, you must also know the exact three methods done inside Swing Components' paint(): 而且,你还必须知道在Swing Components的paint()中完成的三个方法:

(1) it calls its very own paintComponent(),here is where actual painting of such Component is delegated to; (1)它调用它自己的paintComponent(),这里是委托给这种Component的实际绘制的地方;

(2) the method painting its borders; (2)绘制边界的方法; 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; 并将该类传递给JFrame的setContentPane(Container actualgraphicsreference)方法; 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. 自我解释,您现在可以使用freefrompaint进行绘制,并且操作系统对Frame的重绘()的调用不会调用“双图形”默认光栅清除操作,现在您已经在上面的代码中被禁止了指导并向您推荐。 Thank you for an expressive opportunity. 感谢您提供富有表现力的机会。

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? 有点双缓冲?

Drawing to the screen in Java is (almost) always done in paint(). 用Java绘制到屏幕(几乎)总是在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. 如果需要在特定时间打开bullseyes的绘图,请在DrawingFrame对象上创建一个标志,并在需要时设置它。 You will need to call repaint() when the flag is set. 设置标志时,您需要调用repaint()。

Custom painting should RARELY ever be done in the paint() method, especially the paint() method of a JFrame. 自定义绘画应该在paint()方法中完成,特别是JFrame的paint()方法。 Custom painting is done by overriding the paintComponent() method of a Swing component, generally a JComponent or JPanel. 自定义绘制是通过覆盖Swing组件的paintComponent()方法完成的,通常是JComponent或JPanel。 Read the section from the Swing tutorial on Custom Painting for more information and working examples. 阅读自定义绘画的Swing教程中的部分以获取更多信息和工作示例。

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. 您只需创建一个ImageIcon并将Icon添加到JLabel,然后将JLabel添加到面板。 Read the section from the Swing tutorial on How to Use Icons for working examples. 阅读Swing教程中有关如何使用图标的工作示例部分。

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. 您将再次在教程中找到有关使用布局管理器的部分,可以更详细地解释这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM