Dragging of shapes on Jpanel - java

I am using JButton's Action listener to draw different shapes.To keep previously drawn shapes on panel all time, I've used an arraylist in which all drawn shapes has added and repaint whole list.How can I drag any shape while others display on Jpanel all the time?
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("====>>> " + s);
switch (s) {
case "Button1":
Activity act = new Activity();
act.setArcH(15);
act.setArcW(15);
act.setBreadth(40);
act.setLength(50);
act.setXpoint(x);
act.setYpoint(y);
//==========================================================
obj = new ShapePoints();
obj.setShapeId(ShapesID.ROUND_RECTANGLE_ID);
obj.setxPoint(act.getXpoint());
obj.setyPoint(act.getYpoint());
obj.setLength(act.getLength());
obj.setBreadth(act.getBreadth());
obj.setArcW(act.getArcW());
obj.setArcH(act.getArcH());
shapePoints.add(obj);
Iterator itr = shapePoints.iterator();
while (itr.hasNext()) {
ShapePoints sp = (ShapePoints) itr.next();
switch (sp.getShapeId()) {
case ShapesID.ARROW_ID:
break;
case ShapesID.CIRCLE_ID:
g.drawOval(obj.getxPoint(), obj.getyPoint(), obj.getLength(), obj.getBreadth());
break;
case ShapesID.CON_CIRCLE_ID:
g.drawOval(sp.getxPoint(), sp.getyPoint(), sp.getLength(), sp.getLength());
g.fillOval(sp.getxPoint() + 10, sp.getyPoint() + 10, sp.getBreadth() / 2, sp.getBreadth() / 2);
break;
case ShapesID.RECTANGLE_ID:
break;
case ShapesID.ROUND_RECTANGLE_ID:
g.drawRoundRect(obj.getxPoint(), obj.getyPoint(), obj.getLength(), obj.getBreadth(),
obj.getArcW(), obj.getArcH());
break;
}
}
break;
this is for 1 button

You need to add a mouselistener and a mousemotionlistener (usually you make a single instance for both) and check wheter your shape contains the mouse pressed event or not. If yes, you keep track of where the mouse is dragged to translate your shape and continuously call repaint(), like usual.
Single click creates a vertex of a polygon
Double click creates the current drawn polygon (if it has at least 3 vertices) and we create a new one
Right-click clears the current drawn polygon and creates a new one
Press/Drag/Release moves the polygon located under the mouse (if there are several, it takes the first one found. it would probably better to make a reverse for-loop)
Here is an example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseAdapter;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestNaming {
private static final int PANEL_WIDTH = 600;
private static final int PANEL_HEIGHT = 600;
public static class Drawing extends JPanel {
private static final Font FONT = new Font("Arial", Font.PLAIN, 12);
private List<Polygon> polygons = new ArrayList<Polygon>();
private Polygon currentPolygon = new Polygon();
private MouseAdapter mouseListener = new MouseAdapter() {
private Polygon dragged;
private Point lastLocation;
#Override
public void mousePressed(java.awt.event.MouseEvent e) {
for (Polygon p : polygons) {
if (p.contains(e.getPoint())) {
dragged = p;
lastLocation = e.getPoint();
break;
}
}
}
#Override
public void mouseDragged(java.awt.event.MouseEvent e) {
if (dragged != null) {
dragged.translate(e.getX() - lastLocation.x, e.getY() - lastLocation.y);
lastLocation = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(java.awt.event.MouseEvent e) {
dragged = null;
lastLocation = null;
}
#Override
public void mouseClicked(java.awt.event.MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
if (e.getClickCount() == 1) {
addPoint(e.getX(), e.getY());
} else if (e.getClickCount() == 2) {
createPolygon();
}
} else if (SwingUtilities.isRightMouseButton(e)) {
clearCurrentPolygon();
}
}
};
public Drawing() {
addMouseListener(mouseListener);
addMouseMotionListener(mouseListener);
}
protected void addPoint(int x, int y) {
currentPolygon.addPoint(x, y);
repaint();
}
protected void clearCurrentPolygon() {
currentPolygon = new Polygon();
repaint();
}
protected void createPolygon() {
if (currentPolygon.npoints > 2) {
polygons.add(currentPolygon);
}
clearCurrentPolygon();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PANEL_WIDTH, PANEL_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.setFont(FONT);
for (Polygon polygon : polygons) {
drawPolygon(g, polygon);
}
g.setColor(Color.GREEN);
drawPolygon(g, currentPolygon);
}
private void drawPolygon(Graphics g, Polygon polygon) {
if (polygon.npoints < 3) {
if (polygon.npoints == 1) {
g.fillOval(polygon.xpoints[0] - 2, polygon.ypoints[0] - 2, 4, 4);
drawNthPoint(g, polygon, 0);
} else if (polygon.npoints == 2) {
g.drawLine(polygon.xpoints[0], polygon.ypoints[0], polygon.xpoints[1], polygon.ypoints[1]);
drawNthPoint(g, polygon, 0);
drawNthPoint(g, polygon, 1);
}
} else {
g.drawPolygon(polygon);
for (int i = 0; i < polygon.npoints; i++) {
drawNthPoint(g, polygon, i);
}
}
}
private void drawNthPoint(Graphics g, Polygon polygon, int nth) {
// Only works 26 times!
String name = Character.toString((char) ('A' + nth));
int x = polygon.xpoints[nth];
int height = g.getFontMetrics().getHeight();
int y = polygon.ypoints[nth] < height ? polygon.ypoints[nth] + height : polygon.ypoints[nth];
Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(name, g);
g.drawString(name, x, y);
}
}
protected static void initUI() {
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Drawing());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
}

Related

I added a rectangle to a shape Arraylist but the shape will not show up on the panel

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
#SuppressWarnings("serial")
public class GUI extends JFrame implements ActionListener, MouseListener {
private boolean drawLine = false;
private boolean drawRec = false;
private boolean drawOval = false;
private final JButton line;
private final JButton oval;
private final JButton rectangle;
private final JPanel buttonPanel;
public DrawStuff drawPanel = new DrawStuff();
public int x1;
public int x2;
public int y1;
public int y2;
public int click;
public GUI() {
super("Graphics IO");
this.click = 1;
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
line = new JButton("Line");
line.addActionListener(this);
buttonPanel.add(line);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.SOUTH);
//add(drawPanel);
addMouseListener((MouseListener) this);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == line) {
drawLine = true;
repaint();
} else if (source == oval) {
drawOval = true;
repaint();
} else if (source == rectangle) {
drawRec = true;
repaint();
}
}
public static void main(String[] args) {
GUI guiIO = new GUI();
}
class DrawStuff extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLUE);
ArrayList<Shape> shapes = new ArrayList<>();
if (drawLine) {
drawLine = false;
} else if (drawOval) {
//no clue how to add an oval
drawOval = false;
} else if (drawRec) {
Rectangle rec = new Rectangle(x1, y1,Math.abs(x2-x1) , Math.abs(y2-y1));
shapes.add(rec);
drawRec = false;
}
Graphics2D j = (Graphics2D)g;
shapes.stream().map((s) -> {
((Graphics2D) j).draw((Shape) s);
return s;
}).forEach((_item) -> {
repaint();
});
}
}
#Override
public void mousePressed(MouseEvent me) {
if (click == 1){
x1 = me.getX();
y1 = me.getY();
System.out.println(x1);
System.out.println(y1);
click = 2;
}else if (click == 2) {
x2 = me.getX();
y2 = me.getY();
System.out.println(x2);
System.out.println(y2);
click = 1;
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
}
Okay so i have to make a program to create shapes using two mouseclicks and then be able to export/import them. I am trying to use arraylist for this but im having a hard time trying to get it to work. The rectangle im creating will not show up on the panel. What am i doing wrong? Please help me.
Lets start with the fact that DrawStuff hasn't actually been added to anything that is capable of painting it.
DrawStuff#paintComponent should be making decisions about updating the state of the shapes List, instead, your ActionListener and MouseListener should be making these decisions (what to add, where and what do modify), the DrawStuff panel should just be painting what's in the Shape list
You also shouldn't be modifying the state of the component from within the paintComponent calling things like setBackground could set up a repeated repaint request which could cripple your application if not your PC
Modify DrawStuff so it has it's own MouseListener and methods that allow your GUI to ask it to create new shapes. Make the shapes List a instance field so you can manage from within DrawStuff more easily
Something like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GUI extends JFrame implements ActionListener {
private boolean drawLine = false;
private boolean drawRec = false;
private boolean drawOval = false;
private final JButton line;
private final JButton oval;
private final JButton rectangle;
private final JPanel buttonPanel;
public DrawStuff drawPanel = new DrawStuff();
public int x1;
public int x2;
public int y1;
public int y2;
public int click;
public GUI() {
super("Graphics IO");
this.click = 1;
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
line = new JButton("Line");
line.addActionListener(this);
buttonPanel.add(line);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.SOUTH);
add(drawPanel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == line) {
drawPanel.setDrawShape(DrawStuff.DrawShape.LINE);
} else if (source == oval) {
drawPanel.setDrawShape(DrawStuff.DrawShape.OVAL);
} else if (source == rectangle) {
drawPanel.setDrawShape(DrawStuff.DrawShape.RECTANGLE);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GUI guiIO = new GUI();
}
});
}
public static class DrawStuff extends JPanel {
public enum DrawShape {
LINE, OVAL, RECTANGLE;
}
private ArrayList<Shape> shapes = new ArrayList<>();
private DrawShape drawShape = DrawShape.LINE;
private Shape currentShape;
public DrawStuff() {
setBackground(Color.BLUE);
MouseAdapter ma = new MouseAdapter() {
private Point clickPoint;
#Override
public void mousePressed(MouseEvent e) {
clickPoint = e.getPoint();
currentShape = null;
}
#Override
public void mouseReleased(MouseEvent e) {
if (currentShape != null) {
shapes.add(currentShape);
currentShape = null;
repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
switch (getDrawShape()) {
case LINE:
currentShape = new Line2D.Double(clickPoint, e.getPoint());
break;
case OVAL:
case RECTANGLE:
int x = clickPoint.x;
int y = clickPoint.y;
int width = p.x - clickPoint.x;
int height = p.y - clickPoint.y;
if (width < 0) {
x = p.x;
width *= -1;
}
if (height < 0) {
y = p.y;
height *= -1;
}
switch (getDrawShape()) {
case OVAL:
currentShape = new Ellipse2D.Double(x, y, width, height);
break;
case RECTANGLE:
currentShape = new Rectangle2D.Double(x, y, width, height);
break;
}
break;
}
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public DrawShape getDrawShape() {
return drawShape;
}
public void setDrawShape(DrawShape drawShape) {
this.drawShape = drawShape;
currentShape = null;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
for (Shape shape : shapes) {
g2d.draw(shape);
}
if (currentShape != null) {
g2d.setColor(Color.RED);
g2d.draw(currentShape);
}
}
}
}
For example. You always need to be asking yourself "who is responsible for doing what". In this case the DrawStuff panel is actually responsible for determine "where" something is drawn, but it needs more information about "what", then based on that information it can perform the actual operation

Java - Circles with lines connecting the centers

I have a JFrame with a subclass, Paint_Panel. Paint_Panel extends JPanel and implements a MouseListener.
I need to place three circles with mouse clicks. No problem. I have a button (Draw) that should draw lines from each circle's center to the other (thus - a triangle). I can maintain the coordinates within an ArrayList - no problem. However, when I try to reference the ArrayList by clicking the button, the list is returned empty. The Array isn't in memory at the time it is needed to draw the lines. Thoughts?
Note- Circles are hard-coded at 40.
Code:
public class Paint_Panel extends JPanel implements MouseListener {
public static int flag = 0;
boolean drawCircles = false;
boolean drawLines = false;
private final ArrayList<Point> points = new ArrayList<>();
public Paint_Panel() {
addMouseListener(this);
}
//Method to draw lines from point to point
public void drawLines() {
Graphics g = getGraphics();
drawLines = true;
paintComponent(g);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (drawCircles) {
for (int i = 0; i < points.size(); i++) {
//Circle number 1
g.setColor(Color.RED);
g.fillOval(points.get(0).x - 20, points.get(0).y - 20, 40, 40);
//Circle number 2
if (points.size() >= 2) {
g.setColor(Color.GREEN);
g.fillOval(points.get(1).x - 20, points.get(1).y - 20, 40, 40);
}
//Circle number 3
if (points.size() >= 3) {
g.setColor(Color.BLUE);
g.fillOval(points.get(2).x - 20, points.get(2).y - 20, 40, 40);
}
}
} else if (drawLines) {
g.setColor(Color.BLACK); //Set line color
g.drawLine(points.get(0).x, points.get(0).y, points.get(1).x, points.get(1).y);
g.drawLine(points.get(1).x, points.get(1).y, points.get(2).x, points.get(2).y);
g.drawLine(points.get(2).x, points.get(2).y, points.get(0).x, points.get(0).y);
}
}
public void mouseClicked(MouseEvent evt) { //Place circles for click event
Graphics g = getGraphics();
if (!drawCircles) {
prevX = evt.getX() - 20; //Allows placement at center. Size - radius
prevY = evt.getY() - 20;
points.add(evt.getPoint()); //Add point to ArrayList
if (flag < 3) { //Keep track of how many circles are placed
flag += 1;
drawCircles = true;
paintComponent(g);
} else if (flag == 3) { //If additional circles attempted, inform user
flag = 4;
System.out.println("Only 3 circles allowed."); //Debug
drawCircles = false;
}
}
drawCircles = false;
}
#Override
public void mousePressed(MouseEvent evt) { //Unused
}
#Override
public void mouseReleased(MouseEvent evt) { //Unused
}
#Override
public void mouseEntered(MouseEvent evt) { //Unused
}
#Override
public void mouseExited(MouseEvent evt) { //Unused
}
}
Here's one way to draw 3 circles and 3 lines. Edited to draw the circles first, then the lines. Edited again to check for an invalid button press.
I separated the view and controller logic.
Here's the runnable code.
package com.ggl.testing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
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 java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CirclePaintTest implements Runnable {
private JFrame frame;
private PaintPanel paintPanel;
#Override
public void run() {
frame = new JFrame("Circle Paint Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
paintPanel = new PaintPanel();
mainPanel.add(paintPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
JButton lineButton = new JButton("Draw Lines");
lineButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
if (paintPanel.isComplete()) {
paintPanel.setDrawLines(true);
paintPanel.repaint();
}
}
});
buttonPanel.add(lineButton);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new CirclePaintTest());
}
public class PaintPanel extends JPanel {
private static final long serialVersionUID = 6481890334304291711L;
private final Color[] colors = { Color.RED, Color.GREEN, Color.BLUE,
Color.ORANGE, Color.CYAN, Color.YELLOW };
private boolean drawLines;
private final int pointLimit;
private final List<Point> points;
public PaintPanel() {
this.points = new ArrayList<Point>();
this.pointLimit = 3;
this.drawLines = false;
this.addMouseListener(new CircleMouseListener());
this.setPreferredSize(new Dimension(400, 400));
}
public void setDrawLines(boolean drawLines) {
this.drawLines = drawLines;
}
public boolean isComplete() {
return points.size() >= pointLimit;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Point pp = null;
Point p0 = null;
for (int i = 0; i < points.size(); i++) {
g.setColor(colors[i]);
Point p = points.get(i);
g.fillOval(p.x - 20, p.y - 20, 40, 40);
pp = p;
}
if (drawLines && (points.size() > 1)) {
p0 = points.get(0);
pp = p0;
g.setColor(Color.BLACK);
for (int i = 1; i < points.size(); i++) {
Point p = points.get(i);
g.drawLine(pp.x, pp.y, p.x, p.y);
pp = p;
}
g.drawLine(pp.x, pp.y, p0.x, p0.y);
}
}
public class CircleMouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent event) {
if (points.size() < pointLimit) {
points.add(event.getPoint());
PaintPanel.this.repaint();
}
}
}
}
}
You don't call repaint when flag equals 3, so there is no call to the paintComponent method with the right condition (drawCircles false and drawLines true).
I suggest you to call repaint either when flag equals to 3 or and the end of mouseClicked.

How to name the coordinates (points) in Java Swing

I'm designing an interface using java swing. There is a canvas for the user to draw shapes (circle, triangle, square, etc.). When the user draws a shape, I want to name each point in the shape alphabetically. I know how to get the coordinates but how do I name the points?
Here is one way to do it. You use Character.toString(char) and use 'A'+offset to get any char from the alphabet.
See in this small demo example, which draws polygons.
Single click creates vertices of your polygon
Double-click stores the current polygon and starts creating a new polygon
Right-click clears the current polygon and starts a new one.
Side-note: positioning of the text is not smart, so it overlaps lines of the polygon sometimes.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseAdapter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestNaming {
private static final int PANEL_WIDTH = 600;
private static final int PANEL_HEIGHT = 600;
public static class Drawing extends JPanel {
private static final Font FONT = new Font("Arial", Font.PLAIN, 12);
private List<Polygon> polygons = new ArrayList<Polygon>();
private Polygon currentPolygon = new Polygon();
private MouseAdapter mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
if (e.getClickCount() == 1) {
addPoint(e.getX(), e.getY());
} else if (e.getClickCount() == 2) {
createPolygon();
}
} else if (SwingUtilities.isRightMouseButton(e)) {
clearCurrentPolygon();
}
}
};
public Drawing() {
addMouseListener(mouseListener);
}
protected void addPoint(int x, int y) {
currentPolygon.addPoint(x, y);
repaint();
}
protected void clearCurrentPolygon() {
currentPolygon = new Polygon();
repaint();
}
protected void createPolygon() {
if (currentPolygon.npoints > 2) {
polygons.add(currentPolygon);
}
clearCurrentPolygon();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PANEL_WIDTH, PANEL_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.setFont(FONT);
for (Polygon polygon : polygons) {
drawPolygon(g, polygon);
}
g.setColor(Color.GREEN);
drawPolygon(g, currentPolygon);
}
private void drawPolygon(Graphics g, Polygon polygon) {
if (polygon.npoints < 3) {
if (polygon.npoints == 1) {
g.fillOval(polygon.xpoints[0] - 2, polygon.ypoints[0] - 2, 4, 4);
drawNthPoint(g, polygon, 0);
} else if (polygon.npoints == 2) {
g.drawLine(polygon.xpoints[0], polygon.ypoints[0], polygon.xpoints[1], polygon.ypoints[1]);
drawNthPoint(g, polygon, 0);
drawNthPoint(g, polygon, 1);
}
} else {
g.drawPolygon(polygon);
for (int i = 0; i < polygon.npoints; i++) {
drawNthPoint(g, polygon, i);
}
}
}
private void drawNthPoint(Graphics g, Polygon polygon, int nth) {
// Only works 26 times!
String name = Character.toString((char) ('A' + nth));
int x = polygon.xpoints[nth];
int height = g.getFontMetrics().getHeight();
int y = polygon.ypoints[nth] < height ? polygon.ypoints[nth] + height : polygon.ypoints[nth];
g.drawString(name, x, y);
}
}
protected static void initUI() {
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Drawing());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initUI();
}
});
}
}
If I'm understanding you correctly, you want to label the coordinates alphabetically (like A, B, C, D)
Since you said you know the coordinates already...use a JLabel:
JLabel A_label = new JLabel("A");
JLabel B_label = new JLabel("B");
A_label.setLocation(shape1_x, shape1_y);
B_label.setLocation(shape2_x, shape2_y);

Object issues in Java

I'm attempting to implement the dragging functionality of shapes on a canvas. My Shape class inherits from JPanel.
Absolutely nothing happens when I click on a shape, drag it and let go of the mouse button. It just remains where it was originally. Any ideas?
You need a few basic things:
A field for the shape itself (you already had)
Fields to keep track of the offset of the click within the shape (already had)
A field to keep track of if you're dragging
Overwrite the paintComponent method to paint your shape
A MouseListener and MouseMotionListener added to the Panel (MouseAdapter does both of these)
Here's a basic working example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawTest extends JPanel{
//Shape doesn't have a location field - you'd have to keep track of
//this yourself if you're set on using the shape interface
private Rectangle shape = new Rectangle(100, 100);
// The location within the shape you clicked
private int xOffset = 0;
private int yOffset = 0;
// To indicate dragging is happening
boolean isDragging = false;
public DrawTest(){
MouseAdapter listener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// Starts dragging and calculates offset
if(shape.contains(e.getPoint())){
isDragging = true;
xOffset = e.getPoint().x - shape.x;
yOffset = e.getPoint().y - shape.y;
}
}
#Override
public void mouseReleased(MouseEvent e) {
// Ends dragging
isDragging = false;
}
#Override
public void mouseDragged(MouseEvent e) {
// Moves the shape - doesn't actually need to be a method
// but is because you had it as one
if(isDragging){
moveShape(e);
}
}
private void moveShape(MouseEvent e) {
Point newLocation = e.getPoint();
newLocation.x -= xOffset;
newLocation.y -= yOffset;
shape.setLocation(newLocation);
repaint();
}
};
//Add a mouse mostion listener (for dragging) and regular listener (for clicking)
addMouseListener(listener);
addMouseMotionListener(listener);
}
// So we have a play area to work with
public Dimension getPreferredSize(){
return new Dimension(400,300);
}
//Paints the shape
public void paintComponent(Graphics g){
super.paintComponent(g);
g.clearRect(0,0,getWidth(), getHeight());
g.fillRect(shape.x, shape.y, shape.width, shape.height);
}
public static void main(String[] args)
{
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Tried a small simple example
Dragging the rectangle will make it move with the cursor it also checks the bounds so the rectangle cannot be dragged off screen:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ShapeMover {
public ShapeMover() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Shape Mover");
initComponents(frame);
frame.pack();
frame.setVisible(true);
}
public static void main(String s[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ShapeMover();
}
});
}
private void initComponents(JFrame frame) {
frame.getContentPane().add(new DragPanel());
}
}
class DragPanel extends JPanel {
Rectangle rect = new Rectangle(0, 0, 100, 50);
int preX, preY;
boolean isFirstTime = true;
Rectangle area;
boolean pressOut = false;
private Dimension dim = new Dimension(400, 300);
public DragPanel() {
setBackground(Color.white);
addMouseMotionListener(new MyMouseAdapter());
addMouseListener(new MyMouseAdapter());
}
#Override
public Dimension getPreferredSize() {
return dim;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
if (isFirstTime) {
area = new Rectangle(dim);
rect.setLocation(50, 50);
isFirstTime = false;
}
g2d.setColor(Color.black);
g2d.fill(rect);
}
boolean checkRect() {
if (area == null) {
return false;
}
if (area.contains(rect.x, rect.y, 100, 50)) {
return true;
}
int new_x = rect.x;
int new_y = rect.y;
if ((rect.x + 100) > area.getWidth()) {
new_x = (int) area.getWidth() - 99;
}
if (rect.x < 0) {
new_x = -1;
}
if ((rect.y + 50) > area.getHeight()) {
new_y = (int) area.getHeight() - 49;
}
if (rect.y < 0) {
new_y = -1;
}
rect.setLocation(new_x, new_y);
return false;
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
preX = rect.x - e.getX();
preY = rect.y - e.getY();
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = true;
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (!pressOut) {
updateLocation(e);
} else {
}
}
#Override
public void mouseReleased(MouseEvent e) {
if (rect.contains(e.getX(), e.getY())) {
updateLocation(e);
} else {
pressOut = false;
}
}
public void updateLocation(MouseEvent e) {
rect.setLocation(preX + e.getX(), preY + e.getY());
checkRect();
repaint();
}
}
}
Reference:
http://www.java2s.com/Code/Java/Event/MoveShapewithmouse.htm

java swing - paint jcomponent

i am try to make chorded keyboard simulation.
I cannot resolve why KeyboardButtons in Keyboard are not painting. I have more KeyboardButtons in Keyboard. Mouse is listened properly, but polygons are not painted.
When i call paint to each KeyboardButton in the Keyboard's paintComponent(), polygons are painted, but not changing color on mousePressed.
Keyboard.java
package keyboard;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Keyboard extends JPanel implements MouseListener{
Point[] leftFingers;
Point leftCenter = new Point(300, 600);
KeyboardButton[] buttons;
public Keyboard(Point left1, Point left2, Point left3, Point left4, Point left5) {
leftFingers = new Point[5];
leftFingers[0] = left1;
leftFingers[1] = left2;
leftFingers[2] = left3;
leftFingers[3] = left4;
leftFingers[4] = left5;
buttons = registerKeys();
addMouseListener(this);
}
public KeyboardButton[] registerKeys() {
Polygon[] polygons = generateKeyPolygons(calculateBordersOfKeys(leftFingers));
KeyboardButton[] buttons = new KeyboardButton[5];
for (int i = 0; i < polygons.length; i++) {
buttons[i] = new KeyboardButton(polygons[i]);
}
return buttons;
}
private Point[] calculateBordersOfKeys(Point[] fingers) {
Point[] centers = calculateCentersBetweenEachTwoFingers(fingers);
Point[] result = new Point[6];
result[0] = calculateCentralSymmetry(centers[0], fingers[0]);
System.arraycopy(centers, 0, result, 1, centers.length);
result[5] = calculateCentralSymmetry(centers[3], fingers[4]);
return result;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.drawOval(leftCenter.x - 25, leftCenter.y - 25, 50, 50);
for (int i = 0; i < leftFingers.length; i++) {
g.drawOval(leftFingers[i].x, leftFingers[i].y, 10, 10);
}
}
private Polygon[] generateKeyPolygons(Point[] borders) {
Polygon[] polygons = new Polygon[5];
for (int i = 0; i < borders.length - 1; i++) {
Polygon p = new Polygon();
p.addPoint(leftCenter.x, leftCenter.y);
p.addPoint(borders[i].x, borders[i].y);
p.addPoint(borders[i + 1].x, borders[i + 1].y);
polygons[i] = p;
}
return polygons;
}
private Point[] calculateCentersBetweenEachTwoFingers(Point[] fingers) {
Point[] centers = new Point[4];
for (int i = 0; i < fingers.length - 1; i++) {
centers[i] = new Point(((fingers[i].x + fingers[i + 1].x) / 2), ((fingers[i].y + fingers[i + 1].y) / 2));
}
return centers;
}
private Point calculateCentralSymmetry(Point toReflected, Point center) {
Point reflection = new Point();
if (toReflected.x > center.x) {
reflection.x = center.x - Math.abs(center.x - toReflected.x);
} else {
reflection.x = center.x + Math.abs(center.x - toReflected.x);
}
if (toReflected.y > center.y) {
reflection.y = center.y - Math.abs(center.y - toReflected.y);
} else {
reflection.y = center.y + Math.abs(center.y - toReflected.y);
}
return reflection;
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
for (KeyboardButton button : buttons) {
button.checkMousePosition(e);
}
}
public void mouseReleased(MouseEvent e) {
for (KeyboardButton button : buttons) {
button.checkMousePosition(e);
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
KeyboardButton.java
package keyboard;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.event.*;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class KeyboardButton extends JComponent {
Polygon polygon;
boolean isActive;
final Color ACTIVE_COLOR = Color.red;
final Color INACTIVE_COLOR = Color.blue;
public KeyboardButton(Polygon p) {
polygon = p;
}
public void checkMousePosition(MouseEvent e) {
if (polygon.contains(e.getX(), e.getY())) {
setState(true);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(isActive ? ACTIVE_COLOR : INACTIVE_COLOR);
g.drawPolygon(polygon);
}
void setState(boolean state) {
isActive = state;
System.out.println(this.hashCode());
repaint();
}
}
As far as I can tell, the KeyboardButton components are never added to the Keyboard. So, when they call repaint(), it has no effect because they are not part of the view hierarchy.

Categories