Adding 2 shapes at the same time on a jFrame - java

I read many other posts regarding this and I learned that the frame is set to BorderLayout by default. I added one shape to the west and one shape to the center of the frame. But still, only one shape comes up on the frame. The shape that comes up on the frame is the one whose location is at center.
Here is the code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class ShapeMover {
private static final int FRAME_WIDTH = 400;
private static final int FRAME_HEIGHT = 400;
private static final int SHAPE_WIDTH = 50;
private static final int INITIAL_X = 30;
private static final int INITIAL_Y = 100;
private static final int rec_x = 200;
private static final int rec_y = 200;
private static final int rec_height = 30;
private static final int rec_width = 50;
private boolean recToggle = true;
private boolean circleToggle = true;
private JFrame frame;
private CircleComponent myShape;
private RectangleComponent recShape;
private JButton circle, rectangle;
private JPanel panel, panel2;
private void initialSetUp() {
frame = new JFrame();
myShape = new CircleComponent(INITIAL_X, INITIAL_Y, SHAPE_WIDTH);
recShape = new RectangleComponent(rec_x, rec_y,rec_height, rec_width);
circle = new JButton("Click for circle");
event c = new event();
circle.addActionListener(c);
rectangle = new JButton("Click for rectangle");
event2 r = new event2();
rectangle.addActionListener(r);
panel = new JPanel();
panel.add(circle);
panel.add(rectangle);
frame.add(panel, BorderLayout.NORTH);
frame.add(myShape, BorderLayout.WEST);
frame.add(recShape,BorderLayout.CENTER);
myShape.setVisible(false);
recShape.setVisible(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setVisible(true);
} //method
public class event implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(circleToggle == true){
myShape.setVisible(true);
circleToggle = false;
}
else{
myShape.setVisible(false);
circleToggle = true;
}
}
}
public class event2 implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
if(recToggle == true){
recShape.setVisible(true);
recToggle = false;
}
else{
recShape.setVisible(false);
recToggle = true;
}
}
}
public static void main(String[] args) {
ShapeMover sm = new ShapeMover();
sm.initialSetUp();
} //main
} //class
I warn you the other code is pretty long.
Here is rectangle component:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;
public class RectangleComponent extends JComponent{
private CompoundShape shape2;
private Point mousePoint2;
public RectangleComponent(int x, int y, int height, int width){
shape2 = new RectangleShape(x, y, height, width);
addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent event2){
mousePoint2 = event2.getPoint();
if(!shape2.contains(mousePoint2)){
mousePoint2 = null;
}
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent event2){
if(mousePoint2 == null){
return;
}
Point lastMousePoint2 = mousePoint2;
mousePoint2 = event2.getPoint();
double dx = mousePoint2.getX() - lastMousePoint2.getX();
double dy = mousePoint2.getY() - lastMousePoint2.getY();
shape2.translate((int) dx, (int) dy);
repaint();
}
});
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//shape.draw(g2);
shape2.draw(g2);
} //method
}
Here is the circle Component:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JComponent;
public class CircleComponent extends JComponent{
private Circle shape2;
private Point mousePoint2;
public CircleComponent(int x, int y, int width){
shape2 = new Circle(x, y, width);
addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent event2){
mousePoint2 = event2.getPoint();
if(!shape2.contains(mousePoint2)){
mousePoint2 = null;
}
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent event2){
if(mousePoint2 == null){
return;
}
Point lastMousePoint2 = mousePoint2;
mousePoint2 = event2.getPoint();
double dx = mousePoint2.getX() - lastMousePoint2.getX();
double dy = mousePoint2.getY() - lastMousePoint2.getY();
shape2.translate((int) dx, (int) dy);
repaint();
}
});
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
//shape.draw(g2);
shape2.draw(g2);
} //method
}
Here is circle:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class Circle implements CompoundShape {
private GeneralPath path = null;
private int x;
private int y;
private final int width;
public Circle(int x, int y, int width){
this.x = x;
this.y = y;
this.width = width;
}
#Override
public void draw(Graphics2D g2) {
Ellipse2D.Double c = new Ellipse2D.Double(x,y,width,width);
g2.setColor(Color.RED);
g2.fill(c);
g2.draw(c);
path = new GeneralPath();
path.append(c,false);
g2.draw(path);
}
#Override
public void translate(int dx, int dy) {
// TODO Auto-generated method stub
x = x + dx;
y = y + dy;
}
#Override
public boolean contains(Point point) {
// TODO Auto-generated method stub
if(path == null){
return false;
}
return path.contains(point);
}
}
Here is rectangle shape:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class RectangleShape implements CompoundShape {
private GeneralPath path = null;
private int x;
private int y;
private final int width;
private final int height;
public RectangleShape(int x, int y, int width, int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
#Override
public void draw(Graphics2D g2) {
Rectangle r = new Rectangle(x,y,width,height);
g2.setColor(Color.BLUE);
g2.fill(r);
g2.draw(r);
path = new GeneralPath();
path.append(r,false);
g2.draw(path);
}
#Override
public void translate(int dx, int dy) {
// TODO Auto-generated method stub
x = x + dx;
y = y + dy;
}
#Override
public boolean contains(Point point) {
// TODO Auto-generated method stub
if(path == null){
return false;
}
return path.contains(point);
}
}
Here is compound shape:
import java.awt.Graphics2D;
import java.awt.Point;
public interface CompoundShape {
void draw(Graphics2D g2);
void translate(int dx, int dy);
boolean contains(Point point);
} //interface

Examples of iterating an ArrayList<Shape> can be seen in:
This answer to Get mouse detection with a dynamic shape.
This answer to 'Fill' Unicode characters in labels.
Of course, those examples are painting to an image, but once there is a Graphics (or Graphics2D as I prefer to work with) the principle is much the same. Copy/pasted from one example:
ArrayList<Shape> regions = separateShapeIntoRegions(imageShapeArea);
// ..
for (Shape region : regions) {
// ..
g.fill(region);
// ..
}

Related

How to move different shapes with MouseListener

I have a program that paints different shapes that I put in the ArrayList, it works fine to iterate with shapes to paint them but my methods for moving them doesn't work. Is it something wrong with my move() method?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyShapes extends JPanel {
private Point2D.Float position;
private final DifferentShapes[] shapes = new DifferentShapes[]{new Circle(), new Triangle(), new Square()};
MovingAdapter ma = new MovingAdapter();
public MyShapes() {
addMouseMotionListener(ma);
addMouseListener(ma);
}
interface DifferentShapes {
void paint(Graphics2D graphics);
boolean contains(int x, int y);
void move(int dx, int dy);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D graphics = (Graphics2D) g;
for (DifferentShapes shape : this.shapes) {
shape.paint(graphics);
}
}
class MovingAdapter
public class MovingAdapter extends MouseAdapter {
private int x;
private int y;
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseDragged(MouseEvent e) {
final int dx = e.getX() - x;
final int dy = e.getY() - y;
for (DifferentShapes shape : shapes) {
if (shape.contains(x, y)) {
shape.move(dx, dy);
}
}
x += dx;
y += dy;
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Shapes World");
MyShapes m = new MyShapes();
m.setDoubleBuffered(true);
frame.add(m);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class Circle
class Circle implements MyShapes.DifferentShapes {
public Circle() {
}
public static Ellipse2D.Float myCr = new Ellipse2D.Float(10,10, 100, 100);
public void paint(Graphics2D graphics) {
Graphics2D circle = (Graphics2D) graphics;
circle.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
circle.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
circle.setColor(new Color(0, 0, 117));
circle.fill(myCr);
}
#Override
public boolean contains(int x, int y) {
if (myCr.contains(x, y)) {
}
return true;
}
public void move(int dx, int dy) {
myCr.x += dx;
myCr.y += dy;
}
}
When I use regular if statement it works fine but not in the for loop and my move() method
The logic is right and you are correctly changing the coordinates. You just need to call repaint() in order to make the the changes display.
if (shape.contains(x, y)) {
shape.move(dx, dy);
repaint();
}

Repaint() and PaintComponent() not updating properly

I have a Jframe with two buttons: 'A' and 'B'. Clicking the button 'A' should display the capital letter A in the JPanel. The problem here is that on repeated mouse click the previous letters drawn are not show. I want to make sure that whatever is drawn stays in the drawing. The following is the code for my program.
Code for JFrame:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawFrame extends JFrame{
private final int WIDTH = 500;
private final int HEIGHT = 300;
private GUIModel model;
private JButton number1;
private JButton number2;
private JPanel numberPanel;
private DrawPanel graphicsPanel;
public DrawFrame()
{
this.model = new GUIModel(" ");
createSelectionPanel();
createGraphicsPanel();
this.setSize(WIDTH, HEIGHT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
private void createSelectionPanel()
{
numberPanel = new JPanel();
ButtonListener listener = new ButtonListener();
number1 = new JButton("A");
number1.addActionListener(listener);
number2 = new JButton("B");
number2.addActionListener(listener);
numberPanel.setLayout(new GridLayout(2,2));
numberPanel.add(number1);
numberPanel.add(number2);
this.add(numberPanel, BorderLayout.WEST);
}
private void createGraphicsPanel()
{
//instantiate drawing panel
graphicsPanel = new DrawPanel(WIDTH, HEIGHT, model);
//add drawing panel to right
add(graphicsPanel);
}
private class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
model.setDisplayString(event.getActionCommand());
}
}
//creates a drawing frame
public static void main(String[] args)
{
DrawFrame draw = new DrawFrame();
}
}
Code for JPanel:
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
public class DrawPanel extends JPanel{
private static final long serialVersionUID = 3443814601865936618L;
private Font font = new Font("Default", Font.BOLD, 30);
private static final Color DEFAULT_TEXT_COLOR = Color.BLACK;
private static final Color HOVER_TEXT_COLOR = Color.RED;
private Color color = DEFAULT_TEXT_COLOR;
private List<GUIModel> numberList = new ArrayList<GUIModel>();
private GUIModel model;
boolean mouseHover = false;
public DrawPanel(int width, int height, GUIModel model){
this.setPreferredSize(new Dimension(width, height));
this.model = model;
//set white background for drawing panel
setBackground(Color.WHITE);
//add mouse listeners
MouseHandler mouseHandler = new MouseHandler();
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
}
// void checkForHover(MouseEvent event) {
// FontMetrics metrics = getFontMetrics(font);
//
// Graphics g = getGraphics();
// Rectangle textBounds = metrics.getStringBounds("C", g).getBounds();
// g.dispose();
//
// int index = 0;
// while (index < numberList.size()) {
// Double x = numberList.get(index).getCoordinate().getX();
// Double y = numberList.get(index).getCoordinate().getY();
//
// textBounds.translate(x.intValue(), y.intValue());
//
// if (textBounds.contains(event.getPoint())) {
// color = HOVER_TEXT_COLOR;
// }
// else {
// color = DEFAULT_TEXT_COLOR;
// }
// index++;
// }
// }
this is my PaintComponent method where I'm going through the list of letters I've drawn at different coordinates and drawing them on the canvas
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setFont(font);
g.setColor(color);
int index = 0;
while (index < numberList.size()) {
Double x = numberList.get(index).getCoordinate().getX();
Double y = numberList.get(index).getCoordinate().getY();
String display = numberList.get(index).getDisplayString();
g.drawString(display, x.intValue(), y.intValue());
index++;
}
if (model.getCoordinate() != null) {
Point p = model.getCoordinate();
g.drawString(model.getDisplayString(), p.x, p.y);
numberList.add(model);
}
}
//class to handle all mouse events
private class MouseHandler extends MouseAdapter implements MouseMotionListener
{
#Override
public void mousePressed(MouseEvent event)
{
model.setCoordinate(event.getPoint());
}
#Override
public void mouseReleased(MouseEvent event)
{
DrawPanel.this.repaint();
}
// #Override
// public void mouseEntered(MouseEvent event) {
// checkForHover(event);
// }
//
// #Override
// public void mouseMoved(MouseEvent event) {
// checkForHover(event);
// }
}
}
Code for GUIModel:
import java.awt.Point;
public class GUIModel {
private String displayString;
private Point coordinate;
public GUIModel(String displayString) {
this.displayString = displayString;
}
public void setDisplayString(String displayString) {
this.displayString = displayString;
}
public String getDisplayString() {
return displayString;
}
public Point getCoordinate() {
return coordinate;
}
public void setCoordinate(int x, int y) {
this.coordinate = new Point(x, y);
}
public void setCoordinate(Point coordinate) {
this.coordinate = coordinate;
}
}
Any help or suggestions would be much appreciated. Thanks.
#MadProgrammer Your comment helped me fix my code. Like you said I needed to create a new GUIModel and add it to my numberList.
I modified my paintComponent method to reflect that and it now works. So, Thanks!
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setFont(font);
g.setColor(color);
int index = 0;
while (index < numberList.size()) {
Double x = numberList.get(index).getCoordinate().getX();
Double y = numberList.get(index).getCoordinate().getY();
String display = numberList.get(index).getDisplayString();
g.drawString(display, x.intValue(), y.intValue());
index++;
}
if (model.getCoordinate() != null) {
Point p = model.getCoordinate();
g.drawString(model.getDisplayString(), p.x, p.y);
GUIModel number = new GUIModel();
number.setCoordinate(p);
number.setDisplayString(model.getDisplayString());
numberList.add(number);
}
}

Coloring 2 Ovals with Graphics2D

I want to Color 2 Ovals in Java with Graphics2D. Oval1(point) Green and Oval2(point2) Blue. The Problem is that Oval2 becomes green and Oval1 black. Does somebody knows what the problem is?
left(oval1) right(oval2)
Here is the SSCCE:
GameView.java
import javax.swing.JFrame;
import stackoverflow.GameView;
public class GameView extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
private Game game = new Game();
public GameView(){
JFrame gameFrame = new JFrame("Game");
gameFrame.setSize(500, 300);
gameFrame.setVisible(true);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.add(game);
game.runGame();
}
public static void main(String[] args) throws InterruptedException {
new GameView();
}
}
Game.java
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
import stackoverflow.Point;
public class Game extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
private Point point = new Point(Color.GREEN);
private Point point2 = new Point(Color.BLUE);
public void runGame(){
repaint();
point2.setX(300);
}
public void paint(Graphics g) {
point.paint(g);
point2.paint(g);
}
}
Point.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
public class Point {
private int x = 100;
private int y = 100;
private int width = 10;
private int height = 10;
private Color color;
public Point(Color color){
this.color = color;
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, width, height);
g2d.setColor(this.color);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Change the order of these calls...
g2d.fillOval(x, y, width, height);
g2d.setColor(this.color);
And you should be painting in JPanel.paintComponent instead.

Java JApplet: Why aren't my components appearing on screen?

So I've got this challenge to make one of those spirograph drawrings in an applet. The problem is, I'm new to Java and have absolutely no idea how to get any components appearing on the screen. I'm hoping someone can just add an extra line of code to fix this, though I'm really grateful for any answers :)
import javax.swing.JApplet;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.Toolkit;
public class SpaceCadets3_WB extends JApplet {
int numOfPoints = 1080;
int[] x = new int[numOfPoints];
int[] y = new int[numOfPoints];
int x1, x2, y1, y2, width, height, animationSleep = 0;
int R = 75;
int r = 10;
int O = 75;
JTextField changeNumOfPoints = new JTextField(15);
public SpaceCadets3_WB() {
}
public void start() {
this.setSize(600, 600);
this.setBackground(new Color(100,100,255));
this.getContentPane().setLayout(null);
this.getContentPane().add(changeNumOfPoints);
changeNumOfPoints.setVisible(true);
changeNumOfPoints.setLocation(width - changeNumOfPoints.getSize().width - 25, 25);
}
public void calculatePoints(){
width = SpaceCadets3_WB.this.getWidth();
height = SpaceCadets3_WB.this.getHeight();
for(int t = 0; t<numOfPoints; t++){
x[t] = (int) ((R+r)*Math.cos(t) - (r+O)*Math.cos(((R+r)/r)*t) + width/2);
y[t] = (int) ((R+r)*Math.sin(t) - (r+O)*Math.sin(((R+r)/r)*t) + height/2);
}
}
public void paint(Graphics g){
g.setColor(Color.RED);
calculatePoints();
for(int i = 0; i<numOfPoints;i++){
x1 = x[i];
x2 = x[i+1];
y1 = y[i];
y2 = y[i+1];
g.drawLine(x1, y1, x2, y2);
try {
Thread.sleep(animationSleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Your sleeping the paint method, something you should never do. It's bad to call Thread.sleep(...) on the Swing event thread, but it's a sin to do it in any painting method. So now the applet can't draw. Remember that any painting method must do nothing but painting, and must do it blazingly fast. It shouldn't do any program logic, it shouldn't directly do animation, it should just paint. Use a Swing timer as any similar question will show you how to do.
Also, never draw directly in the applet but instead in the paintComponent method of a JPanel that the applet holds.
So create your JPanel, override its paintComponent method, and draw using fields of the class. Then change the state of those fields in your Timer and call repaint() on the JPanel.
Edit
And yes, you should avoid using null layouts as that's preventing you from easily and adequately adding components to your GUI. Instead in this situation, a FlowLayout, the default layout for JPanel, would work great.
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.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
#SuppressWarnings("serial")
public class SpaceCadets extends JApplet {
#Override
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
SpaceCadetsPanel panel = new SpaceCadetsPanel();
getContentPane().add(panel);
setSize(SpaceCadetsPanel.PREF_W, SpaceCadetsPanel.PREF_H);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
#SuppressWarnings("serial")
class SpaceCadetsPanel extends JPanel {
public static final int PREF_W = 600;
public static final int PREF_H = 600;
public final static int TOTAL_POINTS = 1080;
private static final int R = 75;
private static final int R2 = 10;
private static final int O = 75;
private static final Color DRAW_COLOR = Color.RED;
private static final int ANIMATION_DELAY = 20;
private Point[] pts;
private JSpinner pointCountSpinner = new JSpinner(new SpinnerNumberModel(
800, 100, 1080, 1));
private JButton doItButton = new JButton(new DoItBtnAction("Do It!"));
private BufferedImage bufImg = new BufferedImage(PREF_W, PREF_H,
BufferedImage.TYPE_INT_ARGB);
private Timer timer;
public int imageIndex;
private CalcWorker calcWorker;
public Graphics2D g2;
public SpaceCadetsPanel() {
System.out.println(pointCountSpinner.getEditor().getClass());
add(pointCountSpinner);
add(doItButton);
setBackground(Color.white);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bufImg != null) {
g.drawImage(bufImg, 0, 0, this);
}
}
class DoItBtnAction extends AbstractAction {
public DoItBtnAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
imageIndex = 0;
if (timer != null && timer.isRunning()) {
timer.stop();
}
if (g2 != null) {
g2.dispose();
}
pts = new Point[0];
bufImg = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
g2 = bufImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(DRAW_COLOR);
int totalPoints = 0;
totalPoints = ((Integer) pointCountSpinner.getValue()).intValue();
timer = new Timer(ANIMATION_DELAY, new TimerListener(totalPoints));
calcWorker = new CalcWorker(totalPoints);
calcWorker.addPropertyChangeListener(new CalcWorkerListener());
calcWorker.execute();
}
}
class CalcWorker extends SwingWorker<Point[], Void> {
private int totalPoints;
public CalcWorker(int totalPoints) {
this.totalPoints = totalPoints;
}
#Override
protected Point[] doInBackground() throws Exception {
Point[] pts2 = new Point[totalPoints];
for (int i = 0; i < pts2.length; i++) {
int x = (int) ((R + R2) * Math.cos(i) - (R2 + O)
* Math.cos(((R + R2) / R2) * i) + PREF_W / 2);
int y = (int) ((R + R2) * Math.sin(i) - (R2 + O)
* Math.sin(((R + R2) / R2) * i) + PREF_H / 2);
pts2[i] = new Point(x, y);
}
return pts2;
}
}
class CalcWorkerListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
try {
pts = calcWorker.get();
timer.start();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
class TimerListener implements ActionListener {
private int totalPoints;
public TimerListener(int totalPoints) {
this.totalPoints = totalPoints;
}
#Override
public void actionPerformed(ActionEvent e) {
int x1 = pts[imageIndex].x;
int y1 = pts[imageIndex].y;
int x2 = pts[imageIndex + 1].x;
int y2 = pts[imageIndex + 1].y;
g2.drawLine(x1, y1, x2, y2);
repaint();
imageIndex++;
if (imageIndex == totalPoints - 1) {
((Timer) e.getSource()).stop();
}
}
}
}
Which displays as,

Java: mouseDragged and moving around in a graphical interface

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);
}
});
}
}

Categories

Resources