可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I would like to be able to paint Image
s 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?
回答1:
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.
回答2:
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:
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?
回答4:
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.
回答5:
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.