Drawing lines on BufferedImage in Java using threads - java

I have a BufferedImage, which is set to a JLabel, which in turn is part of a JPanel. On the click of a button, I am drawing some lines on the BufferedImage, which is subsequently updated on the panel. Earlier, I was drawing each line one-by-one, which was OK, but was time-inefficient for my purposes. To increase the efficiency, I divided the coordinates of the BufferedImage in 4 parts and drew the lines on each part using threads. Now, after the execution is completed, some random part of the image does not have the lines drawn. Why is that? Is drawing using Graphics2D not thread-safe??

Is drawing using Graphics2D not thread-safe??
Yes, Swing (and drawing in it) is definitely not thread-safe and rendering errors which you are experiencing are definitely because of that.
Please refer to following tutorial for more details:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
As per mKorbel comment, please add SSCCE to receive more specific advice.

Related

JavaFX: how to clear a drawing without affecting background

Very simple question, but I could not find the answer in JavaFX docs or StackOverflow:
I have a JavaFX Canvas filled with a graph (various calls to strokeLine(), not the issue here). I need to be able to draw a rectangle over this graph, then simply clear the rectangle, without affecting the graph in the background. (Like an undo operation).
Code to draw the rectangle ('p' and 'e' are points):
gc.rect(p.getX(), p.getY(), e.getX()-p.getX(), e.getY()-p.getY());
gc.stroke();
The most obvious answer would be to use the clearRect() method, but the problem is that it clears also the portion of the graph in the background...
So the question is: how do I clear a drawing that was made with stroke(), without affecting the other drawings in the background?
You can't do this with one canvas.
Canvas only store the result of your painting operation.
This is the interest of the canvas you can stroke million times the same line and it will only store and represent the result and doesn't consume more memory.
So you if you need to draw Something over your chart you should put an other canvas over the chart and draw on the second canvas.
It might be more straight forward and much more the JavaFX-way of doing things if you just put your canvas into a Group and then just add a Rectangle node to the Group which you can remove at any time if you want.
This can be acheaved by taking snapshot(s) of your Canvas, using the .snapshot(SnapshotParameters params, WritableImage image) method. Basicly, every time you draw something on your Canvas, you take a snapshot of it and store it somewhere (for example in a ArrayList). Then you can use those snapshots to create a 'undo' operation, by using the . drawImage(Image img, double x, double y) method of Canvas's GraphicsContext, in which you would pass the snapshot you want to go back to as the Image parameter.

Editind image (JLabel) inside JScrollPane

I am developing an image editor capable of drawing ovals on an image. I am able to successfully add an image into a JScrollPane and draw on it using the fillOval() function. But each and every time I move the scroll bar all the drawn ovals disappear. Since the image to be uploaded is often large in size scroll bars cannot be disabled. I have incorporated the image in a JLabel. Please help.
I am able to successfully add an image into a JScrollPane and draw on it using the fillOval() function. But each and every time I move the scroll bar all the drawn ovals disappear.
This suggests to me that you're not drawing correctly. Since you've not shown us how you're drawing, we can only guess, but perhaps you're calling getGraphics() on a component and using an unstable Graphics instance. If so, you'll be better off calling getGraphics() on a BufferedImage itself, and drawing on it. Either that or drawing in the paintComponent method of your JComponent.
If this doesn't help, please provide more information on exactly what you're doing, preferably by creating and posting a Minimal, Complete, and Verifiable Example Program. We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem.

Creating a small images from JPanel

I'm writing simple slide program in Java. In that program, I draw lines, ellipses, rectangles and etc in each slide. What is more, like a powerpoint I want to show all of my slides' symbolic small pictures on the JList.
How should I create small images from all elements in JPanel?
Thanks.
You might look at capturing a panel's image using Screen Image, discussed here.
Addendum: See also ComponentImageCapture.
If I understood your task correct, you must inherit from JPanel and overload method paintComponent(Graphics g). Inside you can write something like g.drawLine(0,0, 10, 10)

Drawing over a BufferedImage. repaint()

I have a component on which I'm drawing a BufferedImage on all the surface.
I would like to draw something more over it, following the mouse when it passes over the area.
To do it, I'm adding a MouseMotionListener on the component and implement mouseMove method. Inside mouseMoved method I'm calling repaint() at the end of the drawing of the drawing of the cursor image. I would like to know if there is a better way to do it, cause the image following the cursor is really small, and I'm repainting every thing each time.
Add a JLabel containing an Icon to the panel with the buffered image.
Then when you move the mouse you just change the location of the label. Swing will repaint the last location so the buffered image shows through, then it will repaint the label at the new location. So let Swing manage the repaint.
Since you know the coordinate of your mouse and the small image you gonna paint over your background, you can optimize like this [pseudo-code]:
void mouseMoved(event) {
lastCoordinates = currentCoordinates;
currentCoordinates = event.coordinates;
image.repaint(lastCoordinates.x, lastCoordinates.y, smallImage.width, smallImage.height);
image.repaint(currentCoordinates.x, currentCoordinates.y, smallImage.width, smallImage.height);
}
that way you only repaint the two regions you actually care about instead of the whole background.
Also, reading the javadoc it seems the code above my actually trigger 2 separate calls to painting stuff, which would be inefficient. You may want to try to pass in a 10 milliseconds value or so to make sure the 2 paints execute together.
Check out javadoc for repaint() that takes 4 and 5 arguments:
4-argument version
5-argument version

can we zoom in zoom out the drawing we draw on the Canvas?

We have an old (more than 10yrs old) Java Swing applicatin which draws lots of circles and connections (lines) between those circles on a JCanvas (a subclass of JComponent) based on lab data.
Because the data becames bigger and bigger, we cannot display the entire drawing now. We have put the JCavans into a JScrollPane but it is not convenience to scroll the drawing.
Can we add zoom in zoom out for it? if yes, how? I know we can zoom image but the drawing on Canvas is an image?
thanks,
EDIT:
we draw those circles and line with Graphics within paintComponent(Graphics g) method.
You could apply a scaling Transform to the Graphics2D object passed to the paintComponent method. You can learn how to use it in the Java 2D programming trail.
Without knowing anything about your application it's hard to provide useful advice (adding a code snippet or better yet a cutdown example app would be helpful to show how things are being drawn), but I'll give it a shot:
Why don't you multiply the x,y and width,height values by a scaling factor before you draw each circle/line? I assume that somewhere your canvas is using a Graphics object to draw each shape?

Categories