I'm attempting to make a Java Applet that will allow me to draw a graph data structure in a canvas. I will do this by clicking where I want to create nodes, and clicking the nodes to connect them. The problem is I cannot get the paint() method to behave correctly. I add new nodes to the graph (and squares on the canvas) inside the mousePressed(MouseEvent e) method using,
Graphics g = this.getGraphics();
g.setColor(Color.blue);
g.fillRect(e.getX(), e.gety(), 40, 40);
Everything works fine, until I resize the window, and then all the filled rectangles vanish. I overrided the paint method to just an empty method, but the same thing still happens. I can't add the fillRect commands inside paint() because I don't know what rectangles exist until the user interacts with it using the mouse.
How can I use g.fillRect() inside the mouse listener methods and make them stick?
The problem is the place you're drawing to isn't persistant. At any moment, you can lose everything you've drawn to it. The paint(Graphics) method is called when this happens. You'll either need to repaint the entire picture every time this happens, or you'll need to set aside a canvas to draw to and copy the contents to your applet's Graphics as needed.
Here's how to create and draw to an image:
http://java.sun.com/docs/books/tutorial/2d/images/drawonimage.html
Then, in your paint method, use your Graphics' drawImage(...) method to display the image you've created.
I don't know if I'm reading this correctly, but why not just store the location of the last click in a variable to be painted later, when the paint() method is called?
You've got to override the window resize action listener and call repaint inside of it.
The Graphics is temporary. When a region gets dirty, it will be repainted.
The best way is to create a BufferedImage, paint to it on mousePressed and call repaint.
When paint is called, draw the Image onto the passed Graphics Object. This way you don't need to store the Rectangles and you got a buffer which will improve performance.
Related
I am developing a graphic project in java using swing and awt libraries. I am looking for a method that allow me to draw very fast on my JPanel. I tried various methods: overriding paintComponent, calling repaint(x, y, width, heigth).. But in all cases i have to repaint ALL the screen! I have a background and a small image in front of it that changes every few time. i am looking for a method that allow me to paint on the screen only the small image, i don't need to repaint the background too, because it is always the same, and the small image is always at the same coords. for example in C++ i painted the background and then i only painted the small images in front of it using putimage (graphics.h), so that it was very very fast. Do someone have some tips?
I've had some experience with game programming and usually a JPanel is used as canvas. Now to paint on it you would write a simple loop which continuously buffers an image and later paints it to the screen. So on initialisation you create a Graphics or Graphics2D object which is passed to a buffer() method. After painting a BufferedImage with the Instance of Graphics, some paint() method paints the BufferedImage to the screen.
When only painting the background once, previously drawn images will still be visible. If all your images are the same size, you don't have to bother but I still recommend repainting your background as well.
Have a look at the book Killer Game Programming In Java for further information, it's a great reference.
Tips:
Paint static images to a BufferedImage and then draw that within the paintComponent using Graphics#drawImage(...)
You do know that the repaint(...) method is overloaded and that one overload can accept a Rectangle parameter, limiting the area of repainting.
Making a paint-like application that works by saving mouse points in an arraylist. My idea is to have a "points" arraylist with all the previously drawn stuff, and a "temp" arraylist to get and modify the current brush stroke the user just entered. This is necessary as the user can change the color and size, so my idea is to modify the current brush stroke based off what buttons have been pressed, then add that brush stroke to the rest of the picture. I searched around StackOverflow and found some code but cant get it to work how I want to (assuming I found the right code).
#Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
final Graphics2D g = (Graphics2D)g1.create();
try {
g.setColor(brushColor);
for (Point point : tempArrayList){
g.fillOval(point.x, point.y, brushSize, brushSize);
}
} finally {
g.dispose();
}
The problem is that I need to clear the tempArrayList for the next brush stroke, which I can do when they change the color/size, but then it erases what was previously there. I am starting to think that I don't even need the "points" arraylist as descibed above because I was hoping that the g1 graphic would just save what the g graphic created.
I guess I just need to figure out how to add the g graphic to g1
Painting is controlled by the Swing API, there is a expectation that whenever paintComponent is called, you will repaint the entire state of the component (as part of your component might have been damaged due to some system event), so the short answer is, no, you can't...however....
You Could...
Paint to a BufferedImage instead and paint the BufferedImage when paintComponent is called
You Could...
Establish a series of "paintable" objects which contain information about what is to be painted and how it is to the painted, including the brush stroke, stroke color and fill color.
These would then be added to some kind of List and "painted" when the paintComponent method is called
Check out Custom Painting Approaches for exampled of painting from:
A List of objects
A BufferedImage.
The examples show how to draw Rectangles of different colours.
I'm working with android canvas and sometimes the logic is like:
we have some settings in Paint object and draw some graphic using canvas
we should somehow save current Paint settings and draw another graphics
we should restore Paint settings to initial values and continue drawing
the problem is that I didn't find any convinient way to save/restore Paint settings.
I'm not sure that doing it manually is a good way. Could you please advise?
You should make as many paint objects as you need to paint draw on the canvas. You don't want to go changing them on the fly, they are only being used in draw which means you need them already having the value they need to paint. You restore and save on the canvas because that's just popping matrix off the stack, but, paints should be pre-established.
Following Code Draws a structure of a molecule. If I don't pass a molecule the last structure continue to show up in the JPanel. How do I reset this to a blank canvas when there is no molecule. In other words what should I put inside else{} of drawMolecule() method?
You could create a new BufferedImage in the else or you could get the BufferedImage's Graphics2D component, set its background color via setBackground(Color c) and then clear the image via clearRect(...) then dispose of the Graphics2D object when done via its dispose() method.
In fact, on review of your code I don't see you doing this. Don't forget to dispose of the Graphics or Graphics2D resource when done using them, if you've created them yourself (not if obtained from the JVM say via its paint or paintComponent method).
I've been doing a program that will paint lines in a JLabel with picture. after creating those lines, I want to delete those lines that I've drawn. For example, I want to delete the
d.drawLine(label.getGraphics(), 120,215,330,120);
Drawing does not work like that. Once you draw a line, it no longer exists as a line, just as a bunch of pixels that aren't functionally different from all the other pixels. There are however possible workarounds:
Redraw the line using the background colour (e.g. white). This only works if the line doesn't cover anything.
Make a Line class and keep a list of them. When you want to delete a line, remove it from the list, clear all lines, and then redraw all the lines in the list.
You can't delete anything on a GUI. All you can do is keep writing over the top of what's there. If you want to change a black line back to a white background, you can write a white line over the top.
I think you're confusing a canvas type implementation (Java) with a graphics DOM tree type implementation (SVG in browsers, for example).
In a DOM implementation you can remove the element and have the application work out what is the dirty region and to repaint any elements that have sections that fall within that dirty region (usually a rectangle).
In a canvas implementation like Java, you paint directly to a graphics object and once you've painted, the canvas doesn't know where you painted. Generally, you need to implement a mechanism to work out what is dirty and repaint your component in the affected areas. Such a mechanism is known a scene graph.
label.revalidate();
label.repaint();
...
public void paintComponent(Graphics g) { do not draw lines but the rest }
Drawing happens event based, so you put your drawing code into paintComponent or paint.
The redrawing can be triggered i.a. with a repaint.