Java AWT: JFrame SetLocation should not move outside the screen - java

Using the four buttons, the window should be moved in four directions (north, south, east, west) and the window should not leave the screen. This works smoothly to the north and west, but unfortunately not in the other directions. I guess that the error is in the getEffectiveScreenArea method, but I am not sure.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MoveWindowGUI extends JFrame {
private JButton moveUp, moveDown, moveLeft, moveRight;
private int x, y;
public MoveWindowGUI(String title) {
super(title);
this.initializeButtons();
this.prepareWindow();
this.addActionListener();
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
private void initializeButtons() {
this.moveUp = new JButton("U");
this.moveDown = new JButton("D");
this.moveLeft = new JButton("L");
this.moveRight = new JButton("R");
}
private void prepareWindow() {
setLayout(new BorderLayout(25, 25));
this.addComponents();
this.centerWindow();
setSize(300, 300);
}
private void centerWindow() {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension windowSize = getSize();
int centralWidth = (screenSize.width - windowSize.width) / 2;
int centralHeight = (screenSize.height - windowSize.height) / 2;
setLocation(centralWidth, centralHeight);
}
private void addComponents() {
add(this.moveUp, BorderLayout.NORTH);
add(this.moveDown, BorderLayout.SOUTH);
add(this.moveLeft, BorderLayout.WEST);
add(this.moveRight, BorderLayout.EAST);
}
private void addActionListener() {
ActionListener listener = new WindowActionListener();
moveUp.addActionListener(listener);
moveDown.addActionListener(listener);
moveLeft.addActionListener(listener);
moveRight.addActionListener(listener);
}
class WindowActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("U")) {
y -= 10;
} else if (command.equals("D")) {
y += 10;
} else if (command.equals("L")) {
x -= 10;
} else if (command.equals("R")) {
x += 10;
}
this.refreshWindow();
}
private void refreshWindow() {
Point lastLocation = getLocation();
Rectangle effectiveScreenArea = getEffectiveScreenArea();
int newX = lastLocation.x + x;
int newY = lastLocation.y + y;
if (newX < effectiveScreenArea.x) {
newX = effectiveScreenArea.x;
} else if (newY < effectiveScreenArea.y) {
newY = effectiveScreenArea.y;
} else if (newX >= effectiveScreenArea.width) {
newX = effectiveScreenArea.width;
} else if (newY >= effectiveScreenArea.height) {
newY = effectiveScreenArea.height;
}
setLocation(newX, newY);
this.resetHeightAndWitdhLocally();
pack();
}
public Rectangle getEffectiveScreenArea() {
int minX = 0, minY = 0, maxX = 0, maxY = 0;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
int screenDevices = environment.getScreenDevices().length;
for(GraphicsDevice device : environment.getScreenDevices()) {
Rectangle bounds = device.getDefaultConfiguration().getBounds();
minX = Math.min(minX, bounds.x);
minY = Math.min(minY, bounds.y);
maxX = Math.max(maxX, bounds.x + bounds.width);
maxY = Math.max(maxY, bounds.y + bounds.height);
}
return new Rectangle(minX, minY, (maxX - minX) / screenDevices, (maxY - minY) / screenDevices);
}
/*
private Rectangle getEffectiveScreenArea() {
GraphicsConfiguration graphicsConfiguration = getGraphicsConfiguration();
Rectangle bounds = graphicsConfiguration.getBounds();
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration);
Rectangle effectiveScreenArea = new Rectangle();
effectiveScreenArea.x = bounds.x + screenInsets.left;
effectiveScreenArea.y = bounds.y + screenInsets.top;
effectiveScreenArea.height = bounds.height + screenInsets.top - screenInsets.bottom;
effectiveScreenArea.width = bounds.width - screenInsets.left - screenInsets.right;
return effectiveScreenArea;
}
*/
private void resetHeightAndWitdhLocally() {
x = 0;
y = 0;
}
}
}

I took your code and modified it somewhat. Here's the GUI I created.
I placed the JButtons on a JPanel. Then I placed the JPanel on the JFrame. Generally, it's a good idea to put Swing components on a JPanel, rather than directly on the JFrame.
I cleaned up the WindowActionListener class.
Here's the complete runnable code. I made the WindowActionListener class an inner class so I could post this code as one block.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MoveWindowGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new MoveWindowGUI());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame("Move Window GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
WindowActionListener listener = new WindowActionListener(this);
JButton upButton = new JButton("Up");
upButton.addActionListener(listener);
panel.add(upButton, BorderLayout.NORTH);
JButton downButton = new JButton("Down");
downButton.addActionListener(listener);
panel.add(downButton, BorderLayout.SOUTH);
JButton leftButton = new JButton("Left");
leftButton.addActionListener(listener);
panel.add(leftButton, BorderLayout.WEST);
JButton rightButton = new JButton("Right");
rightButton.addActionListener(listener);
panel.add(rightButton, BorderLayout.EAST);
Dimension d = panel.getPreferredSize();
d.width = 300;
panel.setPreferredSize(d);
return panel;
}
public JFrame getFrame() {
return frame;
}
public class WindowActionListener implements ActionListener {
private final MoveWindowGUI view;
public WindowActionListener(MoveWindowGUI view) {
this.view = view;
}
#Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
int increment = 100;
switch (command) {
case "Up":
refreshWindow(0, -increment);
break;
case "Down":
refreshWindow(0, increment);
break;
case "Left":
refreshWindow(-increment, 0);
break;
case "Right":
refreshWindow(increment, 0);
break;
}
}
private void refreshWindow(int deltaX, int deltaY) {
Rectangle frameArea = view.getFrame().getBounds();
Rectangle screenArea = getEffectiveScreenArea();
int x = frameArea.x;
int y = frameArea.y;
int minX = screenArea.x;
int minY = screenArea.y;
int maxX = screenArea.width - frameArea.width;
int maxY = screenArea.height - frameArea.height;
x += deltaX;
y += deltaY;
x = Math.max(minX, x);
x = Math.min(maxX, x);
y = Math.max(minY, y);
y = Math.min(maxY, y);
view.getFrame().setBounds(new Rectangle(x, y, frameArea.width, frameArea.height));
}
private Rectangle getEffectiveScreenArea() {
int minX = 0, minY = 0, maxX = 0, maxY = 0;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
int screenDevices = environment.getScreenDevices().length;
for (GraphicsDevice device : environment.getScreenDevices()) {
Rectangle bounds = device.getDefaultConfiguration().getBounds();
minX = Math.min(minX, bounds.x);
minY = Math.min(minY, bounds.y);
maxX = Math.max(maxX, bounds.x + bounds.width);
maxY = Math.max(maxY, bounds.y + bounds.height);
}
return new Rectangle(minX, minY, (maxX - minX) / screenDevices,
(maxY - minY) / screenDevices);
}
}
}

Related

Vertical alignment of a bottom panel

I want to vertically align 3 buttons in a bottom panel.
Here's what I wrote:
ClientWindow(){
pickBtn = new JButton();
attackBtn = new JButton();
placeBtn = new JButton();
JPanel userPanel = new JPanel();
userPanel.setPreferredSize(new Dimension(100,100));
userPanel.setBackground(Color.red);
JFrame frame = new JFrame();
frame.setTitle("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.setResizable(false);
frame.setSize(1280,720);
frame.setLocationRelativeTo(null);
frame.add(userPanel,BorderLayout.SOUTH);
userPanel.add(pickBtn);
userPanel.add(attackBtn);
userPanel.add(placeBtn);
frame.setVisible(true);
}
How could I align them vertically?
Take a look at Laying Out Components Within a Container
For example, this following uses a GridBagLayout
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JLabel label = new JLabel("This is just here to make some content");
label.setBorder(new EmptyBorder(32, 32, 32, 32));
JFrame frame = new JFrame();
frame.add(label);
frame.add(new UserPanel(), BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class UserPanel extends JPanel {
public UserPanel() {
JButton pickBtn = new JButton("Pick");
JButton attackBtn = new JButton("Attack");
JButton placeBtn = new JButton("Place");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(pickBtn, gbc);
add(attackBtn, gbc);
add(placeBtn, gbc);
}
}
}
Make a ButtonLayout
Important
Please note: The following is intended to replace the GridBagLayout from the above example, as GridBagLayout is complicated and might be a little overkill for this purpose
A REALLY long time ago, I can across a really neat concept of a ButtonLayout, it basically provided a simple layout manager to layout buttons similar to how most OS'es do it (ie, the buttons are of equal size).
The following is a VERY basic example of that concept.
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new UserPanel());
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class UserPanel extends JPanel {
public UserPanel() {
JButton pickBtn = new JButton("Pick");
JButton attackBtn = new JButton("Attack");
JButton placeBtn = new JButton("Place");
setBorder(new LineBorder(Color.BLACK));
setLayout(new ButtonLayout(ButtonLayout.Alignment.VERTICAL, ButtonLayout.Anchor.TRAILING));
add(pickBtn);
add(attackBtn);
add(placeBtn);
}
}
public class ButtonLayout implements LayoutManager2 {
public enum Alignment {
VERTICAL, HORIZONTAL
}
public enum Anchor {
LEADING, CENTER, TRAILING
}
private Alignment alignment;
private Anchor anchor;
private int padding;
private Dimension virtualBounds;
public ButtonLayout() {
this(Alignment.HORIZONTAL, Anchor.TRAILING, 0);
}
public ButtonLayout(Alignment alignment, Anchor anchor) {
this(alignment, anchor, 0);
}
public ButtonLayout(Alignment alignment, Anchor anchor, int padding) {
this.alignment = alignment;
this.padding = padding;
this.anchor = anchor;
}
public Alignment getAlignment() {
return alignment;
}
public Anchor getAnchor() {
return anchor;
}
protected int getPadding() {
return padding;
}
protected int getTotalPadding(Container parent) {
int padding = getPadding();
return (padding * parent.getComponentCount()) - padding;
}
#Override
public void addLayoutComponent(Component comp, Object constraints) {
}
#Override
public void addLayoutComponent(String name, Component comp) {
}
#Override
public void removeLayoutComponent(Component comp) {
}
#Override
public void invalidateLayout(Container target) {
virtualBounds = null;
}
protected Dimension virtualLayout(Container parent) {
if (virtualBounds != null) {
return virtualBounds;
}
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension preferredSize = component.getPreferredSize();
maxHeight = Math.max(maxHeight, preferredSize.height);
maxWidth = Math.max(maxWidth, preferredSize.width);
}
int padding = 0;
int width = 0;
int height = 0;
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL:
width = (maxWidth * componentCount) + getTotalPadding(parent);
height = maxHeight;
break;
case VERTICAL:
width = maxWidth;
height = (maxHeight * componentCount) + getTotalPadding(parent);
break;
}
virtualBounds = new Dimension(width, height);
return virtualBounds;
}
#Override
public Dimension maximumLayoutSize(Container parent) {
return virtualLayout(parent);
}
#Override
public Dimension preferredLayoutSize(Container parent) {
return virtualLayout(parent);
}
#Override
public Dimension minimumLayoutSize(Container parent) {
return virtualLayout(parent);
}
#Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
#Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
#Override
public void layoutContainer(Container parent) {
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension preferredSize = component.getPreferredSize();
maxHeight = Math.max(maxHeight, preferredSize.height);
maxWidth = Math.max(maxWidth, preferredSize.width);
}
Dimension defaultSize = new Dimension(maxWidth, maxHeight);
Point point = offsetForAnchor(parent, defaultSize);
int xDelta = 0;
int yDelta = 0;
switch (alignment) {
case HORIZONTAL:
xDelta = getPadding() + defaultSize.width;
break;
case VERTICAL:
yDelta = getPadding() + defaultSize.height;
break;
}
for (Component component : parent.getComponents()) {
component.setSize(defaultSize);
component.setLocation(point);
point = new Point(point.x + xDelta, point.y + yDelta);
}
}
protected Point offsetForAnchor(Container parent, Dimension defaultSize) {
switch (anchor) {
case LEADING:
return leadingOffSet(parent, defaultSize);
case TRAILING:
return trailingOffSet(parent, defaultSize);
case CENTER:
return centerOffSet(parent, defaultSize);
}
return new Point(0, 0);
}
protected Point leadingOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
switch (alignment) {
case HORIZONTAL:
point.x = padding;
point.y = (parent.getHeight() - defaultSize.height) / 2;
break;
case VERTICAL:
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = padding;
break;
}
return point;
}
protected Point trailingOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL:
int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
point.x = parent.getWidth() - totalWidth;
point.y = (parent.getHeight() - defaultSize.height) / 2;
break;
case VERTICAL:
int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = parent.getHeight() - totalHeight;
break;
}
return point;
}
protected Point centerOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL: {
int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - totalWidth) / 2;
point.y = (parent.getHeight() - defaultSize.height) / 2;
}
break;
case VERTICAL: {
int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = (parent.getHeight() - totalHeight) / 2;
}
break;
}
return point;
}
}
}

Drawing Circles to JFrame

I'm having issues drawing some circles to my JFrame. I originally had it using the default layout and realized this was only adding the most recent circle, so I changed the layout to null, and now nothing gets drawn. I've also tried frame.setLayout(new FlowLayout()) which also doesn't draw anything. Any help would be appreciated!
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
/**
* #author Christopher Nielson
*
*/
public class Main {
private static JFrame frame;
private static Random rand;
private static Jiggler jiggler;
private static ArrayList<JComponent> circles;
private static int fps;
public static void main(String[] args) {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setBounds(100, 100, 450, 450);
rand = new Random();
circles = new ArrayList<JComponent>();
int x = frame.getWidth();
int y = frame.getHeight();
for (int i = 0; i < Integer.parseInt(args[0]); i++) {
circles.add(new Circle(rand.nextInt(frame.getWidth()), rand.nextInt(frame.getHeight()),
rand.nextInt(frame.getWidth() / 10) + 100, rand.nextInt(frame.getHeight() / 10) + 100, null));
}
circles.forEach(current -> {
frame.add(current);
});
frame.setVisible(true);
jiggler = new Jiggler(circles, new JLabel("FPS: ")); // TODO add fps
jiggler.run();
}
}
And this is one reason you'll see us recommending time and time again to avoid using null layouts like the plague.
Having said that, your main problem is a design problem, not a layout problem, and that problem being that your Circle class shouldn't extend JComponent or any component for that matter, since if you want to draw multiple circles, you should have only one component, probably a JPanel doing the drawing, and the Circles should be logical classes, classes that have a public void draw(Graphics g) method, not component classes. You would pass the List of Circles to your drawing JPanel, and it would draw the Circles in its paintComponent method by calling the draw(g) methods of each Circle in the list.
For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class DrawChit extends JPanel {
private static final int PREF_W = 900;
private static final int PREF_H = 700;
private static final int MAX_SHAPES = 30;
private List<MyShape> shapes = new ArrayList<>();
public DrawChit() {
setBackground(Color.WHITE);
for (int i = 0; i < MAX_SHAPES; i++) {
double x = (PREF_W - 100) * Math.random();
double y = (PREF_H - 100) * Math.random();
double w = 100 + (Math.random() * PREF_W) / 10;
double h = 100 + (Math.random() * PREF_H) / 10;
Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
float hue = (float) Math.random();
double delta = 0.3;
float saturation = (float) (Math.random() * delta + (1 - delta));
float brightness = (float) (Math.random() * delta + (1 - delta));
Color color = Color.getHSBColor(hue, saturation, brightness);
shapes.add(new MyShape(ellipse, color));
}
// we'll throw a black square in the middle!
int rectW = 200;
int rectX = (PREF_W - rectW) / 2;
int rectY = (PREF_H - rectW) / 2;
shapes.add(new MyShape(new Rectangle(rectX, rectY, rectW, rectW), Color.BLACK));
MyMouse myMouse = new MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use anti-aliasing to make graphics smooth
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// iterate through the shapes list, filling all
for (MyShape shape : shapes) {
shape.fill(g2);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
private Point p0 = null;
private MyShape shape = null;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
// iterate *backwards* so get top-most Shape
for (int i = shapes.size() - 1; i >= 0; i--) {
if (shapes.get(i).contains(e.getPoint())) {
p0 = e.getPoint();
shape = shapes.get(i);
// move selected shape to the top!
shapes.remove(shape);
shapes.add(shape);
repaint();
return;
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (p0 != null) {
moveShape(e.getPoint());
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (p0 != null) {
moveShape(e.getPoint());
p0 = null;
shape = null;
}
}
// translates the shape
private void moveShape(Point p1) {
int deltaX = p1.x - p0.x;
int deltaY = p1.y - p0.y;
shape.translate(deltaX, deltaY);
p0 = p1;
repaint();
}
}
private static void createAndShowGui() {
DrawChit mainPanel = new DrawChit();
JFrame frame = new JFrame("Draw Chit");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MyShape {
private Path2D path = new Path2D.Double();
private Color color;
public MyShape(Shape shape, Color color) {
path.append(shape, true);
this.color = color;
}
public boolean contains(Point p) {
return path.contains(p);
}
public void draw(Graphics2D g2) {
g2.setColor(color);
g2.draw(path);
}
public void fill(Graphics2D g2) {
g2.setColor(color);
g2.fill(path);
}
public void translate(int deltaX, int deltaY) {
path.transform(AffineTransform.getTranslateInstance(deltaX, deltaY));
}
}

Moving ball inside rectangle program

I am creating a moving ball program that features a ball moving and bouncing off the walls of a rectangle with go and stop buttons at the bottom.
What I am having problems with is I want the ball to start off moving when the program is run and bouncing off the lines inside the rectangle which is my main problem. Below is my code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
//Does the drawing
class MyDrawing extends JPanel {
private int xpos;
private int ypos;
public void setXPos(final int x) {
this.xpos = x;
}
public void setYPos(final int y) {
this.ypos = y;
}
public int getXpos() {
return xpos;
}
public int getYpos() {
return ypos;
}
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
final Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.red);
final Ellipse2D.Double circle = new Ellipse2D.Double(xpos, ypos, 50, 50);
g2.draw(circle);
g2.fill(circle);
final Rectangle box1 = new Rectangle(10, 10, 380, 300);
g.setColor(Color.BLACK);
g2.draw(box1);
}
}
public class ControlledBall extends JFrame {
private final JButton flash = new JButton("Go");
private final JButton steady = new JButton("Stop");
private final JPanel panel = new JPanel(new GridBagLayout());
private final MyDrawing drawing = new MyDrawing();
private final Timer timer;
//direction
private int dx = 3;
private int dy = 2;
public ControlledBall() {
panel.add(flash);
panel.add(steady);
this.add(panel, BorderLayout.SOUTH);
this.add(drawing, BorderLayout.CENTER);
drawing.setXPos(300);
drawing.setYPos(150);
steady.addActionListener(new SteadyListener());
final MoveListener ml = new MoveListener();
flash.addActionListener(ml);
timer = new Timer(15, ml);
}
class MoveListener implements ActionListener {
#Override
public void actionPerformed(final ActionEvent event) {
if (!timer.isRunning()){
timer.start();
}
move();
}
}
class SteadyListener implements ActionListener {
#Override
public void actionPerformed(final ActionEvent event) {
if (timer.isRunning()){
timer.stop();
}
}
}
private void move() {
int x = drawing.getXpos();
int y = drawing.getYpos();
final int dia = 30;
if (x + dx < 0 || x + dia + dx > getWidth()) {
dx *= -1;
}
if (y + dy < 0 || y + dia + dy > getHeight()) {
dy *= -1;
}
x += dx;
y += dy;
drawing.setXPos(x);
drawing.setYPos(y);
repaint();
}
public static void main(final String[] args) {
final JFrame window = new ControlledBall();
window.setSize(400, 400);
window.setTitle("Controlled Ball");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
The problem is the boundaries you check against. If you want to check against the Rectangle you have to implement the size as variables and enter them in your "bounce"-check or you add it manually like (take the size of the rectangle from your code):
if (x + dx < 10 || x + dia + dx > 380) {
dx *= -1;
}
if (y + dy < 10 || y + dia + dy > 300) {
dy *= -1;
}
If you like to take the real distanz use an offset of the size of hallf of the ball and add it to this code. i think this is better than the speed-vector dxand dyonly.

Moving point along lines

I draw a shape, which looks like letter "Y". Then I draw a small point at the bottom of it.
Let's say the shape is 3 lines, like so:
I want to move this point along line 1, then line 2, then back along line 2, then line 3, and finally back to the start at the bottom of line 1.
It moves with speed specified by slider.
Here's my code so far:
public class yyyyy extends JFrame{
private Komponent komponent;
private Timer timer;
private int tick = 0;
private int speed = 4;
private int x1 = 225, y1 = 300, y2 = 225, x3 = 150, y3 = 150, x4 = 300;
private int x = x1, y = y1;
class Komponent extends JComponent{
/**
*
*/
private static final long serialVersionUID = -4028514932033769012L;
#Override
protected void paintComponent(Graphics arg0) {
if(tick< y1-y2){
x = x1;
y = y1-tick;
}
else if(tick>y1-y2 && tick < 2*(y1-y2)){
x = x1-tick + (y1-y2);
y = y2-tick + (y1-y2);
}
else if(tick>2*(y1-y2) && tick < 3*(y1-y2)){
x = x3 + tick - 2*(y1-y2);
y = y3 + tick - 2*(y1-y2);
}
else if(tick>3*(y1-y2)&& tick < 4*(y1-y2)){
x = x1 + tick - 3*(y1-y2);
y = y2 - tick + 3*(y1-y2);
}
else if(tick>4*(y1-y2)&& tick < 5*(y1-y2)){
x = x4 - tick + 4*(y1-y2);
y = y3 + tick - 4*(y1-y2);
}
else{
x = x1;
y = y2 + tick - 5*(y1-y2);
}
arg0.setColor(Color.BLUE);
arg0.drawLine(x1, y1, x1, y2);
arg0.drawLine(x1,y2,x3,y3);
arg0.drawLine(x1, y2, x4, y3);
arg0.setColor(Color.RED);
arg0.fillOval(x-5, y-5, 10, 10);
super.paintComponent(arg0);
}
}
public yyyyy (String string){
super(string);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBounds(100,100,550,550);
add(komponent=new Komponent());
JPanel panel = new JPanel();
add(panel, BorderLayout.SOUTH);
final JCheckBox cb = new JCheckBox("Animacja");
cb.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if(cb.isSelected()){
timer.start();
}
else{
timer.stop();
}
}
});
panel.add(cb);
timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tick+=speed;
if(tick > 6*(y1 -y2)){
tick -= 6*(y1-y2);
}
if(tick < 0){
tick = 6*(y2-y1);
}
komponent.repaint();
}
});
final JSlider speedSlider = new JSlider(-30,30,speed);
panel.add(speedSlider);
speedSlider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
speed = speedSlider.getValue();
komponent.repaint();
}
});
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new yyyyy("wat");
}
});
}
}
Now I have 2 problems:
1. Is the resetting of tick defined properly? I feel like it should go to 0 after being 2 * the sum of distances of all lines.
2. The part of the code I marked with comment. How can I check what the current x and y of the point should be? I tried doing that from line equation, but not much success (point was always just shooting outside of the window).
EDIT: Code updated.
Although the question was already answered in the comment (and although it was mainly a debugging hint, and although this is not really an answer...) I'd like to recommend you to generalize this.
You should probably to model each and every segment manually, with a fixed set of coordinates. Instead, you could create a general "path", that should be followed. The position on the path can be defined as a value between 0.0 and 1.0.
Then, the timing and interpolation are separated, and the timing itself can be handled separately. You can then even add nifty animation effects, for example, add some Math.sin somewhere and obtain interesting ease-in/ease-out effects.
However, here is an MCVE showing an example of how such a generic path follower could be implemented. It may changed from following an Y to following an X just by changing the creation of the PathFollower instance in the main method.
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PathFollowerTest
{
public static void main(String[] args)
{
final PathFollower pathFollower = createPathFollowerY();
//final PathFollower pathFollower = createPathFollowerX();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI(pathFollower);
}
});
}
private static PathFollower createPathFollowerY()
{
Point2D p0 = new Point2D.Double(225, 300);
Point2D p1 = new Point2D.Double(225, 225);
Point2D p2 = new Point2D.Double(150, 150);
Point2D p3 = new Point2D.Double(300, 150);
PathFollower pathFollower = new PathFollower();
pathFollower.addPoint(p0);
pathFollower.addPoint(p1);
pathFollower.addPoint(p2);
pathFollower.addPoint(p1);
pathFollower.addPoint(p3);
pathFollower.addPoint(p1);
pathFollower.addPoint(p0);
return pathFollower;
}
private static PathFollower createPathFollowerX()
{
Point2D p0 = new Point2D.Double(150, 300);
Point2D p1 = new Point2D.Double(225, 225);
Point2D p2 = new Point2D.Double(150, 150);
Point2D p3 = new Point2D.Double(300, 300);
Point2D p4 = new Point2D.Double(300, 150);
PathFollower pathFollower = new PathFollower();
pathFollower.addPoint(p0);
pathFollower.addPoint(p1);
pathFollower.addPoint(p2);
pathFollower.addPoint(p1);
pathFollower.addPoint(p4);
pathFollower.addPoint(p1);
pathFollower.addPoint(p3);
pathFollower.addPoint(p1);
pathFollower.addPoint(p0);
return pathFollower;
}
private static void createAndShowGUI(final PathFollower pathFollower)
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setBounds(100, 100, 550, 550);
f.getContentPane().setLayout(new BorderLayout());
PathFollowerPanel pathFollowerPanel =
new PathFollowerPanel(pathFollower);
f.getContentPane().add(pathFollowerPanel, BorderLayout.CENTER);
final PathFollowerController pathFollowerController =
new PathFollowerController(
pathFollower, pathFollowerPanel);
JPanel panel = new JPanel();
f.getContentPane().add(panel, BorderLayout.SOUTH);
final JCheckBox cb = new JCheckBox("Animacja");
cb.addChangeListener(new ChangeListener()
{
#Override
public void stateChanged(ChangeEvent e)
{
pathFollowerController.setRunning(cb.isSelected());
}
});
panel.add(cb);
final JSlider speedSlider = new JSlider(-30, 30, 0);
panel.add(speedSlider);
speedSlider.addChangeListener(new ChangeListener()
{
#Override
public void stateChanged(ChangeEvent e)
{
pathFollowerController.setSpeed(speedSlider.getValue());
}
});
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class PathFollowerController
{
private int speed = 0;
private PathFollower pathFollower;
private PathFollowerPanel pathFollowerPanel;
private final Timer timer = new Timer(50, new ActionListener()
{
private double alpha = 0;
#Override
public void actionPerformed(ActionEvent e)
{
alpha += speed / 500.0;
alpha %= 1.0;
while (alpha < -1.0)
{
alpha += 1.0;
}
pathFollower.setAlpha(alpha < 0 ? -alpha : alpha);
pathFollowerPanel.repaint();
}
});
PathFollowerController(PathFollower pathFollower,
PathFollowerPanel pathFollowerPanel)
{
this.pathFollower = pathFollower;
this.pathFollowerPanel = pathFollowerPanel;
}
void setRunning(boolean running)
{
if (running)
{
timer.start();
}
else
{
timer.stop();
}
}
public void setSpeed(int speed)
{
this.speed = speed;
}
}
class PathFollower
{
private final List<Point2D> points;
private Shape path;
private double pathLength = -1;
private double alpha = 0;
PathFollower()
{
points = new ArrayList<Point2D>();
}
void addPoint(Point2D p)
{
points.add(new Point2D.Double(p.getX(), p.getY()));
path = null;
pathLength = -1;
}
void setAlpha(double alpha)
{
this.alpha = alpha;
}
Point2D getCurrentPoint()
{
return computePoint(alpha);
}
Shape getPath()
{
if (path == null)
{
path = createPath();
}
return path;
}
private Shape createPath()
{
Path2D path = new Path2D.Double();
for (int i = 0; i < points.size(); i++)
{
Point2D p = points.get(i);
double x = p.getX();
double y = p.getY();
if (i == 0)
{
path.moveTo(x, y);
}
else
{
path.lineTo(x, y);
}
}
return path;
}
private double computePathLength()
{
double pathLength = 0;
for (int i = 0; i < points.size() - 1; i++)
{
Point2D p0 = points.get(i);
Point2D p1 = points.get(i + 1);
pathLength += p0.distance(p1);
}
return pathLength;
}
private Point2D computePoint(double alpha)
{
if (pathLength < 0)
{
pathLength = computePathLength();
}
double alphaPosition = alpha * pathLength;
double accumulatedLength = 0;
for (int i = 0; i < points.size() - 1; i++)
{
Point2D p0 = points.get(i);
Point2D p1 = points.get(i + 1);
double distance = p0.distance(p1);
double nextLength = accumulatedLength + distance;
if (nextLength >= alphaPosition)
{
double localAlpha =
(alphaPosition - accumulatedLength) / distance;
double x = p0.getX() + localAlpha * (p1.getX() - p0.getX());
double y = p0.getY() + localAlpha * (p1.getY() - p0.getY());
return new Point2D.Double(x, y);
}
accumulatedLength = nextLength;
}
Point2D p = points.get(points.size() - 1);
return new Point2D.Double(p.getX(), p.getY());
}
}
class PathFollowerPanel extends JPanel
{
private final PathFollower pathFollower;
PathFollowerPanel(PathFollower pathFollower)
{
this.pathFollower = pathFollower;
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D) gr;
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.BLUE);
g.setStroke(new BasicStroke(3.0f));
g.draw(pathFollower.getPath());
g.setColor(Color.RED);
Point2D p = pathFollower.getCurrentPoint();
double r = 5;
g.fill(new Ellipse2D.Double(
p.getX() - r, p.getY() - r, r + r, r + r));
}
}

How can I move a jlabel image around the screen?

I want to click on the screen and have the character move to that destination. Not instantly, but rather "walk" to the given coordinate. Currently I'm using JLabels and they're fine if I only use static images, but everytime I click somewhere on the screen the image shows up at that exact point. Could someone give me some tips?
edit: Should I override the paint class and draw some items that way?
Here's some code:
package mod;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.awt.KeyboardFocusManager;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Board2 extends JPanel {
private Thread animator;
int x, y;
double ix, iy;
double dx, dy;
final int frameCount = 8;
BufferedImage flower;
private int[][] fPos = {{232, 15},{400, 200},{335, 335}}; // flower coordinates
private static int bWIDTH = 800; // width of window
private static int bHEIGHT = 600;// height of window
private Font font;
private FontMetrics metrics;
ImageIcon grassI = new ImageIcon(this.getClass().getResource("grass.png"));
ImageIcon riverI = new ImageIcon(this.getClass().getResource("river.png"));
private Image grass = grassI.getImage();
private Image river = riverI.getImage();
private House house = new House();
private River river1 = new River();
//private Flower flower = new Flower();
private TitleScreenLayer ts = new TitleScreenLayer();
private Player girlP = new Player();
private static int px = 250;
private static int py = 250;
private boolean visTl = false;
private boolean plant = false;
ArrayList<Flower> flowers= new ArrayList<Flower>();
private long period;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private volatile boolean isPaused = false;
// New stuff for Board2 below
private JLayeredPane lpane;
private JLabel grassLabel;
private JLabel riverLabel;
private JLabel houseLabel;
private JLabel pear1Label;
private JLabel pear2Label;
private JLabel pear3Label;
private JLabel drivewayLabel;
private JLabel girlLabel;
private JProgressBar progressBar;
private JLabel toolLabel;
private JTextArea textBubble;
ImageIcon girlImage = new ImageIcon(girlP.getImage());
int mouseClicks = 0;
CountdownTimer cTimer;
private static String message;
public static String setMessage(String newMessage){
return message = newMessage;
}
private static ImageIcon playerTool = new ImageIcon("BradfordPear.png");
public ImageIcon getPlayerTool(){
return playerTool;
}
public static void setPlayerTool(String image){
playerTool = new ImageIcon(image);
}
public JTextArea getTextBubble(){
return textBubble;
}
public Player getPlayer(){
return girlP;
}
public static int getPlayerX(){
return px;
}
public static int getPlayerY(){
return py;
}
public JLayeredPane getLayeredPane(){
return lpane;
}
public Board2(){
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
//create the layered pane
lpane = new JLayeredPane();
lpane.setPreferredSize(new Dimension(800, 600));
//create the "background" image
ImageIcon image = new ImageIcon("grass.png");
grassLabel = new JLabel(image);
grassLabel.setBounds(0, 0, image.getIconWidth(), image.getIconHeight());
//create the house image
ImageIcon houseImage = new ImageIcon("house.png");
houseLabel = new JLabel(houseImage);
houseLabel.setBounds(-330, -150, image.getIconWidth(), image.getIconHeight());
//create the driveway image
ImageIcon drivewayImage = new ImageIcon("driveway.png");
drivewayLabel = new JLabel(drivewayImage);
drivewayLabel.setBounds(-335, 105, image.getIconWidth(), image.getIconHeight());
//create the river image
ImageIcon riverImage = new ImageIcon("river.png");
riverLabel = new JLabel(riverImage);
riverLabel.setBounds(360, 0, image.getIconWidth(), image.getIconHeight());
//create pear1 image
ImageIcon pear1Image = new ImageIcon("BradfordPear.png");
pear1Label = new JLabel(pear1Image);
pear1Label.setBounds(100, 100, image.getIconWidth(), image.getIconHeight());
//create pear2 image
ImageIcon pear2Image = new ImageIcon("BradfordPear.png");
pear2Label = new JLabel(pear2Image);
pear2Label.setBounds(50, -100, image.getIconWidth(), image.getIconHeight());
//create pear3 image
ImageIcon pear3Image = new ImageIcon("BradfordPear.png");
pear3Label = new JLabel(pear3Image);
pear3Label.setBounds(-100, -50, image.getIconWidth(), image.getIconHeight());
//create initial Player(girl) image
//ImageIcon girlImage = new ImageIcon(girlP.getImage());
girlLabel = new JLabel(girlImage);
girlLabel.setBounds((int)girlP.getPositionX(), (int)girlP.getPositionY(), image.getIconWidth(), image.getIconHeight());
//create progress bar
progressBar = new JProgressBar(JProgressBar.VERTICAL, 0, 10);
progressBar.setValue(0);
progressBar.setBounds(720, 50, 100, 500);
//create timer
JTextField timerField = new JTextField();
cTimer = new CountdownTimer(timerField);
timerField.setBounds(400, 0, 50, 50);
//create toolbox
Toolbox toolbox = new Toolbox();
toolbox.setBounds(550, 0, 250, 50);
//create the text bubble
textBubble = new JTextArea("IDPC is the best coding group ever");
textBubble.setLineWrap(true);
//textBubble.setBounds(200, 200, 100, 100);
//add the background & various images
lpane.add(grassLabel, new Integer(1));
lpane.add(houseLabel, new Integer(2));
lpane.add(riverLabel, new Integer(2));
lpane.add(drivewayLabel, new Integer(2));
lpane.add(pear1Label, new Integer(2));
lpane.add(pear2Label, new Integer(2));
lpane.add(pear3Label, new Integer(2));
lpane.add(progressBar, new Integer(3));
lpane.add(girlLabel, new Integer(3));
lpane.add(timerField, new Integer(2));
lpane.add(toolbox, new Integer(3));
add(lpane);
cTimer.start();
// listen for action events
new ActionListener() {
public void actionPerformed(ActionEvent e) {
girlP.move();
//girlLabel.setLocation(px, py);
}
};
// listen for mouse presses
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
//lpane.remove(textBubble);
mouseClicks+= 1;
testPress(e.getX(), e.getY());
//textBubble.setBounds(e.getX(), e.getY(), 40, 40);
updateProgressBar();
}
});
//listen for player action
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 2){
ImageIcon flowerImage = playerTool;
JLabel flowerPanel = new JLabel(flowerImage);
flowerPanel.setBounds((px -((int)girlP.getPositionX() / 2)),
(py - ((int)girlP.getPositionY() / 2)),
flowerImage.getIconWidth(),
flowerImage.getIconHeight());
lpane.add(flowerPanel, new Integer(3));
textBubble.setBounds(e.getX(), e.getY(), 200, 40);
textBubble.replaceSelection(message);
lpane.add(textBubble, new Integer(3));
//lpane.remove(textBubble);
}
}
});
x = 15;
y = 150;
ix = 0;
iy = 0;
dx = .05;
dy = .05;
girlP.setDestination(px, py);
}
public void testPress(int x, int y){
px = x;
py = y;
if (px < (ix + house.getImage().getWidth(this))
&& (py < (iy + house.getImage().getHeight(this)))) {
px = px + (house.getImage().getWidth(this)/3);
py = py + (house.getImage().getHeight(this)/3);
}
if (px > (bWIDTH - river1.getImage().getWidth(this))) {
px = px - 80 - (river1.getImage().getWidth(this)/2);
}
girlLabel.setBounds((px -((int)(girlP.getPositionX()*2.5))),
(py - ((int)(girlP.getPositionY()*2.5))),
girlImage.getIconWidth(), girlImage.getIconHeight());
girlP.setDestination((px-(girlP.getImage().getWidth(this)/2)),
(py-(girlP.getImage().getHeight(this)/2)));
girlP.pinned(x, y);
}
public void updateProgressBar(){
if(progressBar.getValue() == 3){
//progressBar.setBackground(Color.red);
//UIManager.put("progressBar.foreground", Color.RED);
UIDefaults defaults = new UIDefaults();
defaults.put("progressBar[Enabled].foregroundPainter", Color.RED);
progressBar.putClientProperty("Nimbus.Overrides.InheritDefaults", Boolean.TRUE);
progressBar.putClientProperty("Nimbus.Overrides", defaults);
}
progressBar.setValue(mouseClicks);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new TitleScreenLayer();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Here's the player class:
package mod;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.ImageObserver;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
public class Player {
int tile;
double positionX;
double positionY;
int destinationX;//Used when moving from place to place
int destinationY;
Tool currentTool;
int direction; //Position the image is facing
double dx;
double dy;
int [] pin = new int[10];
private String girl = "girl.png";
ImageIcon ii = new ImageIcon(this.getClass().getResource(girl)); // load girl image
private Image image = ii.getImage();
private boolean visible = true;
public boolean plant = false;
Image playerImage;
public double getPositionX() {
return positionX;
}
public void setPositionX(double positionX) {
this.positionX = positionX;
}
public double getPositionY() {
return positionY;
}
public void setPositionY(double positionY) {
this.positionY = positionY;
}
public Player(){
positionX=30;
positionY=20;
dx = 0.2;
dy = 0.2;
destinationX=(int)positionX;
destinationY=(int)positionY;
//this.playerImage=playerImage;
}
public void doAction() {
//currentTool.getNum();
plant = true;
}
public void pinned(int x, int y) {
if (plant == true) {
pin[0] = x;
pin[1] = y;
}
//plant = false;
}
public void plant(Graphics g, ImageObserver io) {
int x = pin[0];
int y = pin[1];
if (plant == true) {
// g.drawImage(flower.getImage(), x, y, io);
}
}
public void ActionPerformed(ActionEvent e) {
positionX += dx;
positionY += dy;
}
public boolean isVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public Image getImage() {
return image;
}
public void move(){
//MOVE LEFT AND RIGHT
if(destinationX<positionX){
positionX-=dx;
}
if(destinationX>positionX){
positionX+=dx;
}
//MOVE UP AND DOWN
if(destinationY<positionY){
positionY-=dy;
}
if(destinationY>positionY){
positionY+=dy;
}
}
public double setDx(double speed) {
dx = speed;
return dx;
}
public double setDy(double speed) {
dy = speed;
return dy;
}
public void TileIn(int px, int py)
{
px=destinationX;
py=destinationY;
int tileX=1;
int tileY = 1;
int bWIDTH=800;
int bHEIGHT=600;
if(px >= 0 && px <= 800*.1)
{
tileX=2;
}
else if(px> bWIDTH*.1 && px <= bWIDTH*.2)
{
tileX=3;
}
else if(px > bWIDTH*.2 && px <= bWIDTH*.3)
{
tileX=4;
}
else if(px > bWIDTH*.3 && px <= bWIDTH*.4)
{
tileX=5;
}
else if(px > bWIDTH*.4 && px <= bWIDTH*.5)
{
tileX=6;
}
else if(px > bWIDTH*.5 && px <= bWIDTH*.6)
{
tileX=7;
}
else if(px > bWIDTH*.6 && px <= bWIDTH*.7)
{
tileX=8;
}
else if(px > bWIDTH*.7 && px <= bWIDTH*.8)
{
tileX=9;
}
else if(px > bWIDTH*.8 && px <= bWIDTH*.9)
{
tileX=10;
}
else if(px > bWIDTH*.9 && px <= bWIDTH)
{
tileX=11;
}
if(py >= 0 && py <= bHEIGHT*.1)
{
tileY=2;
}
else if(py> bHEIGHT*.1 && py <= bHEIGHT*.2)
{
tileY=3;
}
else if(py > bHEIGHT*.2 && py <= bHEIGHT*.3)
{
tileY=4;
}
else if(py > bHEIGHT*.3 && py <= bHEIGHT*.4)
{
tileY=5;
}
else if(py > bHEIGHT*.4 && py <= bHEIGHT*.5)
{
tileY=6;
}
else if(py > bHEIGHT*.5 && py <= bHEIGHT*.6)
{
tileY=7;
}
else if(py > bHEIGHT*.6 && py <= bHEIGHT*.7)
{
tileY=8;
}
else if(py > bHEIGHT*.7 && py <= bHEIGHT*.8)
{
tileY=9;
}
else if(py > bHEIGHT*.8 && py <= bHEIGHT*.9)
{
tileY=10;
}
else if(py > bHEIGHT*.9 && py <= bHEIGHT)
{
tileY=11;
}
System.out.println("Grid X: " + tileX + " Grid Y: " + tileY);
}
public void setDestination(int x, int y){
destinationX=x;
destinationY=y;
System.out.println(x + "," + y);
TileIn(x,y);
}
// public void tileIn(int a)
// {
//
// b=destinationY;
// return TileIn(x,y)
// }
public void draw(Graphics g,ImageObserver io){
g.drawImage(image, (int)positionX,(int) positionY,io);
}
}
Here is the main class:
package mod;
import java.awt.Container;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
public class Skeleton2 extends JFrame /*implements WindowListener*/{
private static int DEFAULT_FPS = 80;
private Board2 bd;
public Skeleton2(long period) {
super("Skeleton");
makeGUI(period);
//addWindowListener(this);
pack();
setResizable(false);
setVisible(true);
}
public void makeGUI(long period) {
Container c = getContentPane();
bd = new Board2();
c.add(bd, "Center");
} // end of makeGUI()
//==================================================================================
// Window Events
//==================================================================================
/*
public void windowActivated(WindowEvent e) {
bd.resumeGame();
}
public void windowDeactivated(WindowEvent e) {
bd.pauseGame();
}
public void windowDeiconified(WindowEvent e) {
bd.resumeGame();
}
public void windowIconified(WindowEvent e) {
bd.pauseGame();
}
public void windowClosing(WindowEvent e) {
bd.stopGame();
}
*/
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
//==================================================================================
public static void main(String[] args) {
int fps = DEFAULT_FPS;
long period = (long) 1000.0/fps;
new Skeleton2(period);
System.out.println("Period: " + period);
}
}
Not instantly, but rather "walk" to the given coordinate.
Then you need to use a Swing Timer. The Timer is used to schedule the animation. So you would need to calculate a path between the two points. Every time the Timer fires you would move the label a few pixels until it reaches it's destination.
There is no need to do custom painting for this. A JLabel will work fine. The hard part is calculating the path you want the character to take. Also make sure you use a null layout on the panel you add the JLabel to, which means you will also need to set the size of the label equal to the preferred size of the label.
You should rather use g.drawImage in your component paintComponent method.

Categories