Simple circle rotation (simulate motion) - java

I have a simple animation in Java that consists of a wheel moving across a window. It is just a plain circle that starts off of the screen from the left, enters and continues to the right until it goes off of the screen. Then it loops and repeats this process.
X is a variable that contains the position of the wheel. It can be between -(wheel width) and the window size + the wheel width.
I would like to simulate rotation by drawing a circle within this wheel, that rotates around the circle as if it were attached.
Imagine a bike wheel in real life with a red flag on the wheel. As the wheel rotates, the red flag would be on the edge on the wheel moving as the wheel progresses. This is the behavior I want.
I am getting a percentage to pass into my wheel class like this:
int percentage = x/windowWidth;
Each frame that the wheel moves, I call wheel.rotate(percentage).
This is the implementation:
private int diameter = 50;
private final int SPOKE_DIAMETER = diameter/5;
public void rotate(double percent){
this.percent = percent;
this.theta = percent*(PI*2);
System.out.println(percent*PI);
}
public void paintComponent(Graphics canvas)
{
// wheel
canvas.setColor(Color.gray);
canvas.fillOval(0, 0, diameter, diameter);
// spinning flag
canvas.setColor(Color.red);
canvas.fillOval((int)(percent*diameter),(int)((sin((percent*(PI*2)))*diameter)), SPOKE_DIAMETER,SPOKE_DIAMETER);
}
The x location works more or less how I wanted, but the y does not. It wiggles like a sin wave, which is expected (I did use sin...), however, I'm not sure how to alter my math to follow the circle around.
What is wrong with my implementation? (I'm not very good with drawing with trigonometric functions)

Basically, you need to calculate the point on the circle, based on an angle that the object should appear...
Like most things, I stole this off the internet somewhere, but it works...
protected Point getPointOnCircle(float degress, float radius) {
int x = Math.round(getWidth() / 2);
int y = Math.round(getHeight() / 2);
double rads = Math.toRadians(degress - 90); // 0 becomes the top
// Calculate the outter point of the line
int xPosy = Math.round((float) (x + Math.cos(rads) * radius));
int yPosy = Math.round((float) (y + Math.sin(rads) * radius));
return new Point(xPosy, yPosy);
}
Based on an angel (in degrees) and the radius of the circle, this will return the x/y position along the circumference of the circle...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class RotateWheel {
public static void main(String[] args) {
new RotateWheel();
}
public RotateWheel() {
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 float degrees = 0;
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
degrees += 0.5f;
repaint();
}
});
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int diameter = Math.min(getWidth(), getHeight());
int x = (getWidth() - diameter) / 2;
int y = (getHeight() - diameter) / 2;
g2d.setColor(Color.GREEN);
g2d.drawOval(x, y, diameter, diameter);
g2d.setColor(Color.RED);
float innerDiameter = 20;
Point p = getPointOnCircle(degrees, (diameter / 2f) - (innerDiameter / 2));
g2d.drawOval(x + p.x - (int) (innerDiameter / 2), y + p.y - (int) (innerDiameter / 2), (int) innerDiameter, (int) innerDiameter);
g2d.dispose();
}
protected Point getPointOnCircle(float degress, float radius) {
int x = Math.round(getWidth() / 2);
int y = Math.round(getHeight() / 2);
double rads = Math.toRadians(degress - 90); // 0 becomes the top
// Calculate the outter point of the line
int xPosy = Math.round((float) (x + Math.cos(rads) * radius));
int yPosy = Math.round((float) (y + Math.sin(rads) * radius));
return new Point(xPosy, yPosy);
}
}
}

Related

How do I draw multiple line looks like dividing the sectors of a panel Java?

I would like to know how to draw multiple line that looks like dividing the panel into sectors.
This is the example of lines that I wanted to draw
Below are the code of so far I've figured it out but it can only draw "x" line and a one horizontal line on the panel. I would like to know how is it possible for me to draw lines like the image above.
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graphic = (Graphics2D)g;
Insets insets = getInsets();
graphic.setStroke(new BasicStroke(5.0f));
graphic.draw(new Line2D.Double(insets.left, insets.top,getWidth()-insets.right, getHeight()-insets.bottom));
graphic.draw(new Line2D.Double(insets.left,getHeight()-insets.bottom,getWidth()-insets.right,insets.top));
graphic.drawLine(0,200,800,200);
}
thank you.
There's probably a few ways you could do this, but to me, this looks like spokes on a wheel, and since I know how to calculate a point a circle, this is where I'd fall back to.
What do we know:
We know the area (size of the panel)
The number of segments/divisions we want
How to calculate a point on a circle
So with that basic information, we can devise the angle delta which would required to draw the number of divisions evenly around the center point
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
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 {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected Point2D pointAt(double radians, double radius) {
double x = radius * Math.cos(radians);
double y = radius * Math.sin(radians);
return new Point2D.Double(x, y);
}
protected Point2D translate(Point2D point, Point2D to) {
Point2D newPoint = new Point2D.Double(point.getX(), point.getY());
newPoint.setLocation(point.getX() + to.getX(), point.getY() + to.getY());
return newPoint;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
double startAngle = 0;
double divisions = 12;
double delta = 360.0 / divisions;
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
int radius = Math.min(centerX, centerY) * 2; // Overshoot the visible bounds
Point2D centerPoint = new Point2D.Double(centerX, centerY);
double angle = startAngle;
for (int index = 0; index < divisions; index++) {
Point2D point = pointAt(Math.toRadians(angle), radius);
point = translate(point, centerPoint);
g2d.draw(new Line2D.Double(centerPoint, point));
angle += delta;
}
g2d.dispose();
}
}
}
Now, if you prefer not to have the lines "overshoot", then change
int radius = Math.min(centerX, centerY) * 2; // Overshoot the visible bounds
to
int radius = Math.min(centerX, centerY);
Now, if you want it to look a little "nicer", you could consider adding
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHints(hints);
into the paintComponent method before you paint anything

Projecting mouse coordinates

This question has probably been answered but from the ones i have found they don't seem to work, others actually not making any changes.
I'm creating a game, the game has a screen (Canvas) that is inside of the window (JFrame). In this game i would like to use a mouse, as well as allowing the user to maximize the window. The game screen stays the same size no matter what, but if the window is re-sized, so i scale the game image to the size of the window.
My problem is that i cannot find a suitable way to project the coordinates of the the mouse, as when the window is maximized, its coordinates are still being read as if the window were still normal sized, creating an offset.
I've tried:
#Override public void mouseMoved(MouseEvent e){
MOUSE_X = Math.round((float) e.getX() / (float) RenderableCanvas.oldSizeX * (float) f.getWidth());
MOUSE_Y = Math.round((float) e.getY() / (float) RenderableCanvas.oldSizeY * (float) f.getHeight());
}
Where MOUSE_X/MOUSE_Y are static variables that can be referenced anywhere in the program to get the mouse location.
and RenderableCanvas is the game window, containing an embedded canvas object, this class also keeps track of the original size of the window stated as oldSizeX and oldSizeY
and finally f.getHeight() and f.getWidth() are the current size of the frame, as f is a reference to the JFrame inside of the RenderableCanvas class.
but all that does the same as:
#Override public void mouseMoved(MouseEvent e){
MOUSE_X = e.getX();
MOUSE_Y = e.getY();
}
Thank you for any help in advance.
The basic idea is you need to be able to convert between the two coordinate systems, in this case, the "world" which is the space getting scaled and the "view" which is what the user sees (or something like that)
The basic maths is to use the default value and the current value to generate a percentage value, by which you can then multiple the target value by, for example convert from the view to the world might look like...
pointInView * (staticSize / currentSize)
So, given a point in "world" coordinates, you need to scale back to "view" coordinates...
protected Point toView(int x, int y) {
return toView(new Point(x, y));
}
protected Point toView(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.y = Math.round(p.y * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
And given "view" coordinates, you need to scale up to the "world" coordinates...
protected Point toWorld(int x, int y) {
return toWorld(new Point(x, y));
}
protected Point toWorld(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) DEFAULT_WIDTH) / (float) getWidth());
scaled.y = Math.round(p.y * ((float) DEFAULT_HEIGHT) / (float) getHeight());
return scaled;
}
So, for example, when the mouse is moved or clicked on your "view", you could use
Point world = toWorld(e.getPoint());
to convert the mouse point into world coordinates
... please feel free to rename those to suit your own needs, but basically, view is the physical view that the user sees and is your virtual concept of that view...
The basic concept will work for Dimension and by extension, Rectangle as well...
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.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
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 {
protected static final int DEFAULT_WIDTH = 200;
protected static final int DEFAULT_HEIGHT = 200;
private Dimension preferredSize = new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
private JLabel properties;
private boolean highlighted = false;
private Rectangle hoverRect = new Rectangle(10, 10, 50, 50);
public TestPane() {
setLayout(new GridBagLayout());
properties = new JLabel("...");
add(properties);
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Point world = toWorld(e.getPoint());
highlighted = hoverRect.contains(world);
repaint();
properties.setText("<html>#" + format(e.getPoint())
+ "<br>world = " + format(world)
+ "<br>view = " + format(toView(world)));
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
preferredSize = new Dimension(DEFAULT_WIDTH * 2, DEFAULT_HEIGHT * 2);
SwingUtilities.windowForComponent(TestPane.this).pack();
}
});
}
protected String format(Point p) {
return p.x + "x" + p.y;
}
protected Point toView(int x, int y) {
return toView(new Point(x, y));
}
protected Point toView(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.y = Math.round(p.y * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
protected Point toWorld(int x, int y) {
return toWorld(new Point(x, y));
}
protected Point toWorld(Point p) {
Point scaled = new Point(p);
scaled.x = Math.round(p.x * ((float) DEFAULT_WIDTH) / (float) getWidth());
scaled.y = Math.round(p.y * ((float) DEFAULT_HEIGHT) / (float) getHeight());
return scaled;
}
protected Rectangle toWorld(Rectangle bounds) {
return toWorld(bounds.x, bounds.y, bounds.width, bounds.height);
}
protected Rectangle toWorld(int x, int y, int width, int height) {
Rectangle scaled = new Rectangle();
scaled.setLocation(toWorld(x, y));
scaled.width = Math.round(width * ((float) DEFAULT_WIDTH / (float) getWidth()));
scaled.height = Math.round(height * ((float) DEFAULT_HEIGHT / (float) getHeight()));
return scaled;
}
protected Rectangle toView(Rectangle bounds) {
return toView(bounds.x, bounds.y, bounds.width, bounds.height);
}
protected Rectangle toView(int x, int y, int width, int height) {
Rectangle scaled = new Rectangle();
scaled.setLocation(toView(x, y));
scaled.width = Math.round(width * ((float) getWidth() / (float) DEFAULT_WIDTH));
scaled.height = Math.round(height * ((float) getHeight() / (float) DEFAULT_HEIGHT));
return scaled;
}
#Override
public Dimension getPreferredSize() {
return preferredSize;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = toView(hoverRect);
if (highlighted) {
g2d.setColor(Color.BLUE);
g2d.fill(bounds);
}
g2d.setColor(Color.BLACK);
g2d.draw(bounds);
}
}
}
So i think I've got it, i did some old Pen and Paper math and realized that i had part of my equation flipped from what i thought i should have.
This seems to work:
#Override public void mouseMoved(MouseEvent e){
MOUSE_X = (int) ((float) e.getX() / (float) f.getWidth() * (float) RenderableCanvas.oldSizeX);
MOUSE_Y = (int) ((float) e.getY() / (float) f.getHeight() * (float) RenderableCanvas.oldSizeY);
}

Calculating Points on a Circle [Java / Processing]

I need to calculate where the red lines (on the image below) cross the circumference of the circle. The problem is I don't know at what angle (from the center) they will cross the circumference.
The only things I know are the radius of the circle (represented by the blue line) and the x positions of the red lines (each offset by radius/4, represented by the green line).
A mathematical solution of any kind would be appreciated, but bonus points for Java / Processing.
You know the horizontal value, being the distance from the red line to the center. Let's call that horz.
You know the radius already, so you can get the angle as
Math.acos(horz / radius)
(worked out, not tested)
For normalized coordinates, the computation for the y-coordinate is
private static double computeY(double x)
{
return Math.sin(Math.acos(x));
}
"Normalized" means that
The parameter x is a value between 0.0 and 1.0 which be computed from the absolute coordinates by dividing by the radius
the result, y, is a value between 0.0 and 1.0, that can be converted to an absolute coordinates by multiplying with the radius
If you only need the angle, this can simply be computed as Math.acos(x)
The result looks like this:
The code:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CircleIntersectionTest
{
public static void main(String[] args) throws IOException
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new CircleIntersectionPanel());
f.setSize(500,500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class CircleIntersectionPanel extends JPanel
implements MouseMotionListener
{
private Point mousePosition = null;
CircleIntersectionPanel()
{
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
double centerX = getWidth() / 2;
double centerY = getHeight() / 2;
double radius = 200;
g.setStroke(new BasicStroke(2));
g.setColor(Color.BLACK);;
g.draw(new Ellipse2D.Double(
centerX-radius, centerY-radius,
radius+radius, radius+radius));
if (mousePosition == null)
{
return;
}
g.setColor(Color.RED);
g.draw(new Line2D.Double(
mousePosition.x, centerY, mousePosition.x, 0));
g.setColor(Color.BLUE);
double x = (mousePosition.x - centerX) / radius;
double y = computeY(x);
double cx = centerX + radius * x;
double cy = centerY - radius * y;
g.fill(new Ellipse2D.Double(cx-8, cy-8, 16, 16));
g.setColor(Color.BLACK);
g.drawString("x = "+x, 10, 30);
g.drawString("y = "+y, 10, 46);
g.drawString("angle: "+Math.toDegrees(Math.acos(x)), 10, 62);
}
private static double computeY(double x)
{
return Math.sin(Math.acos(x));
}
#Override
public void mouseMoved(MouseEvent e)
{
mousePosition = e.getPoint();
repaint();
}
#Override
public void mouseDragged(MouseEvent e)
{
}
}

How do I zoom inside JScrollPane with AffineTransform without shifting[EDITED]

I am trying to implement a zoom tool for my game editor. I am using a Color[] to store all the "Colors/tiles" and I want to be able to zoom inside my JPanel to view all the tiles upclose or from far away i.e zoomed in or zoomed out. These are some requirements that I would like to have(Any examples are appreciated and they don't need to include all or any of the requirements. They are there to help you understand what I am aiming for):
Zooming should be determined by a zoom variable that can be changed dynamicly(prefferably mouseWheel)
When zoomed(in or out) you should be able to navigate horisontaly and vertically with as little as possible tearing or other graphical glitches(using the JScrollBar s in the example)
The zooming should be based on where the mouse cursor is and zoom towards that point
The zooming can use anything inside normal Java which means no external libraries.
This is a very simple version of my editor. I added some test code for zooming but it doesn't work. I am giving you this code so you have something to start from if neccesary. See the PaintComponent method and the mouseWheel listener.
EDITED: Thanks to #trashgod you can now place colors at the right position. See MouseTest class!
The tearing is gone.
package stuff;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
public class ZoomPane extends JPanel implements MouseWheelListener, Scrollable {
private int width, height, screenWidth, screenHeight, tileSize;
private Color[] colorMap;
private double scale = 1.0;
// Zooming
AffineTransform at;
class MouseTest extends MouseAdapter {
public void mousePressed(MouseEvent e) {
try {
int newX = (int) at.inverseTransform(e.getPoint(), null).getX();
int newY = (int) at.inverseTransform(e.getPoint(), null).getY();
colorMap[(newX / tileSize) + ((newY / tileSize) * width)] = getRandomColor();
} catch (NoninvertibleTransformException e1) {
e1.printStackTrace();
}
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
super.mouseDragged(e);
try {
System.out.println("Dragging");
int newX = (int) at.inverseTransform(e.getPoint(), null).getX();
int newY = (int) at.inverseTransform(e.getPoint(), null).getY();
colorMap[(newX / tileSize) + ((newY / tileSize) * width)] = getRandomColor();
} catch (NoninvertibleTransformException e1) {
e1.printStackTrace();
}
repaint();
}
}
public ZoomPane(int width, int height, int tileSize) {
super();
this.width = width;
this.height = height;
this.screenWidth = width * tileSize;
this.screenHeight = height * tileSize;
this.tileSize = tileSize;
this.colorMap = new Color[width * height];
addMouseWheelListener(this);
addMouseListener(new MouseTest());
addMouseMotionListener(new MouseTest());
}
public void paintComponent(Graphics g) {
super.paintComponents(g);
final Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Scale
at = null;
at = g2d.getTransform();
// Translate code here?
at.scale(scale, scale);
g2d.setTransform(at);
final Rectangle clip = g2d.getClipBounds();
g2d.setColor(Color.DARK_GRAY);
g2d.fill(clip);
int topX = clip.x / tileSize;
int topY = clip.y / tileSize;
int bottomX = clip.x + clip.width / tileSize + 1 + (int) (tileSize * scale);
int bottomY = clip.y + clip.height / tileSize + 1;
// Draw colors
for (int y = topY; y < bottomY; y++) {
for (int x = topX; x < bottomX; x++) {
Rectangle r = new Rectangle(width, height);
if (r.contains(x, y) && colorMap[x + y * width] != null) {
g2d.setColor(colorMap[x + y * width]);
g2d.fillRect(x * tileSize, y * tileSize, tileSize, tileSize);
}
}
}
g2d.dispose();
}
private Color getRandomColor() {
Random rand = new Random();
return new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255));
}
#Override
public Dimension getPreferredSize() {
return new Dimension((int) (screenWidth), (int) (screenHeight));
}
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
double delta = 0.05 * e.getPreciseWheelRotation();
if (scale + delta > 0)
scale += delta;
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Zoom test");
// Frame settings
frame.setVisible(true);
frame.setPreferredSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane pane = new JScrollPane(new ZoomPane(50, 50, 32));
frame.add(pane);
frame.pack();
}
});
}
#Override
public Dimension getPreferredScrollableViewportSize() {
repaint();
return null;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
repaint();
return 0;
}
#Override
public boolean getScrollableTracksViewportHeight() {
repaint();
return false;
}
#Override
public boolean getScrollableTracksViewportWidth() {
repaint();
return false;
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
repaint();
return 0;
}
}
If you try to run the program you will see these problems:
When you move the JScrollBars it seams that the mouse position gets an offset when you try to place a color.
If you zoom/scroll the mouse whell everything shifts up/down and left/right. I would like to zoom at the mouse cursor/point or atleast not shift everything sideways.
This is what works at the moment:
Placing of colors works correctly now.
Moving verticaly or horizontaly doesnt tear anymore.
As you see most of the requirements I mentioned at the top can be found in articles here on SO and most of them are really good and well described but I don't know/ can't implement them so that I can solve the problems above.
My goal with this zoom would be something like the example in here with the exception of drawing my "Colors/tiles" instead of the rectangles he draws and that I am using AffineTransform. Otherwise that example is really what I am aiming for.
It doesn't have to use any of the code he uses. I would preffer to use AffineTransform. If any of you knows how to implement what I am looking for in another way I am all ears. I thought that the example might make it easier for you guys to understand what I am aiming for.
I accept any changes or comments about the code or the implementaion and I will respond as quickly as I can and change the post.
Many thanks,
Towni0

Java graphics draw circle with specific parameter

For a problem I have to draw a circle on the screen with center at coordinates (280,300) with a radius of 50. The hint says: A circle is an oval with the same width and height. The center of this circle is 50 pixels below and 50 pixels to the right of the NW corner of this oval.
There is the TryoutPanel class:
import java.awt.*;
import javax.swing.*;
public class TryoutPanel extends JPanel{
private Color myColor;
public TryoutPanel(Color c){
myColor = c;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
setForeground(myColor);
g.drawString("top",10,50);
g.drawLine(10,60, 200,60);
g.drawString("middle",10,80);
g.drawLine(10,90, 200,90);
g.drawString("bottom",10,110);
g.drawLine(10,120, 200,120);
g.drawRect(200,300,100,50);
g.drawOval(200,300,100,50);
for(int j = 0; j < 9; j++)
g.drawOval(50,200, 10 + 20*j, 210 - 20*j);
}
}
I have to fill in the code in the following:
public void paintComponent(Graphics g){
super.paintComponent(g);
setForeground(myColor);
//INSERT CODE HERE
I tried:
g.drawOval(280,300,50,50);
But it says I used incorrect parameters. What am I doing wrong.
The x/y parameter of drawOval is the top/left corner from where the oval will be drawn
In order to be able to draw the circle around the center point if 230x300, you will need to subtract the radius from each point and then generate a width and height (diameter) of double that...
g.drawOval(230 - radius, 300 - radius, radius * 2, radius * 2);
So, this example basic draws a rectangle around the point of 230x300 with a width/height of 200 (radius = 100) and draws lines through this point to illustrate the center point the oval then drawn about...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TryoutOval {
public static void main(String[] args) {
new TryoutOval();
}
public TryoutOval() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TryoutPanel(Color.RED));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TryoutPanel extends JPanel {
private Color myColor;
public TryoutPanel(Color c) {
myColor = c;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int centerX = 280;
int centerY = 300;
int radius = 50;
int diameter = radius * 2;
int x = centerX - radius;
int y = centerY - radius;
g.setColor(Color.BLACK);
g.drawRect(x, y, diameter, diameter);
g.drawLine(x, y, x + diameter, y + diameter);
g.drawLine(x + diameter, y, x, y + diameter);
g.setColor(myColor);
g.drawOval(x, y, diameter, diameter);
g.fillOval(centerX - 5, centerY - 5, 10, 10);
}
}
}
Oh, and setForeground(myColor); is a horribly bad idea within any paint method as it will cause a paint event to be added to the event queue each time the method is called, which will cause a never ending repaint request which will eventually consume your CPU

Categories

Resources