I am trying to create a program that record mouse clicks, draw lines between those points and after some calculations display some circles through a button call. My problem is that I can display the lines or the circles, but not both.
I know there is something overlapping something else, but I am very new to Java and I don't know how to fix it. Here is the code:
package fempack;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
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.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.lang.Math;
public class MainFem extends JPanel {
final DrawPoints Npoints = new DrawPoints();
final DrawLines Nline = new DrawLines();
private static final long serialVersionUID = 1L;
private MouseHandler mouseHandler = new MouseHandler();
private Point p1 = new Point(100, 100);
public int Xpoint[][] = new int[500][30];
public int Ypoint[][] = new int[500][30];
private double Xmpoint[][] = new double[500][1000]; // [i γραμμή][συντεταγμένη Χ]
private double Ympoint[][] = new double[500][1000];
private double Vec[][][] = new double[500][2][500]; // [i γραμμή][0,1][0α 1β]
private double dist[] = new double[10000];
private boolean drawing;
private int c1;
private int c2;
public MainFem() {
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
// -------------- Draw by clicking -----------------------
private class MouseHandler extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e)){
drawing=false;
c2++;
}
if(SwingUtilities.isLeftMouseButton(e)){
p1 = e.getPoint();
Xpoint[c1][c2] = p1.x;
Ypoint[c1][c2] = p1.y;
if (c1 > 3) {
for (int j = 0; j<c2+1; j++){
for (int i = 0; i<c1; i++){
if ((Math.abs(Xpoint[i][j]-Xpoint[c1][c2]) < 10) && (Math.abs(Ypoint[i][j]-Ypoint[c1][c2]) < 10)) {
Xpoint[c1][c2] = Xpoint[i][j];
Ypoint[c1][c2] = Ypoint[i][j];
System.out.println(Xpoint[i][j]);
}
}
}
}
if (drawing == true){
Nline.addLine(Xpoint[c1][c2], Ypoint[c1][c2], Xpoint[c1-1][c2], Ypoint[c1-1][c2]);
}
c1++;
drawing = true;
}
}
}
// ---------------- Create Mesh Points --------------------------
public void createmesh() {
int mdi = 0;
for (int j = 0; j<=c2; j++){
for (int i = 0; i<c1-1; i++){
// Υπολογισμός a και b συνιστωσών της εξίσωσης της γραμμής
Vec[i][0][mdi] = (Ypoint[i+1][j] - Ypoint[i][j])/(Xpoint[i+1][j] - Xpoint[i][j]);
Vec[i][1][mdi] = Ypoint[i][j] - Xpoint[i][j]*Vec[i][1][mdi];
// Υπολογισμός μέτρου διανύσματος
dist[mdi] = Math.sqrt(Math.pow(Xpoint[i][j] - Xpoint[i+1][j], 2) + Math.pow(Ypoint[i][j] - Ypoint[i+1][j], 2) );
// Υπολογισμός ενδιάμεσον σημείων
int nkom = 3;
double xa = Xpoint[i][j];
double ya = Ypoint[i][j];
for (int ii = 0; ii <nkom; ii++) {
double a = Vec[i][0][mdi];
double b = Vec[i][1][mdi];
Xmpoint[i][ii] = (-((2*a)*(b - ya) - 2*xa) + Math.sqrt(Math.abs(Math.pow(((2*a)*(b - ya) - 2*xa), 2) - 4*(1 + a*a)*(xa*xa + Math.pow((b - ya),2) - Math.pow(dist[mdi]/nkom,2)))))/(2 + 2*a*a);
Ympoint[i][ii] = a*Xmpoint[i][ii] + b;
double xm11 = Xmpoint[i][ii];
double ym11 = Ympoint[i][ii];
int xm1 = (int) xm11;
int ym1 = (int) ym11;
Npoints.addPoint(xm1, ym1);
System.out.println("i:" + ym11 + "...ii:" + ym1 );
xa = Xmpoint[i][ii];
ya = Ympoint[i][ii];
}
mdi++;
}
}
}
//------------------------- Display ---------------------------
private void display() {
JFrame f = new JFrame("LinePanel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(500, 600));
f.setLocationRelativeTo(null);
f.add(Npoints);
f.add(Nline);
JPanel buttonsPanel = new JPanel();
//-----------------Complete---------------
JButton dcomp = new JButton("Complete");
buttonsPanel.add(dcomp);
dcomp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
createmesh();
}
});
//------------------Clean-------------------
JButton clearButton = new JButton("Clear");
buttonsPanel.setBorder(BorderFactory.createLineBorder(Color.black));
buttonsPanel.setPreferredSize(new Dimension(500, 100));
f.add(buttonsPanel, BorderLayout.SOUTH);
buttonsPanel.add(clearButton);
clearButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Nline.clearLines();
}
});
f.pack();
f.setVisible(true);
f.add(this);
}
//---------------------------------------------------------
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MainFem().display();
}
});
}
}
Class to draw lines:
package fempack;
import java.awt.Graphics;
import java.util.LinkedList;
import javax.swing.JPanel;
public class DrawLines extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
public DrawLines() {
}
private static class Line{
final int x1;
final int y1;
final int x2;
final int y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
private final LinkedList<Line> lines = new LinkedList<Line>();
public void addLine(int x1, int x2, int x3, int x4) {
lines.add(new Line(x1,x2,x3,x4));
repaint();
}
public void clearLines() {
lines.clear();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Line line : lines) {
// System.out.println(line);
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
}
And class to draw Circles:
package fempack;
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.LinkedList;
public class DrawPoints extends JPanel {
private static final long serialVersionUID = 1L;
public DrawPoints() {
}
private static class Point {
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
private final LinkedList<Point> points = new LinkedList<Point>();
public void addPoint(int x, int y) {
points.add(new Point(x,y));
// System.out.println(x);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Point point : points) {
// System.out.println(point);
g.drawOval(point.x, point.y, 5, 5);
}
}
}
Here is my solution to draw the points added in the createmesh(). I did not modify any handling of the points you got from the mouse position. I just tried to refactor and clean up your code.
Now DrawLine and DrawPoint are no more JPanel's they just hold the data you give them and draw to the Graphics-Object you pass to them in public void draw(Graphics g) method, which is called on paint in the DrawPanel-Class. DrawPanel inherits from JPanel and overrides void PaintComponent(Graphics g); to realize this (Thanks to MadProgrammer ;). Also DrawPanel handels the MouseEvents to put the mouse-positions into DrawLines- and DrawPoints-objects.
MainWindow inherits from JFrame and is the MainWindow. It creates all GUI-elements and calls the DrawPanel if necessary.
MainWindow:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
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;
public class MainWindow extends JFrame {
private static final long serialVersionUID = 6755417048009930291L;
// begin gui components
JButton clearButton = null;
JButton dcomp = null;
JPanel buttonsPanel = null;
DrawPanel drawPanel = null;
// end gui components
public MainWindow(){
// Add ButtonPanel
add(getDrawPanel(), BorderLayout.CENTER);
add(getButtonPanel(), BorderLayout.SOUTH);
// Add Buttons
getButtonPanel().add(getDcomp());
getButtonPanel().add(getClearButton());
addMouseListener(getDrawPanel());
}
// begin getters and setters for gui components
private DrawPanel getDrawPanel(){
if(drawPanel == null){
drawPanel = new DrawPanel();
drawPanel.setVisible(true);
}
return drawPanel;
}
private JPanel getButtonPanel() {
if(buttonsPanel == null){
buttonsPanel = new JPanel();
buttonsPanel.setBorder(BorderFactory.createLineBorder(Color.black));
buttonsPanel.setPreferredSize(new Dimension(500, 100));
}
return buttonsPanel;
}
private JButton getClearButton() {
if(clearButton == null){
clearButton = new JButton("Clear");
clearButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getDrawPanel().clearLines();
}
});
}
return clearButton;
}
private JButton getDcomp() {
if(dcomp == null){
dcomp = new JButton("Complete");
dcomp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getDrawPanel().createmesh();
getDrawPanel().repaint();
}
});
}
return dcomp;
}
// end begin getters and setters for gui components
//as always program entry-point
public static void main(String[] args) {
MainWindow wnd = new MainWindow();
wnd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
wnd.setPreferredSize(new Dimension(500, 600));
wnd.setLocationRelativeTo(null);
wnd.pack();
wnd.setVisible(true);
}
}
DrawPanel:
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DrawPanel extends JPanel implements MouseListener {
private static final long serialVersionUID = -7726303639184194659L;
// begin members
private DrawLines dlines;
private DrawPoints dpoints;
// dont know what these members do
private Point p1 = new Point(100, 100);
public int Xpoint[][] = new int[500][30];
public int Ypoint[][] = new int[500][30];
private double Xmpoint[][] = new double[500][1000]; // [i
// γραμμή][συντεταγμένη
// Χ]
private double Ympoint[][] = new double[500][1000];
private double Vec[][][] = new double[500][2][500]; // [i γραμμή][0,1][0α
// 1β]
private double dist[] = new double[10000];
private boolean drawing;
private int c1;
private int c2;
// end members
public DrawPanel() {
dlines = new DrawLines();
dpoints = new DrawPoints();
addMouseListener(this);
}
// begin class logic
public void clearLines(){
dlines.clearLines();
repaint();
}
// dont know what this does
public void createmesh() {
int mdi = 0;
for (int j = 0; j <= c2; j++) {
for (int i = 0; i < c1 - 1; i++) {
// Υπολογισμός a και b συνιστωσών της εξίσωσης της γραμμής
Vec[i][0][mdi] = (Ypoint[i + 1][j] - Ypoint[i][j])
/ (Xpoint[i + 1][j] - Xpoint[i][j]);
Vec[i][1][mdi] = Ypoint[i][j] - Xpoint[i][j] * Vec[i][1][mdi];
// Υπολογισμός μέτρου διανύσματος
dist[mdi] = Math.sqrt(Math.pow(Xpoint[i][j] - Xpoint[i + 1][j],
2) + Math.pow(Ypoint[i][j] - Ypoint[i + 1][j], 2));
// Υπολογισμός ενδιάμεσον σημείων
int nkom = 3;
double xa = Xpoint[i][j];
double ya = Ypoint[i][j];
for (int ii = 0; ii < nkom; ii++) {
double a = Vec[i][0][mdi];
double b = Vec[i][1][mdi];
Xmpoint[i][ii] = (-((2 * a) * (b - ya) - 2 * xa) + Math
.sqrt(Math.abs(Math.pow(
((2 * a) * (b - ya) - 2 * xa), 2)
- 4
* (1 + a * a)
* (xa * xa + Math.pow((b - ya), 2) - Math
.pow(dist[mdi] / nkom, 2)))))
/ (2 + 2 * a * a);
Ympoint[i][ii] = a * Xmpoint[i][ii] + b;
double xm11 = Xmpoint[i][ii];
double ym11 = Ympoint[i][ii];
int xm1 = (int) xm11;
int ym1 = (int) ym11;
dpoints.addPoint(xm1, ym1);
System.out.println("i:" + ym11 + "...ii:" + ym1);
xa = Xmpoint[i][ii];
ya = Ympoint[i][ii];
}
mdi++;
}
}
}
// end class logic
// begin MouseListener implementation
#Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
drawing = false;
c2++;
}
if (SwingUtilities.isLeftMouseButton(e)) {
p1 = e.getPoint();
Xpoint[c1][c2] = p1.x;
Ypoint[c1][c2] = p1.y;
if (c1 > 3) {
for (int j = 0; j < c2 + 1; j++) {
for (int i = 0; i < c1; i++) {
if ((Math.abs(Xpoint[i][j] - Xpoint[c1][c2]) < 10)
&& (Math.abs(Ypoint[i][j] - Ypoint[c1][c2]) < 10)) {
Xpoint[c1][c2] = Xpoint[i][j];
Ypoint[c1][c2] = Ypoint[i][j];
System.out.println(Xpoint[i][j]);
}
}
}
}
if (drawing == true) {
dlines.addLine(Xpoint[c1][c2], Ypoint[c1][c2],
Xpoint[c1 - 1][c2], Ypoint[c1 - 1][c2]);
}
c1++;
drawing = true;
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
// end MouseListener implementation
// beging PAINTING
#Override
protected void paintComponent(Graphics g) {
System.out.println("paintComponent");
super.paintComponent(g);
dlines.draw(g);
dpoints.draw(g);
}
// end PAINTING
}
DrawPoints:
import java.awt.Graphics;
import java.util.LinkedList;
public class DrawPoints {
public DrawPoints() {
}
private static class Point {
final int x;
final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
private final LinkedList<Point> points = new LinkedList<Point>();
public void addPoint(int x, int y) {
points.add(new Point(x, y));
}
public void draw(Graphics g){
for (Point point : points) {
g.drawOval(point.x, point.y, 5, 5);
}
}
}
DrawLines:
import java.awt.Graphics;
import java.util.LinkedList;
public class DrawLines{
public DrawLines() {
}
private static class Line {
final int x1;
final int y1;
final int x2;
final int y2;
public Line(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
private final LinkedList<Line> lines = new LinkedList<Line>();
public void addLine(int x1, int x2, int x3, int x4) {
lines.add(new Line(x1, x2, x3, x4));
}
public void clearLines() {
lines.clear();
}
public void draw(Graphics g){
for (Line line : lines) {
g.drawLine(line.x1, line.y1, line.x2, line.y2);
}
}
}
I think its a good idea to handle things like this. You want to paint on a Panel or something so pass it to the object which hold your data and let them draw to their common canvas like I did with the void draw(Graphics g) method in DrawPoints- and DrawLines-class.
I hope this will help you.
Fell free to ask if something is unclear.
Related
newbie programmer here.
I'm making a program that renders user-inputted equations in a Cartesian coordinate system. At the moment I'm having some issues with letting the user move the view around freely in the coordinate. Currently with mouseDragged the user can drag the view around a bit, but once the user releases the mouse and tries to move the view again the origin snaps back to the current position of the mouse cursor. What is the best way to let the user move around freely? Thanks in advance!
Here's the code for the drawing area.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JPanel;
public class DrawingArea extends JPanel implements MouseMotionListener {
private final int x_panel = 350; // width of the panel
private final int y_panel = 400; // height of the panel
private int div_x; // width of one square
private int div_y; // height of one square
private int real_y;
private int real_x;
private Point origin; // the origin of the coordinate
private Point temp; // temporary point
private static int y = 0;
private static int x = 0;
DrawingArea() {
setBackground(Color.WHITE);
real_x = x_panel;
real_y = y_panel;
setDivisionDefault();
setOrigin(new Point((real_x / 2), (real_y / 2)));
setSize(x_panel, y_panel);
addMouseMotionListener(this);
}
DrawingArea(Point origin, Point destination) {
this.origin = origin;
this.destination = destination;
panel = new JPanel();
panel.setSize(destination.x, destination.y);
panel.setLocation(origin);
this.panel.setBackground(Color.red);
panel.setLayout(null);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D line = (Graphics2D) g;
temp = new Point(origin.x, origin.y);
line.setColor(Color.red);
drawHelpLines(line);
line.setColor(Color.blue);
drawOrigin(line);
line.setColor(Color.green);
for (int i = 0; i < 100; i++) { // This is a test line
//temp = this.suora();
temp.x++;
temp.y++;
line.drawLine(temp.x, temp.y, temp.x, temp.y);
}
}
public void setOrigin(Point p) {
origin = p;
}
public void drawOrigin(Graphics2D line) {
line.drawLine(origin.x, 0, origin.x, y_panel);
line.drawLine(0, origin.y, x_panel, origin.y);
}
public void drawHelpLines(Graphics2D line) {
int xhelp= origin.x;
int yhelp= origin.y;
for (int i = 0; i < 20; i++) {
xhelp+= div_x;
line.drawLine(xhelp, 0, xhelp, y_panel);
}
xhelp= origin.x;
for (int i = 0; i < 20; i++) {
xhelp-= div_x;
line.drawLine(xhelp, 0, xhelp, y_panel);
}
for (int i = 0; i < 20; i++) {
yhelp-= div_y;
line.drawLine(0, yhelp,x_panel, yhelp);
}
yhelp= origin.y;
for (int i = 0; i < 20; i++) {
yhelp+= div_y;
line.drawLine(0, yhelp, x_panel, yhelp);
}
}
public void setDivisionDefault() {
div_x = 20;
div_y = 20;
}
#Override
public void mouseDragged(MouseEvent e) {
//Point temp_point = new Point(mouse_x,mouse_y);
Point coords = new Point(e.getX(), e.getY());
setOrigin(coords);
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
Based on this example, the following program allows the user to drag the axes' intersection to an arbitrary point, origin, which starts at the center of the panel.
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/15576413/230513
* #see https://stackoverflow.com/a/5312702/230513
*/
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final int W = 640;
private static final int H = 480;
private Point origin = new Point(W / 2, H / 2);
private Point mousePt;
public MouseDragTest() {
this.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
origin.setLocation(origin.x + dx, origin.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, origin.y, getWidth(), origin.y);
g.drawLine(origin.x, 0, origin.x, getHeight());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
I'm trying to make Boy1 move but in the second class I'm getting redlines under setX. Anyone know what's wrong?
First Class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class MyGame extends JPanel implements ActionListener, KeyListener {
Timer t = new Timer(5, this);
int x = 0, y = 0, velx =0, vely =0;
public MyGame() {
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(x,y,50,30);
}
public void actionPerformed(ActionEvent e) {
if(x < 0)
{
velx=0;
x = 0;
}
if(x > 530)
{
velx=0;
x = 530;
}
if(y < 0)
{
vely=0;
y = 0;
}
if(y > 330)
{
vely=0;
y = 330;
}
x += velx;
y += vely;
repaint();
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_DOWN){
vely = 1;
velx = 0;
}
if (code == KeyEvent.VK_UP){
vely = -1;
velx = 0;
}
if (code == KeyEvent.VK_LEFT){
vely = 0;
velx = -1;
}
if (code == KeyEvent.VK_RIGHT){
vely = 0;
velx = 1;
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {
velx=0;
vely=0;
}
public static void main (String arge[]){
JFrame f = new JFrame();
MyGame s = new MyGame();
f.add(s);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600,400);
f.setVisible(true);
}
}
Problem is with this last class. Perhaps it needs to be KeyAdapter? But I tried that and seems like that totally doesn't work.
The compiler is flagging you for a reason -- you're trying to call methods on a variable as if it were a variable that the class contains when it isn't -- it's held by a different class. And this isn't Kosher in Java.
What you should do is give the class that holds the variable public methods that outside classes can call and that will allow outside classes to be able to move the label. Then give your control object (the listener) an instance of the class that has these methods.
As an aside, you're usually better off using Key Bindings and not using a KeyListener.
I can give you an example of code that uses Key Bindings to move a JLabel around a JPanel:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.EnumMap;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class AnimateExample extends JPanel {
public static final String DUKE_IMG_PATH = // https://duke.kenai.com/iconSized/duke.gif
"https://duke.kenai.com/iconSized/duke4.gif";
private static final int PREF_W = 800;
private static final int PREF_H = 800;
private static final int TIMER_DELAY = 20;
private static final String KEY_DOWN = "key down";
private static final String KEY_RELEASE = "key release";
public static final int TRANSLATE_SCALE = 3;
private static final String BACKGROUND_STRING = "Use Arrow Keys to Move Image";
private static final Font BG_STRING_FONT = new Font(Font.SANS_SERIF,
Font.BOLD, 32);
private EnumMap<Direction, Boolean> dirMap =
new EnumMap<AnimateExample.Direction, Boolean>(Direction.class);
private BufferedImage image = null;
private int imgX = 0;
private int imgY = 0;
private int bgStringX;
private int bgStringY;
public AnimateExample() {
for (Direction dir : Direction.values()) {
dirMap.put(dir, Boolean.FALSE);
}
try {
URL imgUrl = new URL(DUKE_IMG_PATH);
image = ImageIO.read(imgUrl);
Icon icon = new ImageIcon(image);
JOptionPane.showMessageDialog(null, icon);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
new Timer(TIMER_DELAY, new TimerListener()).start();
// here we set up our key bindings
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
for (final Direction dir : Direction.values()) {
// for the key down key stroke
KeyStroke keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0,
false);
inputMap.put(keyStroke, dir.name() + KEY_DOWN);
actionMap.put(dir.name() + KEY_DOWN, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
dirMap.put(dir, true);
}
});
// for the key release key stroke
keyStroke = KeyStroke.getKeyStroke(dir.getKeyCode(), 0, true);
inputMap.put(keyStroke, dir.name() + KEY_RELEASE);
actionMap.put(dir.name() + KEY_RELEASE, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent arg0) {
dirMap.put(dir, false);
}
});
}
FontMetrics fontMetrics = getFontMetrics(BG_STRING_FONT);
int w = fontMetrics.stringWidth(BACKGROUND_STRING);
int h = fontMetrics.getHeight();
bgStringX = (PREF_W - w) / 2;
bgStringY = (PREF_H - h) / 2;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g.setFont(BG_STRING_FONT);
g.setColor(Color.LIGHT_GRAY);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.drawString(BACKGROUND_STRING, bgStringX, bgStringY);
if (image != null) {
g.drawImage(image, imgX, imgY, this);
}
}
private class TimerListener implements ActionListener {
public void actionPerformed(java.awt.event.ActionEvent e) {
for (Direction dir : Direction.values()) {
if (dirMap.get(dir)) {
imgX += dir.getX() * TRANSLATE_SCALE;
imgY += dir.getY() * TRANSLATE_SCALE;
}
}
repaint();
};
}
enum Direction {
Up(KeyEvent.VK_UP, 0, -1), Down(KeyEvent.VK_DOWN, 0, 1), Left(
KeyEvent.VK_LEFT, -1, 0), Right(KeyEvent.VK_RIGHT, 1, 0);
private int keyCode;
private int x;
private int y;
private Direction(int keyCode, int x, int y) {
this.keyCode = keyCode;
this.x = x;
this.y = y;
}
public int getKeyCode() {
return keyCode;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
private static void createAndShowGui() {
AnimateExample mainPanel = new AnimateExample();
JFrame frame = new JFrame("Animate Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have a window that dynamically updates the buffered image set on a JPanel using javax.swing.Timer
Everything works as expected but every time I invoke the dynamic update there seems to be another buffered image displayed below the currently updating one.
The image of the window before and after clicking the train button (which triggers the dynamic update) is given below.
Since the image below the dynamically updating image looks like the initial screen. I rechecked the following
Whether I'm adding two dynamic lattice objects to the same panel
Multiple calls of repaint()
Unwanted initialization of the dynamic lattice
I could not find any of these in my code. I cannot post the code since it is huge and whenever I'm creating a minimal set to reproduce the same behavior it is not there. So I'm sure I'm missing something or doing something on my project code which triggers this behavior. Any suggestions on how to debug this or why it is doing something like this?
Thank you
EDIT
SSCCE is give below. If executing, click the load button followed by the train button to get the error.
(MapScreen.java - Main Class)
package test;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import java.awt.Font;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import test.DisplayLattice;
import test.SelfOrganizingMap;
public class MapScreen extends JFrame {
private double NUM_ITERATIONS = 0.0;
private double ETA = 0.0;
private double SPREAD_FACTOR = 0.0;
private double RADIUS = 0.0;
private int WIDTH = 0;
private int HEIGHT = 0;
private SelfOrganizingMap SOM = null;
private Timer REFRESH_TIMER = null;
private JPanel pnlMap;
private JButton btnLoadParameters;
private JButton btnTrain;
private DisplayLattice displayScreen;
public MapScreen(double iterations, double learningRate, double spreadFactor, double radius, int option, int width, int height, int mapOption) {
NUM_ITERATIONS = iterations;
ETA = learningRate;
SPREAD_FACTOR = spreadFactor;
RADIUS = radius;
WIDTH = width;
HEIGHT = height;
setType(Type.UTILITY);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Map");
setSize(650, 800);
setLocation(150,150);
getContentPane().setLayout(null);
displayScreen = new DisplayLattice();
pnlMap = displayScreen;
pnlMap.setBounds(6, 130, 600, 600);
getContentPane().add(pnlMap);
btnLoadParameters = new JButton("Load Parameters");
btnLoadParameters.setFont(new Font("Tahoma", Font.PLAIN, 11));
btnLoadParameters.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0)
{
SOM = new SelfOrganizingMap(10000,0,0,13,displayScreen);
}
});
btnLoadParameters.setBounds(192, 46, 126, 23);
getContentPane().add(btnLoadParameters);
btnTrain = new JButton("Train");
btnTrain.setFont(new Font("Tahoma", Font.PLAIN, 11));
btnTrain.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
initialObjectSetUp();
}
});
btnTrain.setBounds(192, 72, 62, 23);
getContentPane().add(btnTrain);
}
private void initialObjectSetUp()
{
SOM.initTrainSOM(null, 100, 0.25);
REFRESH_TIMER = new Timer(100, SOM);
REFRESH_TIMER.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
MapScreen frame = new MapScreen(100,0.25,0.0,0.0,1,100,0,0);
frame.setVisible(true);
}
});
}
}
(SelfOrganizingMap.java)
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SelfOrganizingMap implements ActionListener {
private Node[][] SOM = null;
private double[][] NORM_MAP = null; //holds the L2 norm of each vector in the SOM[][].
#SuppressWarnings("unused")
private int GRID_OPTION = 0;
private int INPUT_DIMENSION = 0;
private int NUMER_OF_ITERATIONS = 0;
private int CURRENT_ITERATION=0;
private int SOM_HORIZONTAL_LENGTH = 0;
private int SOM_VERTICAL_LENGTH = 0;
private double INITIAL_LEARNING_RATE = 0.0;
private double LEARNING_RATE = 0.0;
private double MAX_RADIUS = 0.0; //radius at first epoch (t = 0)
private double RADIUS = 0.0;
private double TIME_STEP = 0.0; //lambda of X(t) = t0 * exp(-t/lambda)
private String INPUT_SAMPLES = null;
private DisplayLattice DISPLAY_SCREEN = null;
public SelfOrganizingMap(int numberOfNodes, int depth, int grid, int inputDimensison, DisplayLattice screen)
{
INPUT_DIMENSION = inputDimensison;
if(grid == 0)
{
int side = (int)Math.sqrt(numberOfNodes);
SOM = new Node[side][side];
NORM_MAP = new double[side][side];
GRID_OPTION = grid;
MAX_RADIUS = side/2;
DISPLAY_SCREEN = screen;
}
RADIUS = MAX_RADIUS;
}
public void initTrainSOM(String input, int iterations, double learningRate)
{
NUMER_OF_ITERATIONS = iterations;
INITIAL_LEARNING_RATE = learningRate;
LEARNING_RATE = INITIAL_LEARNING_RATE;
TIME_STEP = NUMER_OF_ITERATIONS/Math.log(MAX_RADIUS);
INPUT_SAMPLES = input;
}
private void singleCompleteRun()
{
DISPLAY_SCREEN.render();
System.out.println(CURRENT_ITERATION);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(CURRENT_ITERATION <= NUMER_OF_ITERATIONS)
{
singleCompleteRun();
CURRENT_ITERATION++;
}
}
}
(DisplayLattice.java)
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class DisplayLattice extends JPanel {
private BufferedImage img = new BufferedImage(500, 500, 1);
public void paintComponent(Graphics g) {
if (img == null)
super.paintComponents(g);
else
g.drawImage(img, 0, 0, this);
}
public void render() {
float cellWidth = 100;
float cellHeight = 100;
int imgW = img.getWidth();
int imgH = img.getHeight();
float r, g, b;
Graphics2D g2 = img.createGraphics();
g2.setBackground(Color.black);
g2.clearRect(0,0,imgW,imgH);
for (int x=0; x<100; x++) {
for (int y=0; y<100; y++) {
r = (float)Math.random();
g = (float)Math.random();
b = (float)Math.random();
g2.setColor(new Color(r,g,b));
g2.fillRect((int)(x*cellWidth), (int)(y*cellHeight),
(int)cellWidth+1, (int)cellHeight+1);
}
}
g2.setColor(Color.black);
g2.dispose();
repaint();
}
public BufferedImage getImage() {
if (img == null)
img = (BufferedImage)createImage(500, 500);
return img;
}
public void setImage(BufferedImage bimg) {
img = bimg;
}
}
(Node.java - Structure class for the SOM)
package test;
public class Node {
private int DIMENSION = 0;
private int POSITION_X = 0;
private int POSITION_Y = 0;
private double ACTIVATION_VALUE = 0.0;
public Node(int Dimensions, int x, int y)
{
DIMENSION = Dimensions;
setWeightVector();
POSITION_X = x;
POSITION_Y = y;
}
public int getX() {
return POSITION_X;
}
public int getY() {
return POSITION_Y;
}
public double getACTIVATION_VALUE() {
return ACTIVATION_VALUE;
}
public void setPOSITION_X(int x) {
POSITION_X = x;
}
public void setPOSITION_Y(int y) {
POSITION_Y = y;
}
public void setACTIVATION_VALUE(double y) {
ACTIVATION_VALUE= y;
}
private void setWeightVector()
{
double temp[] = new double[DIMENSION];
for(int i = 0; i<temp.length ; i++)
{
temp[i] = Math.random();
}
}
}
The problem is your DiaplyLattice class.
You overrode paintComponent but you invoke super.paintComponents(g). Notice the extra s you have at the end of paintComponents! This of course is unwanted and should be super.paintComponent(g);
I would have you method as follow:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
Now, just as a good advice/tip to give, don't use null layout and rather use LayoutManager's and possibly use several level of nesting. It's always easier.
Also, you missed an important thing in SSCCE: the SHORT part. Meaning that you should remove anything unnecessary and have a single file to copy/paste.
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.
I am supposed to make a little game simulation. in this game there are three button . when user click start tank and car will close each other in 90 degrees when user click shut button tank will throw bullet to car.
i made and a simulation for this. tank throw bullet to car but when bullet crash car i couldn't this. i just need increase score of how many times tank hit car.
here is the source code
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Vehicle extends Thread {
private JPanel box;
private int XSIZE;
private int YSIZE;
private int time;
private int x;
private int y;
private int dx = 5;
private int dy = 5;
private int dim;
public Vehicle(JPanel b, int i) {
box = b;
this.dim = i;
if (i == 0) {
x = 0;
y = 100;
time = 1000;
XSIZE = 9;
YSIZE = 20;
} else {
time = 200;
y = box.getSize().height;
x = box.getSize().width / 2;
XSIZE = 6;
YSIZE = 10;
}
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void moveHorizontal() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setColor(Color.BLUE);
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
Dimension d = box.getSize();
if (x < 0) {
x = 0;
dx = -dx;
}
if (x + XSIZE >= d.width) {
x = d.width - XSIZE;
dx = -dx;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public JPanel getBox() {
return box;
}
public void setBox(JPanel box) {
this.box = box;
}
public void moveVertical() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
y += dy;
Dimension d = box.getSize();
if (y < 0) {
y = 0;
dy = -dy;
}
if (y + YSIZE >= d.height) {
y = d.height - YSIZE;
dy = -dy;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move(int i) {
if (i == 0) {
moveHorizontal();
} else {
moveVertical();
}
}
public int getYSIZE() {
return YSIZE;
}
public void setYSIZE(int ySIZE) {
YSIZE = ySIZE;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public int getXSIZE() {
return XSIZE;
}
public void setXSIZE(int xSIZE) {
XSIZE = xSIZE;
}
public void setY(int y) {
this.y = y;
}
public void run() {
try {
draw();
for (;;) {
move(dim);
sleep(time);
}
} catch (InterruptedException e) {
}
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Bullet extends Thread {
private JPanel box;
private int XSIZE = 3;
public int getXSIZE() {
return XSIZE;
}
public void setXSIZE(int xSIZE) {
XSIZE = xSIZE;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
private int YSIZE = 1;
private int x;
private int y;
private int dx = 3;
public Bullet(JPanel b, Vehicle tank, Vehicle car) {
box = b;
x = tank.getX() + tank.getXSIZE();
if (x >= tank.getBox().getSize().width / 2)
dx = -dx;
y = tank.getY() + tank.getYSIZE() / 2;
;
}
public void draw() {
Graphics g = box.getGraphics();
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void move() {
if (!box.isVisible())
return;
Graphics g = box.getGraphics();
g.setColor(Color.RED);
g.setXORMode(box.getBackground());
g.fillOval(x, y, XSIZE, YSIZE);
x += dx;
Dimension d = box.getSize();
if (x < 0) {
x = 0;
}
if (x + XSIZE >= d.width) {
x = d.width - XSIZE;
}
g.fillOval(x, y, XSIZE, YSIZE);
g.dispose();
}
public void run() {
try {
draw();
for (;;) {
move();
sleep(20);
}
} catch (InterruptedException e) {
}
}
}
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
#SuppressWarnings("serial")
public class Tank_Shut_Car_ThreadFrame extends JFrame {
private JPanel canvas;
private boolean isOn = false;
private Vehicle tank;
private Vehicle car;
private JLabel score;
public static int sc = 0;
public Tank_Shut_Car_ThreadFrame() {
setResizable(false);
setSize(600, 400);
setTitle("Tank Shut Car");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = getContentPane();
canvas = new JPanel();
contentPane.add(canvas, "Center");
canvas.setLayout(null);
score = new JLabel("0");
score.setBounds(527, 11, 36, 14);
canvas.add(score);
JLabel lblScore = new JLabel("score");
lblScore.setBounds(481, 11, 36, 14);
canvas.add(lblScore);
JPanel p = new JPanel();
addButton(p, "Start", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (!isOn) {
tank = new Vehicle(canvas, 0);
tank.start();
car = new Vehicle(canvas, 1);
car.start();
isOn = true;
}
}
});
addButton(p, "Shut", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (isOn) {
Bullet bullet = new Bullet(canvas, tank, car);
bullet.start();
score.setText("" + sc);
}
}
});
addButton(p, "Close", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
canvas.setVisible(false);
System.exit(0);
}
});
contentPane.add(p, "South");
}
public void addButton(Container c, String title, ActionListener a) {
JButton button = new JButton(title);
c.add(button);
button.addActionListener(a);
}
}
import javax.swing.JFrame;
public class Test {
public static void main(String[] args) {
JFrame frame = new Tank_Shut_Car_ThreadFrame();
frame.setVisible(true);
}
}
Okay, so I had a play around with this (just for fun)
Now, this is far from a "proper" or "complete" game engine, but it provides a basic idea of how it might be possible to mix a core thread engine with UI components.
Rather then pasting the entire code, I've uploaded the source it to Tank.zip
But the basic engine looks like this...
public class GameEngine extends Thread {
public static final Object ASSET_LOCK = new Object();
private List<GameAsset> lstAssets;
private GameScreen screen;
public GameEngine(GameScreen screen) {
// Let the thread die when the JVM closes
setDaemon(true);
// Want to be below the UI thread (personal preference)
setPriority(NORM_PRIORITY - 1);
// A list of game assests
lstAssets = new ArrayList<GameAsset>(25);
// A reference to the screen
this.screen = screen;
// Add global key listener, this is simpler to the trying to attach a key listener
// to the screen.
Toolkit.getDefaultToolkit().addAWTEventListener(new EventHandler(), AWTEvent.KEY_EVENT_MASK);
}
public GameAsset[] getAssets() {
synchronized (ASSET_LOCK) {
return lstAssets.toArray(new GameAsset[lstAssets.size()]);
}
}
/*
* Allows for assets to be added
*/
public void addAsset(GameAsset asset) {
synchronized (ASSET_LOCK) {
lstAssets.add(asset);
}
}
#Override
public void run() {
while (true) {
try {
sleep(40);
} catch (InterruptedException ex) {
}
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : assets) {
if (lstAssets.contains(asset)) {
asset.update(this, screen);
}
}
screen.repaint(new ArrayList<GameAsset>(lstAssets));
}
}
}
/**
* Allows the removal of an asset...
*/
public void removeAsset(GameAsset asset) {
synchronized (ASSET_LOCK) {
lstAssets.remove(asset);
}
}
/**
* Key event handling...
*/
protected class EventHandler implements AWTEventListener {
#Override
public void eventDispatched(AWTEvent event) {
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getID() == KeyEvent.KEY_PRESSED) {
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : assets) {
if (lstAssets.contains(asset)) {
asset.processKeyPressed(GameEngine.this, screen, keyEvent);
}
}
}
} else if (keyEvent.getID() == KeyEvent.KEY_RELEASED) {
synchronized (ASSET_LOCK) {
GameAsset[] assets = lstAssets.toArray(new GameAsset[lstAssets.size()]);
for (GameAsset asset : lstAssets) {
if (lstAssets.contains(asset)) {
asset.processKeyReleased(GameEngine.this, screen, keyEvent);
}
}
}
}
}
}
}
Swing is not thread safe. Events should be fired on the event-dispatching thread.
http://www.javamex.com/tutorials/threads/invokelater.shtml