Paint Program: Array is writing backwards to the panel - java

I posted this code earlier, and got a very good answer, but not a working answer. Could someone please show me how to change my code in order to get this fixed? This will run and compile. It is supposed to draw a line on top of a line, but instead it is drawing under the previous line. I have tried using Collections.reverse(segments); but it doesn't take care of element at zero. I also have tried changing to segments.add(new Segment()); but I am not sure what to change in MouseMotionListener to get this to work accordingly. Any help with this would be great! Thank You! :)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class SimplePaint extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
JButton action = new JButton();
JButton red = new JButton();
JButton blue = new JButton();
JButton yellow = new JButton();
Color initial = Color.MAGENTA;
JButton thin = new JButton();
JButton medium = new JButton();
JButton thick = new JButton();
Stroke stroke = new BasicStroke(3);
private static ArrayList<Point> points = new ArrayList<Point>();
JButton erase = new JButton();
JButton drawing = new JButton();
Point start = null;
Point end = null;
Line2D draw = new Line2D.Float();
JPanel panel = new JPanel();
private class Segment {
private final List<Point> points = new ArrayList<Point>();
private final Color color = initial;
private final Stroke stroke = SimplePaint.this.stroke;
}
private final List<Segment> segments = new ArrayList<>();
public SimplePaint() {
getContentPane().add(panel);
setSize(450, 450);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
design();
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
segments.add(0, new Segment());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
segments.get(0).points.add(e.getPoint());
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e){
points.add(e.getPoint());
repaint();
}
});
blue.addActionListener(this);
red.addActionListener(this);
yellow.addActionListener(this);
thin.addActionListener(this);
medium.addActionListener(this);
thick.addActionListener(this);
erase.addActionListener(this);
drawing.addActionListener(this);
}
public void design() {
panel.setBackground(Color.BLACK);
blue.setBackground(Color.BLUE);
blue.setPreferredSize(new Dimension(50, 25));
panel.add(blue);
red.setBackground(Color.RED);
red.setPreferredSize(new Dimension(50, 25));
panel.add(red);
yellow.setBackground(Color.yellow);
yellow.setPreferredSize(new Dimension(50, 25));
panel.add(yellow);
thin.setText("Thin");
panel.add(thin);
medium.setText("Medium");
panel.add(medium);
thick.setText("Thick");
panel.add(thick);
erase.setText("Erase");
panel.add(erase);
drawing.setText("Draw");
panel.add(drawing);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == blue){
initial = Color.BLUE;
}else if(e.getSource() == red){
initial = Color.RED;
}else if(e.getSource() == yellow){
initial = Color.YELLOW;
}else if(e.getSource() == thin){
stroke = new BasicStroke(1);
}else if(e.getSource() == medium){
stroke = new BasicStroke(5);
}else if(e.getSource() == thick){
stroke = new BasicStroke(10);
}else if(e.getSource() == erase){
initial = Color.WHITE;
stroke = new BasicStroke(15);
}
//repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
int x1, y1, x2, y2;
for (Segment segment : segments) {
g2.setColor(segment.color);
g2.setStroke(segment.stroke);
for (int p = 0; p < segment.points.size() - 1; p++) {
x1 = segment.points.get(p).x;
y1 = segment.points.get(p).y;
x2 = segment.points.get(p + 1).x;
y2 = segment.points.get(p + 1).y;
g2.drawLine(x1, y1, x2, y2);
}
}
g2.dispose();
}
public static void main(String []args){
SimplePaint s = new SimplePaint();
s.setVisible(true);
}
}

To fix your issue, you need to add to the end of the List and not the beginning:
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
segments.add(new Segment());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
segments.get(segments.size() - 1).points.add(e.getPoint());
repaint();
}
});
Additionally, the second mouseDragged() implementation appears redundant, if you remove it, it still functions as expected.
// Can be removed
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
Also, you should really use a JComponent or JPanel to paint your sketch, #Override paintComponent() as opposed to paint() with this approach. This will help (or should completely) remove the flickering you see. Coupled with a javax.swing.Timer to repaint() as opposed to dragging which could update extremely (and unnecessarily) quickly.
Finally, you should ensure your GUI is running on the event dispatch thread using SwingUtilities.invokeLater(Runnable doRun), since Swing objects are not thread safe.
e.g.
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
SimplePaint s = new SimplePaint();
s.setVisible(true);
}
});
}

Related

Neither ActionListener nor MouseListener added to JButton works for setting color in PaintComponent in JPanel

I am creating a Java program to simulate Microsoft Paint in Windows 95. There is a color palette in the bottom. Clicking any color in the palette will change the color of the painting tool like pencil. I tried to use Graphics2D to set each color for the tool according to the button clicked in the palette. I tried to add ActionListener to JButton representing the color button in the palette and then changed it to MouseListener. But my code does not work for this purpose. I am not sure whether this occurs because ActionListener/MouseListener is included in a for loop, which is then included in MouseMotionListener. Neither ActionListener nor MouseListener added to JButton works for setting color in PaintComponent in JPanel in this code. Is there a better way to rewrite this code?
This is a screenshot of Paint simulation that I created:
enter image description here
My code is as follows:
paintOpen = new JFrame();
paintCanvasPanel = new JPanel() {
private static final long serialVersionUID = 1L;
public void paintComponent(Graphics g) {
this.addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
Graphics2D g = (Graphics2D) getGraphics();
g.drawLine(e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen());
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setStroke(new BasicStroke(WIDTH, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL));
for (int i = 0; i < 28; i++) {
//Neither ActionListener nor MouseListener works
paintColorButton[i].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
for (int j = 0; j < 28; j++) {
g.setColor(paintPaletteColor[j]);
}
}
});
}
}
}
public void mouseMoved(MouseEvent e) {
}
});
}
};
paintScrollPane = new JScrollPane(paintCanvasPanel);
paintScrollPane.setBackground(white);
paintScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
paintScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
paintOpen.getContentPane().add(paintScrollPane);
paintOpen.getContentPane().setBackground(white);
paintOpen.setAlwaysOnTop(true);
paintOpen.setBounds(200, 0, 420, 600);
paintOpen.setExtendedState(JFrame.MAXIMIZED_BOTH);
paintOpen.setIconImage(paintIcon.getImage());
paintOpen.setTitle("untitled - Paint");
paintPalettePanel = new JPanel();
paintColorButton = new JButton[28];
for (int i = 0; i < 28; i++) {
paintColorButton[i] = new JButton();
paintColorButton[i].setBackground(paintPaletteColor[i]);
paintPalettePanel.add(paintColorButton[i]);
}
paintOpen.add(paintPalettePanel, BorderLayout.SOUTH);
}
I tried to change ActionListener to MouseListener, but the color still cannot be changed.
for (int i = 0; i < 28; i++) {
paintColorButton[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int j = 0; j < 28; j++) {
g.setColor(paintPaletteColor[j]);
}
}
});
}
I'm not sure if this is of any help, but I took your code, put things in order, removed the redundant and added the missing. I can only recommend that you take a closer look at things. Swing is event oriented and you have to remember when the mouse was moved or a button was pressed in order to be able to process this information in the paintComponent event. In this case, repaint() must be called in mouseDragged so that the result is visible.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PaintPanel extends JPanel implements MouseMotionListener, ActionListener{
private Color[] paintPaletteColor = { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW };
private Color drawColor = Color.BLACK;
private MouseEvent e;
public static void main(String[] args) {
new PaintPanel();
}
public PaintPanel() {
addMouseMotionListener(this);
setPreferredSize(new Dimension(1024, 768));
JScrollPane paintScrollPane = new JScrollPane(this);
paintScrollPane.setBackground(Color.WHITE);
paintScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
paintScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
paintScrollPane.setBackground(Color.white);
JPanel paintPalettePanel = new JPanel();
// Add a button for each color defined in paintPaletteColor.
// Add more colors there for additional buttons.
for (int i = 0; i < paintPaletteColor.length; i++) {
JButton button = new JButton();
button.setBackground(paintPaletteColor[i]);
button.addActionListener(this);
paintPalettePanel.add(button);
}
JFrame paintOpen = new JFrame();
paintOpen.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
paintOpen.add(paintScrollPane);
paintOpen.add(paintPalettePanel, BorderLayout.SOUTH);
paintOpen.setIconImage(new ImageIcon("Icon.png").getImage());
paintOpen.setTitle("untitled - Paint");
paintOpen.pack();
paintOpen.setLocationRelativeTo(null);
paintOpen.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
// A button was clicked - remember its color.
drawColor = ((JButton)e.getSource()).getBackground();
}
#Override
public void mouseDragged(MouseEvent e) {
// The mouse was dragged - remember the new position and repaint the panel.
this.e = e;
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
//
}
#Override
public void paintComponent(Graphics g) {
// triggered `repaint`, so let's go.
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(4, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL));
g2d.setColor(drawColor);
// mouse dragged ?
if(e != null) g2d.drawLine(e.getX(), e.getY(), e.getX(), e.getY());
}
}

Simple Paint Program - new line is not being recognized

I have created a simple paint program. All the functionalities are working, but when I go to create a new line, the program does not recognize that it is creating a new line, and instead just creates one huge line. The code will compile if you run it. Any help would be greatly appreciated. Thank you!
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.swing.*;
public class SimplePaint extends JFrame implements ActionListener{
private static final long serialVersionUID = 1L;
JButton action = new JButton();
JButton red = new JButton();
JButton blue = new JButton();
JButton yellow = new JButton();
Color initial = Color.MAGENTA;
JButton thin = new JButton();
JButton medium = new JButton();
JButton thick = new JButton();
Stroke stroke = new BasicStroke(3);
private static ArrayList<Point> points = new ArrayList<Point>();
JButton erase = new JButton();
JButton drawing = new JButton();
Point start = null;
Point end = null;
Line2D draw = new Line2D.Float();
JPanel panel = new JPanel();
public SimplePaint(){
getContentPane().add(panel);
setSize(450, 450);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
design();
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
//points.clear();
points.add(e.getPoint());
// repaint();
}
public void mouseReleased(MouseEvent e){
points.add(e.getPoint());
// points.clear();
//repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e){
points.add(e.getPoint());
repaint();
}
});
blue.addActionListener(this);
red.addActionListener(this);
yellow.addActionListener(this);
thin.addActionListener(this);
medium.addActionListener(this);
thick.addActionListener(this);
erase.addActionListener(this);
drawing.addActionListener(this);
}
public void design(){
panel.setBackground(Color.BLACK);
blue.setBackground(Color.BLUE);
blue.setPreferredSize(new Dimension(50, 25));
panel.add(blue);
red.setBackground(Color.RED);
red.setPreferredSize(new Dimension(50, 25));
panel.add(red);
yellow.setBackground(Color.yellow);
yellow.setPreferredSize(new Dimension(50, 25));
panel.add(yellow);
thin.setText("Thin");
panel.add(thin);
medium.setText("Medium");
panel.add(medium);
thick.setText("Thick");
panel.add(thick);
erase.setText("Erase");
panel.add(erase);
drawing.setText("Draw");
panel.add(drawing);
}
public void actionPerformed(ActionEvent e){
if(e.getSource() == blue){
initial = Color.BLUE;
}else if(e.getSource() == red){
initial = Color.RED;
}else if(e.getSource() == yellow){
initial = Color.YELLOW;
}else if(e.getSource() == thin){
stroke = new BasicStroke(1);
}else if(e.getSource() == medium){
stroke = new BasicStroke(5);
}else if(e.getSource() == thick){
stroke = new BasicStroke(10);
}else if(e.getSource() == erase){
initial = Color.BLACK;
}
//repaint();
}
#Override
public void paint(Graphics g){
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(initial);
g2.setStroke(stroke);
if(points != null && points.size() > 1){
for(int p = 0; p < points.size() - 1; p++){
int x1 = points.get(p).x;
int y1 = points.get(p).y;
int x2 = points.get(p + 1).x;
int y2 = points.get(p + 1).y;
g2.drawLine(x1, y1, x2, y2);
}
}
g2.dispose();
}
public static void main(String []args){
SimplePaint s =new SimplePaint();
s.setVisible(true);
}
}
It looks to me as though you need to be storing the line segments separately rather than in one list of points. To do that you need to define a class to hold them and store a list of segments rather than points.
private class Segment {
private final List<Point> points = new ArrayList<Point>();
private final Color color = initial;
private final Stroke stroke = SimplePaint.this.stroke;
}
private final List<Segment> segments = new ArrayList<>();
Then create a new segment each time the mouse is pressed and add the point to the current segment each time the mouse is dragged:
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
segments.add(0, new Segment());
segments.get(0).points.add(e.getPoint());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
segments.get(0).points.add(e.getPoint());
repaint();
}
});
You don't need to do anything when the mouse is released as the point will already have been added on drag. You can delete that listener.
Your paint method then needs to iterate through all segments:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
for (Segment segment : segments) {
g2.setColor(segment.color);
g2.setStroke(segment.stroke);
for (int p = 0; p < segment.points.size() - 1; p++) {
Point p1 = segment.points.get(p);
Point p2 = segment.points.get(p + 1);
g2.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
g2.dispose();
}
I've removed your check to ignore lines with less than two points: the for loop will skip those anyway so it's redundant.
Inserting the new segments at index 0 makes the code to add points simple but has the disadvantage that lines drawn first overwrite later lines. Simple solution would be to use a Deque and peekLast rather than List and get(0).
There are lots of other improvements (particularly performance) you can make but I've tried those changes myself and they work fine.

How can I prevent shapes from changing on mouseclick?

I am having a problem with my code, if I click on rectangle and do the mouse clicks on the screen it will show the shape and it works fine.. but if I clicked on the circle after that, all the rec
tangles that have been stored stays on same location but changes to circle. how can I prevent the shapes that have been stored from changing?
First Class:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class MouseClick implements ActionListener{
private static int x,y;
private static DrawingObjects object = new DrawingObjects();
JPanel panel = new JPanel();
JFrame frame = new JFrame("MouseClick");
MouseClick(){
dObjects();
}
void dObjects() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(2,2));
frame.add(object);
frame.add(panel);
panel.setBackground(Color.WHITE);
panel.setSize(10, 300);
panel.setLocation(100, 200);
panel.setLayout(new GridLayout(1,2));
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setSize(400, 400);
object.addMouseListener(new AL());
Button rect = new Button("Rectangle");
Button oval = new Button("Circle");
panel.add(rect);
panel.add(oval);
rect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
object.setType(1);
}
});
oval.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
object.setType(2);
}
}); }
public static void main(String[] args){
new MouseClick();
}
static class AL extends MouseAdapter{
public void mouseClicked (MouseEvent e){
x = e.getX();
y = e.getY();
object.drawing(x, y);
}
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
Second Class:
import javax.swing.*;
import javafx.scene.input.MouseEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.*;
public class DrawingObjects extends JPanel{
private ArrayList<Point> points = new ArrayList<>();
public int shapetype ;
public void drawing(int x, int y){
points.add(new Point(x, y));
repaint();
}
public void setType(int choice){
if(choice==1){
shapetype = 1;
}
else if (choice ==2){
shapetype = 2;
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
if(shapetype == 1){
for(Point p : points){
g.fillRect(p.x, p.y, 60, 20);
g.setColor(Color.GREEN);
repaint();
}
}
else if (shapetype == 2){
for(Point p : points){
g.fillOval(p.x, p.y, 20, 20);
g.setColor(Color.RED);
repaint();
}
}
}
}
The problem occurs because the shapetype is not stored along with the points on which the shapes are drawn. As a result, within the paintComponent method, when all shapes in locations stored in points array get redrawn, they use the current value of shapetype. Not the value of shapetype when the shape was created for the first time.
A simple (yet not the best) solution, with minimum code change would be to store the shapetype as follows.
In DrawingObjects class, add another array to store the shapetype.
private ArrayList<Integer> shapeTypes = new ArrayList<>();
Update the drawing method as follows to store the current shapetype along with the point.
public void drawing(int x, int y) {
points.add(new Point(x, y));
shapeTypes.add(shapetype);
repaint();
}
Refer the stored shapetype when repainting the shapes as follows.
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i = 0; i < points.size(); i++) {
Point p = points.get(i);
if (shapeTypes.get(i) == 1) {
g.fillRect(p.x, p.y, 60, 20);
g.setColor(Color.GREEN);
repaint();
} else if (shapeTypes.get(i) == 2) {
g.fillOval(p.x, p.y, 20, 20);
g.setColor(Color.RED);
repaint();
}
}
}
A better design would be to create a separate class with the capability to store the location as well as the shape type with the implementation on how it should be painted.

Java Code: Creating a Draw app

i'm trying to create a small drawing tool in java. I want the color the user is drawing with to change when they select a button. I tried to set up my buttons to do such. But when I run the app and select a button the color does not change. How can I fix this?
myJPanel.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class myJPanel extends JPanel implements MouseMotionListener, ActionListener
{
JButton red, blue, yellow, eraser;
JPanel p1;
Graphics gg;
public myJPanel()
{
setBackground(Color.white);
setLayout(new BorderLayout());
p1 = new JPanel();
p1.setLayout(new GridLayout(3,3));
red = new JButton("Red");
blue = new JButton("Blue");
yellow = new JButton("Yellow");
eraser = new JButton("Eraser");
p1.add(red);
p1.add(blue);
p1.add(yellow);
p1.add(eraser);
add(p1,"South");
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent evt)
{
}
public void mouseDragged(MouseEvent evt)
{
Point pt = evt.getPoint();
int x = pt.x;
int y = pt.y;
Graphics gg = getGraphics();
gg.setColor(Color.GREEN);
gg.fillRect(x, y, 5, 5);
}
#Override
public void actionPerformed(ActionEvent event)
{
Object obj = event.getSource();
String choice = event.getActionCommand();
if (obj == red) {
gg.setColor(Color.red);
}
if (obj == blue) {
gg.setColor(Color.blue);
}
if (obj == yellow) {
gg.setColor(Color.yellow);
}
if (obj == eraser) {
gg.setColor(Color.white);
}
}
}
You use a graphics that is not used to paint.
Whatever, don't draw like this, override paintComponent method to make it draw what you like, and call repaintwhen you need the drawing to be made:
public class myJPanel extends JPanel implements MouseMotionListener, ActionListener
{
JButton red, blue, yellow, eraser;
JPanel p1;
Color currentColor;
int x, y;
public myJPanel() {
setBackground(Color.white);
setLayout(new BorderLayout());
p1 = new JPanel();
p1.setLayout(new GridLayout(3,3));
yellow = new JButton("Yellow");
eraser = new JButton("Eraser");
p1.add(yellow);
p1.add(eraser);
add(p1,"South");
addMouseMotionListener(this);
}
public void paintComponent(Graphics g) { // draw something on request
g.setColor(currentColor);
g.fillRect(x, y, 5, 5);
}
public void mouseDragged(MouseEvent evt)
{
Point pt = evt.getPoint();
x = pt.x;
y = pt.y;
repaint(); // a new point to draw, please call me back...
}
#Override
public void actionPerformed(ActionEvent event) {
Object obj = event.getSource();
String choice = event.getActionCommand();
if (obj == yellow) {
currentColor = Color.yellow);
}
if (obj == eraser) {
currentColor = Color.white);
}
}
}

How do I clear my Jpanel but keep the grid lines?

I'm drawing lines on a JPanel using a paint component and graphics 2D, but the background of the JPanel is set to a grid which is drawn when the user enters some dimensions. How do I clear the lines drawn on the JPanel when a button is clicked but regenerate a fresh panel again with the grid lines drawn? With the action event method for the clear button, I've tried using repaint(), removeAll() and creating a new instance of the JPanel but none of that seems to work.
Here is the code for the class with the main Panel and button functions:
package floorplan;
/**
*
* #author xodkx
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
public class FloorPlan extends JFrame
{
private JPanel backPanel = new JPanel();
private JPanel toolsPanel = new JPanel();
private JFrame chooseFurniture;
private JFrame chooseFixture;
private JFrame chooseFramework;
private JButton furnitureButton = new JButton();
private JButton fixturesButton = new JButton();
private JButton frameworkButton = new JButton();
private JButton deleteButton = new JButton();
private JButton saveButton = new JButton();
private JButton clearButton = new JButton();
private JButton closeButton = new JButton();
private JRadioButton wall = new JRadioButton("Wall");
private JRadioButton door = new JRadioButton("Door");
private JRadioButton window = new JRadioButton("Window");
Floor floor = new Floor();
public FloorPlan()
{
super("Floor Plan Generator");
createWindow();
buttonFunctions();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
private void createWindow()
{
backPanel.setLayout(new BorderLayout());
backPanel.setBorder(BorderFactory.createEmptyBorder(200, 200, 200, 200));
GridLayout panelLayout = new GridLayout();
frameworkButton.setText("Framework");
fixturesButton.setText("Fixtures");
furnitureButton.setText("Furniture");
deleteButton.setText("Delete");
saveButton.setText("Save");
clearButton.setText("Clear");
add(backPanel, BorderLayout.CENTER);
backPanel.add(toolsPanel, BorderLayout.NORTH);
backPanel.add(floor, BorderLayout.CENTER);
backPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
toolsPanel.add(frameworkButton);
toolsPanel.add(fixturesButton);
toolsPanel.add(furnitureButton);
toolsPanel.add(deleteButton);
toolsPanel.add(saveButton);
toolsPanel.add(clearButton);
add(backPanel);
}
private void buttonFunctions()
{
frameworkButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent e)
{
chooseFramework = new JFrame("Pick A Framework");
chooseFramework.setSize(250,250);
chooseFramework.setLayout(new GridLayout(4,1));
chooseFramework.add(wall);
chooseFramework.add(door);
chooseFramework.add(window);
chooseFramework.add(closeButton);
closeButton.setText("Close");
wall.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
floor.setFramework(Framework.WALL);
}});
door.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
floor.setColor(Color.RED);
floor.setFramework(Framework.DOOR);
}});
window.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
floor.setColor(Color.BLUE);
floor.setFramework(Framework.WALL);
}});
closeButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
chooseFramework.setVisible(false);
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
chooseFramework.setVisible(true);
}
});
furnitureButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent e)
{
chooseFurniture = new JFrame("Pick Furniture to add");
chooseFurniture.setSize(250,250);
chooseFurniture.setLayout(new GridLayout(4,1));
chooseFurniture.add(closeButton);
closeButton.setText("Close");
closeButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
chooseFurniture.setVisible(false);
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
chooseFurniture.setVisible(true);
}
});
fixturesButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent e)
{
chooseFixture = new JFrame("Pick Furniture to add");
chooseFixture.setSize(250,250);
chooseFixture.setLayout(new GridLayout(4,1));
chooseFixture.add(closeButton);
closeButton.setText("Close");
closeButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
chooseFixture.setVisible(false);
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
chooseFixture.setVisible(true);
}
});
**clearButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent e)
{
**//THIS IS WHERE I WANT TO CLEAR THE JPANEL WHEN THIS BUTTON IS CLICKED**
}
});**
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
FloorPlan floorPlan = new FloorPlan();
}
});
}
}
Here is the class that does all the graphics stuff and draws onto the JPanel
package floorplan;
/**
*
* #author xodkx
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.event.MouseListener;
public class Floor extends JPanel implements MouseListener, MouseMotionListener
{
private static final int WIDTH = Integer.parseInt(JOptionPane.showInputDialog("Please
enter the width of your room"));
private static final int LENGTH = Integer.parseInt(JOptionPane.showInputDialog("Please
enter the width of your room"));
private static final Color BACKGROUND = Color.WHITE;
private static final Color INITIAL_COLOUR = Color.BLACK;
private static final Framework INITIAL_FRAMEWORK = Framework.WALL;
private MouseState state = MouseState.IDLE;
private Framework frameworkType = INITIAL_FRAMEWORK;
private Color colour = INITIAL_COLOUR;
private Point start = null;
private Point end = null;
private Point startpt = null;
private Point endpt = null;
private BufferedImage bufImage = null;
public Floor()
{
setPreferredSize(new Dimension(LENGTH,WIDTH));
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder (Color.black, 5));
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void setColor(Color color)
{
colour = color;
}
public void setFramework(Framework framework)
{
frameworkType = framework;
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
if(bufImage == null)
{
int h = this.getHeight();
int w = this.getWidth();
bufImage = (BufferedImage)this.createImage(h,w);
Graphics2D gc = bufImage.createGraphics();
gc.setColor(BACKGROUND);
gc.fillRect(0, 0, w, h);
}
g2.drawImage(bufImage,null,0,0);
drawGrid(g2);
if(state == MouseState.DRAGGING)
{
createComponent(g2);
}
}
public void drawGrid(Graphics g2)
{
int gridDivisions = 20;
int divisionSize = WIDTH/gridDivisions;
int grid = WIDTH*LENGTH;
g2.setColor(Color.lightGray);
for(int i=1; i<grid; i++)
{
int x = i * divisionSize;
g2.drawLine(x,0,x,getSize().height);
}
for(int i=1; i<grid; i++)
{
int y = i*divisionSize;
g2.drawLine(0,y,getSize().width,y);
}
}
public void createComponent(Graphics2D g2)
{
g2.setColor(colour);
switch (frameworkType)
{
case WALL:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
case DOOR:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
case WINDOW:
g2.setStroke(new BasicStroke(5));
g2.drawLine(start.x, start.y, end.x,end.y);
break;
default:
g2.drawString("test", 10, 20);
break;
}
}
#Override
public void mousePressed(MouseEvent e)
{
state = MouseState.DRAGGING;
start = e.getPoint();
end = start;
}
#Override
public void mouseDragged(MouseEvent e)
{
state = MouseState.DRAGGING;
end = e.getPoint();
this.repaint();
}
#Override
public void mouseReleased(MouseEvent e)
{
end = e.getPoint();
if(state == MouseState.DRAGGING)
{
state = MouseState.IDLE;
createComponent(bufImage.createGraphics());
this.repaint();
}
}
#Override
public void mouseClicked(MouseEvent e)
{
}
#Override
public void mouseEntered(MouseEvent e)
{
}
#Override
public void mouseExited(MouseEvent e)
{
}
#Override
public void mouseMoved(MouseEvent e)
{
}
}
It is not clear exactly how do you want to incorporate the logic of displaying the grid. Here is an example how to toggle it just to give you the idea. In Floor class add boolean flag that controls whether the grid is displayed or not. Then in Floor.paintComponent() draw grid based on the value of this boolean flag. Changing the flag's value should trigger a repaint. Then, change the value of this flag from FloorPlan class, in response to an action or some other program logic. Here is a simple implementation that toggles grid when clear button is clicked :
Floor class:
private boolean displayGrid = true;
public boolean isDisplayGrid() {
return displayGrid;
}
public void setDisplayGrid(boolean displayGrid) {
this.displayGrid = displayGrid;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
...
if (displayGrid)
drawGrid(g2);
}
FloorPlan class:
clearButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
floor.setDisplayGrid(!floor.isDisplayGrid());
}
});
EDIT:
Seems that I totally misinterpreted your question. If I understand correctly you want to clear the drawings upon a button click. Looks like all the drawings are done on the bufImage in the Floor class. Simply reset this image, ie:
Floor class:
public void clear() {
bufImage.flush();
bufImage = null;
repaint();
}
FloorPlan class:
clearButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
floor.clear();
}
});
You could use a for loop with panel.remove the buttons (instead of panel.add)

Categories

Resources