Using Java Graphics 2D to render image minute by minute to create time lapse video cause blurry image when running. Image resolution on Full HD (1920 X 1080) Blurry appears on image not on video.
I use buffered image as the configuration as bellow
BufferedImage alt = config.createCompatibleImage(resX, resY);
Graphics2D g2 = alt.createGraphics();
When resX and resY are
final int resX = 1920;
final int resY = 1080;
Trying to draw circle and text with this x,y configuration
// Image
g2.drawImage(img, leftSideX, resYTop + paddingImg, resX - leftSideX - paddingImg, resY - resYTop - paddingImg - paddingImg, null);
// Draw Cirlce 1
g2.setColor(new Color(0,161,155));
g2.fillArc(78, 160, 200, 200, 90, -340);
g2.setColor(new Color(73, 73, 73));
g2.fillArc(98, 180, 160, 160, 90, -340);
// Percentage
g2.setColor(new Color(0,161,155));
g2.setFont(g2.getFont().deriveFont(45F));
g2.drawString("10%", 135, 275 );
// Draw circle Legend
g2.setColor(new Color(0,161,155));
g2.fillArc(paddingLegend, resY - 150, paddingLegend, paddingLegend, 360, 360);
g2.setColor(new Color(249,178,52));
g2.fillArc(paddingLegend, resY - 120, paddingLegend, paddingLegend, 360, 360);
g2.setColor(new Color(190,22,35));
g2.fillArc(paddingLegend, resY - 90, paddingLegend, paddingLegend, 360, 360);
g2.setColor(new Color(178,178,178));
g2.setFont(g2.getFont().deriveFont( 15F ));
g2.drawString("Occupied / Moving Goods", paddingLegend + 30, resY - 135 );
g2.drawString("Goods idle > 2 days and < 5 days", paddingLegend + 30, resY - 105);
g2.drawString("Goods idle \u2265 5 days", paddingLegend + 30, resY - 75 );
// Capacity Level Title
g2.setFont(g2.getFont().deriveFont( 20F ));
g2.drawString("Capacity Level ", paddingLeftSubTitle + paddingLegend, resYTop + paddingTopSubTitle1 + paddingLegend);
// Goods Movement Title
g2.setFont(g2.getFont().deriveFont( 20F ));
g2.drawString("Goods Movement ", paddingLeftSubTitle + paddingLegend, resYTop + paddingTopSubTitle2 + paddingLegend);
and here are the result
Blur appears on circle and text
as you can see from the image above the circle and text are totally blurry but the warehouse image are not blur at all. I have tried bellow code and nothing improvement.
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
How I can improve my image render quality?
Many Thanks
So, when I patch your code together and run it, I get...
which seems fine to me. So either it's something else going on in your code which we're not privy to, or it's a hardware/driver issue.
Consider providing a Minimal, Complete, and Verifiable example - this removes the guess work and provides us with a better oppurunity to understand the problem and provide possible solutions
Nb: I'm rending the output at 1920x1080, I've just clipped the output for the post
ps- I know this is not a "answer", but I'm not getting any help from the OP
CircularProgress
Because I haven't done it a hundred times before...
While you can do this kind of thing use the regular 2D Graphics API, I tend to find the "shapes" API a much more useful approach, especially for generating complex re-usable shapes
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CircleProgressTest {
public static void main(String[] args) {
new CircleProgressTest();
}
public CircleProgressTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private double progress = 0d;
private double radius = 90;
private CircleProgress cp;
public TestPane() {
cp = new CircleProgress(radius, 20, 0d);
Timer timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (progress >= 1.0) {
((Timer)(e.getSource())).stop();
progress = 1.0;
} else {
progress += 0.001;
}
cp = new CircleProgress(radius, 20, progress);
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
double x = (getWidth() - (radius * 2d)) / 2d;
double y = (getHeight() - (radius * 2d)) / 2d;
g2d.transform(AffineTransform.getTranslateInstance(x, y));
g2d.setStroke(new BasicStroke(4f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.setColor(Color.DARK_GRAY);
g2d.draw(cp);
g2d.setColor(new Color(0,161,155));
g2d.fill(cp);
g2d.dispose();
}
}
public class CircleProgress extends Path2D.Double {
private double radius;
private double thickness; // subtracted from radius
private double progress;
public CircleProgress(double radius, double thickness, double progress) {
this.radius = radius;
this.thickness = thickness;
this.progress = progress;
build();
}
protected void build() {
double innerRadius = radius - thickness;
if (progress >= 1.0) {
Area outter = new Area(new Ellipse2D.Double(0, 0, radius * 2d, radius * 2d));
Area inner = new Area(new Ellipse2D.Double(thickness, thickness, innerRadius * 2d, innerRadius * 2d));
outter.subtract(inner);
append(outter, true);
} else if (progress <= 0.0) {
// What does this actually mean...?
} else {
double extent = -(360.0 * progress);
double startAt = 90d;
append(new Arc2D.Double(0, 0, radius * 2d, radius * 2d, startAt, extent, Arc2D.OPEN), true);
append(new Arc2D.Double(thickness, thickness, innerRadius * 2d, innerRadius * 2d, startAt + extent, -extent, Arc2D.OPEN), true);
closePath();
}
}
}
}
Related
I am new to Java programming and I am trying to rotate an image using the following code but nothing seems to be working, I searched a lot online but nothing helped. I saw people doing it using BufferedImage but don't want to use that. This code is rotating entire 2d object instead of just image which i want to rotate. I found out this by displaying rectangle as images were not aligned on top of each other. Thanks for your help.
package package3;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Rotate extends JPanel {
public static void main(String[] args) {
new Rotate().go();
}
public void go() {
JFrame frame = new JFrame("Rotate");
JButton b = new JButton("click");
MyDrawPanel p = new MyDrawPanel();
frame.add(p);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 1000);
frame.setVisible(true);
}
class MyDrawPanel extends JPanel{
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Image image = new ImageIcon(
getClass()
.getResource("wheel.png"))
.getImage();
g2d.drawImage(image, 0, 0, 500, 500, this);
int x = image.getHeight(this);
int y = image.getWidth(this);
g2d.rotate(1, x/2, y/2);
g2d.setBackground(Color.black);
g2d.drawImage(image, 0, 0, 500, 500, this);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
}
}
}
here's what output looks like
First of all, when rotating an image with a Graphics context, the rotation will occur at a "anchor" point (the top/left is default position if I recall).
So, in order to rotate an image around it's center, you need to set the anchor point to the center of the image WITHIN the context of it's container.
This would mean that the rotate call should be something like...
g2d.rotate(radians, xOffset + (image.getWidth() / 2), yOffset + (image.getHeight() / 2));
Then when you draw the image at xOffset/yOffset, the image will "appear" rotated around the anchor point (or the center of the image).
Second, transformations are compounding. That is, when you transform a graphics context, all subsequent paint operations will be transformed. If you then transform it again, the new transformation will be add to the old one (so if you rotated by 45 degrees and then rotate again by 45 degrees, the transformation would now be 90 degrees).
It's typically "easiest" to create a "copy" of the Graphics state first, apply your transformations and paint operations and then dispose of the copy, which will leave the original context in it's original (transformed) state (all painting operations applied), this way you don't to spend time trying to figure out how to undo the mess
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new MyDrawPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
class MyDrawPanel extends JPanel {
private BufferedImage image;
public MyDrawPanel() throws IOException {
image = ImageIO.read(getClass().getResource("/images/MegaTokyo.png"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1000, 1000);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
drawImageTopLeft(g2d);
drawImageBottomRight(g2d);
drawImageMiddle(g2d);
g2d.rotate(Math.toRadians(45), getWidth() / 2, getHeight() / 2);
g2d.setColor(Color.BLACK);
g2d.drawRect(0, 0, this.getWidth(), this.getHeight());
g2d.dispose();
}
protected void drawImageTopLeft(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
int x = 0;
int y = 0;
g2d.rotate(Math.toRadians(135), image.getWidth() / 2, image.getHeight() / 2);
g2d.drawImage(image, x, y, this);
g2d.dispose();
}
protected void drawImageBottomRight(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
int x = (getWidth() - image.getWidth());
int y = (getHeight() - image.getHeight());
g2d.rotate(Math.toRadians(-45), getWidth() - (image.getWidth() / 2), getHeight() - (image.getHeight() / 2));
g2d.drawImage(image, x, y, this);
g2d.dispose();
}
protected void drawImageMiddle(Graphics2D g2d) {
g2d = (Graphics2D) g2d.create();
int x = (getWidth() - image.getWidth()) / 2;
int y = (getHeight() - image.getHeight()) / 2;
g2d.rotate(Math.toRadians(45), getWidth() / 2, getHeight() / 2);
g2d.drawImage(image, x, y, this);
g2d.dispose();
}
}
}
BEFORE YOU MARK IT AS DUPLICATE
I have searched a lot in the internet for that and tried every solution, but no one does it the same way I do it. In my case the rotation is in a sperate class.
I have created a java class that inherits JLabel class, in my class I have an arrow BufferedImage which I draw using the paintComponent(Graphics g) method.
I am trying to make the arrow point to a specific point (which I get from a different method) but something goes wrong and the arrow rotates to the wrong direction.
I THINK: it doesn't calculate correctly because the imageLocation is relative to the label.
Here is my code:
package pkg1;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public final class ImageLabel extends JLabel {
private float angle = 0.0f; // in radians
private Point imageLocation = new Point();
private File imageFile = null;
private Dimension imageSize = new Dimension(50, 50);
private BufferedImage bi;
private BufferedImage resizeImage(BufferedImage originalImage, int img_width, int img_height) {
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizedImage = new BufferedImage(img_width, img_height, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, img_width, img_height, null);
g.dispose();
return resizedImage;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bi == null) {
return;
}
imageLocation = new Point(getWidth() / 2 - bi.getWidth() / 2, getHeight() / 2 - bi.getHeight() / 2);
Graphics2D g2 = (Graphics2D) g;
g2.rotate(angle, imageLocation.x + bi.getWidth() / 2, imageLocation.y + bi.getHeight() / 2);
g2.drawImage(bi, imageLocation.x, imageLocation.y, null);
}
public void rotateImage(float angle) { // rotate the image to specific angle
this.angle = (float) Math.toRadians(angle);
repaint();
}
public void pointImageToPoint(Point target) {
calculateAngle(target);
repaint();
}
private void calculateAngle(Point target) {
// calculate the angle from the center of the image
float deltaY = target.y - (imageLocation.y + bi.getHeight() / 2);
float deltaX = target.x - (imageLocation.x + bi.getWidth() / 2);
angle = (float) Math.atan2(deltaY, deltaX);
if (angle < 0) {
angle += (Math.PI * 2);
}
}
}
Okay, so two things jump out at me...
If you take a Point from outside the context of the label, you will have to translate the point into the components coordinate context
The calculateAngle seems wrong
So starting with...
private void calculateAngle(Point target) {
// calculate the angle from the center of the image
float deltaY = target.y - (imageLocation.y + bi.getHeight() / 2);
float deltaX = target.x - (imageLocation.x + bi.getWidth() / 2);
angle = (float) Math.atan2(deltaY, deltaX);
if (angle < 0) {
angle += (Math.PI * 2);
}
}
angle = (float) Math.atan2(deltaY, deltaX); should be angle = (float) Math.atan2(deltaX, deltaY); (swap the deltas)
You will find that you need to adjust the result by 180 degrees in order to get the image to point in the right direction
angle = Math.toRadians(Math.toDegrees(angle) + 180.0);
Okay, I'm an idiot, but it works :P
I'd also make use of a AffineTransform to translate and rotate the image - personally, I find it easier to deal with.
In the example, I've cheated a little. I set the translation of the AffineTransform to the centre of the component, I then rotate the context around the new origin point (0x0). I then paint the image offset by half it's height/width, thus making it appear as the if the image is been rotated about it's centre - It's late, I'm tired, it works :P
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private ImageLabel label;
public TestPane() {
setLayout(new GridBagLayout());
label = new ImageLabel();
add(label);
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
label.pointImageToPoint(e.getPoint(), TestPane.this);
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public final class ImageLabel extends JLabel {
private double angle = 0;
private Point imageLocation = new Point();
private File imageFile = null;
private Dimension imageSize = new Dimension(50, 50);
private BufferedImage bi;
public ImageLabel() {
setBorder(new LineBorder(Color.BLUE));
bi = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.setColor(Color.RED);
g2d.drawLine(25, 0, 25, 50);
g2d.drawLine(25, 0, 0, 12);
g2d.drawLine(25, 0, 50, 12);
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(), bi.getHeight());
}
protected Point centerPoint() {
return new Point(getWidth() / 2, getHeight() / 2);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bi == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = g2d.getTransform();
Point center = centerPoint();
at.translate(center.x, center.y);
at.rotate(angle, 0, 0);
g2d.setTransform(at);
g2d.drawImage(bi, -bi.getWidth() / 2, -bi.getHeight() / 2, this);
g2d.dispose();
}
public void rotateImage(float angle) { // rotate the image to specific angle
this.angle = (float) Math.toRadians(angle);
repaint();
}
public void pointImageToPoint(Point target, JComponent fromContext) {
calculateAngle(target, fromContext);
repaint();
}
private void calculateAngle(Point target, JComponent fromContext) {
// calculate the angle from the center of the image
target = SwingUtilities.convertPoint(fromContext, target, this);
Point center = centerPoint();
float deltaY = target.y - center.y;
float deltaX = target.x - center.x;
angle = (float) -Math.atan2(deltaX, deltaY);
angle = Math.toRadians(Math.toDegrees(angle) + 180.0);
repaint();
}
}
}
I just want to add that using a JLabel for this purpose is overkill, a simple JPanel or JComponent would do the same job and carry a lot less overhead with it, just saying
I want to make the pacman open/close mouth animation using the easiest method.
Here is my recent code: The problem is, nothing is happening?
package ordner;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PacMan implements ActionListener {
private JFrame frame;
private DrawPanel panel;
private void initGui() {
frame = new JFrame("Pacman");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new DrawPanel();
frame.add(panel);
panel.setBackground(Color.BLACK);
frame.setSize(300, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
PacMan pm = new PacMan();
pm.initGui();
}
#Override
public void actionPerformed(ActionEvent e) {
panel.repaint();
}
}
and here is my draw panel:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.yellow);
g.fillArc(70,50,150,150,30,300);
int i = 0;
while ( i <= 60) {
g.fillArc(70,50,150,150,30-i,300+i+i);
try {
Thread.sleep(25);
}
catch (Exception e) {
Thread.currentThread().interrupt();
}
i++;
}
}
}
The while loop doesn't affect anything, what could be the reason for that?
Something like this might work for PacMan images. It uses a Java 2D based Shape instance to represent the form, and an AffineTransform to produce the different orientations.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.io.*;
import javax.imageio.ImageIO;
class PacManShape {
private double size;
private double rotation;
final int maxSize = 4;
static File home = new File(System.getProperty("user.home"));
static File images = new File(home, "images");
PacManShape(int size, double rotation) {
this.size = size;
this.rotation = rotation;
}
public Area getPacManShape(double jaws) {
Area area = new Area(new Ellipse2D.Double(0d, 0d, size, size));
double x1 = size / 2 + (2d * size * Math.cos(jaws / 2d));
double y1 = size / 2 + (2d * size * Math.sin(jaws / 2d));
double x2 = x1;
double y2 = size / 2 - (2d * size * Math.sin(jaws / 2d));
Polygon mouth = new Polygon();
mouth.addPoint((int) (size / 2), (int) (size / 2));
mouth.addPoint((int) x1, (int) y1);
mouth.addPoint((int) x2, (int) y2);
mouth.addPoint((int) (size / 2), (int) (size / 2));
area.subtract(new Area(mouth));
return area;
}
public BufferedImage getPacManImage(double angle, Color color) {
BufferedImage bi = new BufferedImage(
(int) size, (int) size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
g2.setColor(color);
g2.fillRect(0, 0, (int) size, (int) size);
AffineTransform rotate = AffineTransform.getRotateInstance(
rotation, size / 2, size / 2);
g2.setTransform(rotate);
Area pacMan = getPacManShape(angle);
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.YELLOW);
float[] dist = {.15f, .9f};
Color[] colors = {Color.YELLOW, Color.ORANGE};
Point2D center = new Point2D.Double(size / 2, size / 2);
RadialGradientPaint radial = new RadialGradientPaint(
center, (float) ((size / 2) - 2f), dist, colors);
g2.setPaint(radial);
g2.fill(pacMan);
GradientPaint gradient = new GradientPaint(
0, 0, new Color(255, 255, 225, 220),
(int) (size / 3), 0, new Color(255, 255, 255, 0));
g2.setPaint(gradient);
g2.fill(pacMan);
g2.dispose();
return bi;
}
public void savePacManImage(int q, int num) throws IOException {
double angle = Math.PI*2 / 3d * ((double) num / (double) maxSize);
BufferedImage bi = getPacManImage(angle, Color.WHITE);
images.mkdirs();
File img = new File(images, "PacMan-" + q + "x" + num + ".gif");
ImageIO.write(bi, "gif", img);
}
public static void main(String[] args) {
try {
for (int ii = 0; ii < 4; ii++) {
PacManShape pms = new PacManShape(100, (double) ii * Math.PI / 2d);
for (int jj = 0; jj <= pms.maxSize; jj++) {
pms.savePacManImage(ii, jj);
}
}
Desktop.getDesktop().open(images);
} catch (IOException ex) {
ex.printStackTrace();
}
Runnable r = new Runnable() {
#Override
public void run() {
JPanel gui = new JPanel(new BorderLayout());
gui.add(new PacManComponent());
JOptionPane.showMessageDialog(null, gui);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
class PacManComponent extends JPanel {
double angle = 0d;
int preferredSize = 100;
double diff = Math.PI / 8;
boolean chomp = true;
Timer timer;
PacManComponent() {
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
};
timer = new Timer(180, listener);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(preferredSize, preferredSize);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
//double size = (getWidth() < getHeight() ? getWidth() : getHeight());
if (angle > 2 * Math.PI / 3) {
chomp = true;
} else if (angle < 0.01) {
chomp = false;
}
if (chomp) {
angle -= diff;
} else {
angle += diff;
}
PacManShape pms = new PacManShape(100, 0d);
Image image = pms.getPacManImage(angle, new Color(0, 0, 0, 0));
g2.drawImage(image, 0, 0, this);
g2.dispose();
}
}
If you wanted to transform & render images at run-time, try starting with this series of PNG format images that uses partial transparency to soften the edges.
For the animation, you could use a Swing Timer to move the Pacman graphic as well as adjusting the angle by which the "mouth" opens, by varying the parameters used by fillArc.
Interaction with KeyEvents for movement control can be acheived using Key Bindings.
Also, I would move the paint functionality to a paintComponent method in a sub-classed JComponent for better paint performance.
Related: Painting with Swing
Edit:
As youre starting Java there are a number of tasks to get working first
Create the JComponent based class with a static Pacman graphic. Move your painting logic to paintComponent
Get the Swing Timer functionality working. Follow the Oracle guide for Timers.
Implement the Key Bindings
Other functionality such as score keeping, etc.
2d animation:
http://en.wikipedia.org/wiki/File:The_Horse_in_Motion.jpg
Pseudocode:
while programActive:
deltatime = get_time_since_last_call()
update_animation_frame(deltatime)
image = get_animation_frame()
draw_background()
draw(image)
enforce_framerate(24)
To learn and do this sort of thing in Pygame would be easy compared to Java, but unsuitable for larger projects
I want to make the pacman open/close mouth animation using the easiest method.
Here is my recent code: The problem is, nothing is happening?
package ordner;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PacMan implements ActionListener {
private JFrame frame;
private DrawPanel panel;
private void initGui() {
frame = new JFrame("Pacman");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new DrawPanel();
frame.add(panel);
panel.setBackground(Color.BLACK);
frame.setSize(300, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
PacMan pm = new PacMan();
pm.initGui();
}
#Override
public void actionPerformed(ActionEvent e) {
panel.repaint();
}
}
and here is my draw panel:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.yellow);
g.fillArc(70,50,150,150,30,300);
int i = 0;
while ( i <= 60) {
g.fillArc(70,50,150,150,30-i,300+i+i);
try {
Thread.sleep(25);
}
catch (Exception e) {
Thread.currentThread().interrupt();
}
i++;
}
}
}
The while loop doesn't affect anything, what could be the reason for that?
Something like this might work for PacMan images. It uses a Java 2D based Shape instance to represent the form, and an AffineTransform to produce the different orientations.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.io.*;
import javax.imageio.ImageIO;
class PacManShape {
private double size;
private double rotation;
final int maxSize = 4;
static File home = new File(System.getProperty("user.home"));
static File images = new File(home, "images");
PacManShape(int size, double rotation) {
this.size = size;
this.rotation = rotation;
}
public Area getPacManShape(double jaws) {
Area area = new Area(new Ellipse2D.Double(0d, 0d, size, size));
double x1 = size / 2 + (2d * size * Math.cos(jaws / 2d));
double y1 = size / 2 + (2d * size * Math.sin(jaws / 2d));
double x2 = x1;
double y2 = size / 2 - (2d * size * Math.sin(jaws / 2d));
Polygon mouth = new Polygon();
mouth.addPoint((int) (size / 2), (int) (size / 2));
mouth.addPoint((int) x1, (int) y1);
mouth.addPoint((int) x2, (int) y2);
mouth.addPoint((int) (size / 2), (int) (size / 2));
area.subtract(new Area(mouth));
return area;
}
public BufferedImage getPacManImage(double angle, Color color) {
BufferedImage bi = new BufferedImage(
(int) size, (int) size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
g2.setColor(color);
g2.fillRect(0, 0, (int) size, (int) size);
AffineTransform rotate = AffineTransform.getRotateInstance(
rotation, size / 2, size / 2);
g2.setTransform(rotate);
Area pacMan = getPacManShape(angle);
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.YELLOW);
float[] dist = {.15f, .9f};
Color[] colors = {Color.YELLOW, Color.ORANGE};
Point2D center = new Point2D.Double(size / 2, size / 2);
RadialGradientPaint radial = new RadialGradientPaint(
center, (float) ((size / 2) - 2f), dist, colors);
g2.setPaint(radial);
g2.fill(pacMan);
GradientPaint gradient = new GradientPaint(
0, 0, new Color(255, 255, 225, 220),
(int) (size / 3), 0, new Color(255, 255, 255, 0));
g2.setPaint(gradient);
g2.fill(pacMan);
g2.dispose();
return bi;
}
public void savePacManImage(int q, int num) throws IOException {
double angle = Math.PI*2 / 3d * ((double) num / (double) maxSize);
BufferedImage bi = getPacManImage(angle, Color.WHITE);
images.mkdirs();
File img = new File(images, "PacMan-" + q + "x" + num + ".gif");
ImageIO.write(bi, "gif", img);
}
public static void main(String[] args) {
try {
for (int ii = 0; ii < 4; ii++) {
PacManShape pms = new PacManShape(100, (double) ii * Math.PI / 2d);
for (int jj = 0; jj <= pms.maxSize; jj++) {
pms.savePacManImage(ii, jj);
}
}
Desktop.getDesktop().open(images);
} catch (IOException ex) {
ex.printStackTrace();
}
Runnable r = new Runnable() {
#Override
public void run() {
JPanel gui = new JPanel(new BorderLayout());
gui.add(new PacManComponent());
JOptionPane.showMessageDialog(null, gui);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
class PacManComponent extends JPanel {
double angle = 0d;
int preferredSize = 100;
double diff = Math.PI / 8;
boolean chomp = true;
Timer timer;
PacManComponent() {
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
};
timer = new Timer(180, listener);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(preferredSize, preferredSize);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
//double size = (getWidth() < getHeight() ? getWidth() : getHeight());
if (angle > 2 * Math.PI / 3) {
chomp = true;
} else if (angle < 0.01) {
chomp = false;
}
if (chomp) {
angle -= diff;
} else {
angle += diff;
}
PacManShape pms = new PacManShape(100, 0d);
Image image = pms.getPacManImage(angle, new Color(0, 0, 0, 0));
g2.drawImage(image, 0, 0, this);
g2.dispose();
}
}
If you wanted to transform & render images at run-time, try starting with this series of PNG format images that uses partial transparency to soften the edges.
For the animation, you could use a Swing Timer to move the Pacman graphic as well as adjusting the angle by which the "mouth" opens, by varying the parameters used by fillArc.
Interaction with KeyEvents for movement control can be acheived using Key Bindings.
Also, I would move the paint functionality to a paintComponent method in a sub-classed JComponent for better paint performance.
Related: Painting with Swing
Edit:
As youre starting Java there are a number of tasks to get working first
Create the JComponent based class with a static Pacman graphic. Move your painting logic to paintComponent
Get the Swing Timer functionality working. Follow the Oracle guide for Timers.
Implement the Key Bindings
Other functionality such as score keeping, etc.
2d animation:
http://en.wikipedia.org/wiki/File:The_Horse_in_Motion.jpg
Pseudocode:
while programActive:
deltatime = get_time_since_last_call()
update_animation_frame(deltatime)
image = get_animation_frame()
draw_background()
draw(image)
enforce_framerate(24)
To learn and do this sort of thing in Pygame would be easy compared to Java, but unsuitable for larger projects
I have gone through this website Change look and feel of JSlider
but except for Slider.altTrackColor nothing else is working. I want to do something like shown in pic1 any suggestion would be of great help. I'm working on JDK 1.6.
UIDefaults defaults = UIManager.getDefaults();
defaults.put("Slider.altTrackColor", Color.red);
defaults.put("Slider.thumb", Color.red);
I have also tried this:
WindowUtilities.setNativeLookAndFeel();
// WindowUtilities.setNimbuzzLookAndFeel();
// WindowUtilities.setJavaLookAndFeel();
WindowUtilities is class that tells the system to use native look and feel, as in previous releases. Metal (Java) LAF is the default otherwise.
public static void setNativeLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
System.out.println("Error setting native LAF: " + e);
}
Here is a full example of working UI that shown on 1st image:
(no magic - just a bit of work with graphics and basic UI knowledge)
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.plaf.basic.BasicSliderUI;
/**
*
* #see http://stackoverflow.com/a/12297384/714968
*/
public class CustomSliderUI extends BasicSliderUI {
private BasicStroke stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 0f, new float[]{1f, 2f}, 0f);
public CustomSliderUI(JSlider b) {
super(b);
}
#Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
#Override
protected Dimension getThumbSize() {
return new Dimension(12, 16);
}
#Override
public void paintTrack(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Stroke old = g2d.getStroke();
g2d.setStroke(stroke);
g2d.setPaint(Color.BLACK);
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2,
trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
} else {
g2d.drawLine(trackRect.x + trackRect.width / 2, trackRect.y,
trackRect.x + trackRect.width / 2, trackRect.y + trackRect.height);
}
g2d.setStroke(old);
}
#Override
public void paintThumb(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int x1 = thumbRect.x + 2;
int x2 = thumbRect.x + thumbRect.width - 2;
int width = thumbRect.width - 4;
int topY = thumbRect.y + thumbRect.height / 2 - thumbRect.width / 3;
GeneralPath shape = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
shape.moveTo(x1, topY);
shape.lineTo(x2, topY);
shape.lineTo((x1 + x2) / 2, topY + width);
shape.closePath();
g2d.setPaint(new Color(81, 83, 186));
g2d.fill(shape);
Stroke old = g2d.getStroke();
g2d.setStroke(new BasicStroke(2f));
g2d.setPaint(new Color(131, 127, 211));
g2d.draw(shape);
g2d.setStroke(old);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
JSlider slider = new JSlider(0, 100);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(25);
slider.setUI(new CustomSliderUI(slider));
frame.add(slider);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
You can easily modify the thumb (gripper) size by changing the returned bounds. The thumb painting will adapt to any size. And you can also easily customize painting of any other slider part.
Here is the final view by the way:
P.S. I did not adapt UI for vertical sliders, but that shouldn't take too long.