How to control rendering quality using JAVA - java

I have simple drawing canvas like this:
public class DrawingCanvas extends JPanel
private BufferedImage image;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
image = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D) image.getGraphics();
// draw some items....
g2.dispose();
g.drawImage(image, 0, 0, null);
}
}
I want to ask you, if I can set some render quality?
For example Antialiasing.. I want use BEST render quality.
How ?

Have a look at RenderingHints.
You can set them with calling g2.setRenderingHint(RenderingHints.Key hintKey, Object hintValue).
With this you can alter different settings for the render quality, like (text)anti-aliasing, alpha-interpolation etc.
For anti-aliasing:
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
The other keys and values are pretty self-explanatory.

Related

How to use Graphics2D in a method that is required by Abstract that uses Graphics [duplicate]

This question already has answers here:
Getting the Graphics2D?
(2 answers)
Closed 3 years ago.
I am creating a simple game, and I would like to give my player different skins (textures). However I am struggling to do so. Every object in my game uses render(Graphics g) but for textures the easiest way I could find was using a bufferedImage. Now the way I would do it now, would require render(Graphics2D g2d) so I am not quite sure how to do that since the abstract is also for enemies and I just want them a solid color. Maybe it just works to convert them over? I am new to programming so sorry if it is simple.
#Override
public void render(Graphics g) //What I have right now
{
g.setColor(Color.blue);
g.fillRect((int)x, (int)y, 32, 32);
}
public void iWantThis(Graphics2D g2d) //What I would like
{
BufferedImage img = getImg();
g2d.drawImage(img, (int)x, (int)y, 32, 32, null);
}
I just did Graphics2D g2d = (Graphics2D) g;

I'm trying to change the Rectangle colour to Black but its not working

I'm new to Java and don't know exactly what the cause.Let me explain the issue
I created a Rectangle Shape and its working, then i thought about changing its color to black for some testing but it seems not working below is my code.
When i call the method from paintComponent itself then its working but if i do the same from any other method then its not changing the color. I tried calling the method repaint also but still the same
public class Meme extends JPanel {
Rectangle2D.Float myRect = new Rectangle2D.Float(90, 90, 90, 90);
Graphics2D graphics2d;
public void DRAW() {
graphics2d.setColor(new Color(0, 0, 200));
graphics2d.fill(myRect);
}
public void ChangeColour() {
System.out.println("Called");
graphics2d.setPaint(Color.BLACK);
System.out.println("Called2");
graphics2d.fill(myRect);
System.out.println("Called3");
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
graphics2d = (Graphics2D) g;
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
DRAW();
}
}
Button click listener method
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
meme1.ChangeColour();
}
As far as I can remember, whenever you change some properties (color in this case), you have to call repaint. This will invoke a call to paintComponent and the frame will be drawn once again.
In your case, I am guessing even if you call repaint after changing color, the DRAW method gets called again in paintComponent which resets the changed color back to (0, 0, 200). Therefore, you don't see any change in the screen. But when you call changeColor in paintComponent method (assuming after the call to DRAW), the change of color persists and does not get overridden.
POSSIBLE SOLUTION
Just keep the color stored somewhere else. Like
Color myColor = new Color(0,0,200);
then in DRAW:
private void DRAW() {
graphics2d.setColor(myColor);
graphics2d.fill(myRect);
}
and in ChangeColor:
private void ChangeColour() {
myColor = Color.BLACK;
}
Hope it helps.
update your function like this
public void ChangeColour() {
System.out.println("Called");
graphics2d.setColor(new Color(1, 1, 200));
System.out.println("Called2");
graphics2d.fill(myRect);
System.out.println("Called3");
}
Painting in Swing is both passive and destructive. That is, a paint pass can occur at anytime for any number of reasons, many which you don't control. Destructive means, on each paint pass you are expected to repaint the entire component from scratch.
In Swing, you update the state you want change and then call repaint to trigger a new paint pass.
Painting should only ever paint the current state, it should never try and change it
public class Meme extends JPanel {
Rectangle2D.Float myRect = new Rectangle2D.Float(90, 90, 90, 90);
private Color color;
public void draw(Graphics2D graphics2d) {
graphics2d.setColor(color);
graphics2d.fill(myRect);
}
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void ChangeColour() {
color = Color.BLACK;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
graphics2d = (Graphics2D) g.create();
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
draw(graphics2d);
graphics2d.dispose();
}
}
Also, the graphics context passed to your component is shared with all the other components, so it's important that any significant changes you make to the context are undone before the method exists - in most cases, it's just a simple case of calling create on the Graphics context to snapshot it state and dispose (on the copy you created) when you're done

Cannot Rotate JPanel Image

I have been having trouble rotating one of my sprites in a game I'm working on. I have followed a tutorial about rotating images on JPanels about the center of the image (which was very well-done). I even created a simple project that works just fine.
However, when I tried to use the same technique on my game, my sprite will not rotate. I have determined that the problem is drawing the sprite, as I have checked in the paintComponent(Graphics g) method via a println() statement that the rotation value is updated properly and that the repaint() method is being called when appropriate.
Here is the relevant code to the issue (excludes unnecessary methods and such):
Highest-level class:
public abstract class GameObject extends JPanel {
protected BufferedImage image;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw sprite
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, 0, 0, null);
// Clean up
g.dispose();
g2.dispose();
}
}
Lowest-level class:
// Entity is a subclass of GameObject.
// It does not override paintComponent.
// All it does is add an update method that is called every game tick.
public abstract class MicroObject extends Entity {
protected Location location; // variable to store position and rotation
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.translate(this.getWidth() / 2, this.getHeight() / 2);
g2.rotate(Math.toRadians(location.getRotation()));
// In the following two lines, image is inherited from GameObject
g2.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
g2.drawImage(image, 0, 0, null);
g2.dispose();
g.dispose();
}
}
I know this isn't necessarily a unique question, but I've looked at all of the "duplicate" threads, and they've all left me with similar answers, but the same problem in the end. I would appreciate it if someone took the time to look at my code and see where I went wrong.
Thank you all!
Don't dispose those Graphics objects! They're re-used by Swing to draw children components & borders.
The reason why it's not working is because GameObject is disposing the graphics object before MicroObject can use it.
Also, there's no reason to draw the image twice. Remove the code in GameObject's paintComponent().
Lastly, just use classes. There's no reason for those to be abstract.
So:
Highest-level class:
public class GameObject extends JPanel {
protected BufferedImage image;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Don't draw sprite. Subclass will do that.
// Don't clean up. Swing does that for us.
}
}
Lowest-level class:
// Entity is a subclass of GameObject.
// It does not override paintComponent.
// All it does is add an update method that is called every game tick.
public class MicroObject extends Entity {
protected Location location; // variable to store position and rotation
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.translate(this.getWidth() / 2, this.getHeight() / 2);
g2.rotate(Math.toRadians(location.getRotation()));
// In the following two lines, image is inherited from GameObject
g2.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
g2.drawImage(image, 0, 0, null);
}
}

Render swing with graphics class

Can you render components swing through a Graphics object?
I have a structure like this in my class:
public void render(Graphics g) {
//Render stuff
}
Is it possible to create an object swing, and for that object to render i using the Graphics object?
sure, absolutely possible.
public class MyClass extends JComponent {
//...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
render(g);
}
}
I take it, you want to draw, but not to the screen.
One can create a BufferedImage (or read a background image) and create a Graphics2D object with which to draw.
File imgFile = new File("scenery.png");
BufferedImage img = ImageIO.read(imgFile);
Graphics2D g = img.createGraphics();
render(g);
g.dispose();
ImageIO.write(img, "png", imgFile);
Not to forget the g.dispose() to releast native drawing state.

Update a draw in a Java Canvas

I want to make an application in which I can draw a path on a canvas. The problem is that I have to update this canvas continuously.
Currently I'm able to do it, but I have to redraw all the path every time and so I have to store all the points in memory. I would prefer to simply update the draw by adding a new point.
Is it possible?
Currently my code is:
public class MyCanvas extends Canvas{
private static final long serialVersionUID = 1L;
public MyCanvas(){}
public void paint(Graphics graphics){
super.paint(graphics);
graphics.setColor(Color.green);
// points is an ArrayList of Point2D
for (Iterator iterator = points.iterator(); iterator.hasNext();) {
Point2D point2d = (Point2D) iterator.next();
graphics.fillOval((int)((canvas.getWidth()/2.0) + point2d.getX()), (int)((canvas.getHeight()/2.0) + point2d.getY()), 5, 5);
}
}
}
Thanks!
EDIT
This is the current solution:
PanelCanvas canvasPanel;
...
public void drawCircle(int x, int y){
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setColor(Color.green);
g2d.setBackground(Color.white);
g2d.fillOval((int)((panelCanvas.getWidth() / 2.0) + x/10.0), (int)((panelCanvas.getHeight() / 2.0) + y/10.0), 5, 5);
panelCanvas.repaint();
}
public class CanvasPanel extends JPanel{
public void paintComponent(Graphics graphics){
super.paintComponents(graphics);
Graphics2D g2d = (Graphics2D)graphics;
g2d.setBackground(Color.white);
g2d.drawImage(bufferedImage, null, 0, 0);
}
}
Draw the points (whatever) to a BufferedImage. During paint(), draw the BufferedImage.
Note though, that the JRE can draw thousands of objects in paint without any visual artifacts or slow-down.
The canvas is embedded in a Swing GUI. What do you suggest for replacing AWT.Canvas?
JComponent for complete custom rendering, JPanel for custom rendering combined with components. It sounds like the JComponent would be better suited to this use-case.
For either of those, override paintComponent(Graphics) instead of paint(Graphics). The rest of the advice is the same.

Categories