0

I completed my Java Homework, but it was all mushed into one main class (with a couple of private classes). I'm trying to make my code more elegant by having separate classes to handle things. I'm having trouble having the listener interact with the existing panels.

The main parts I'm looking at are in the Listener.java. The mouse click and action listener. I am able to get the name of the button that was clicked to trigger the listener, which is helpful, but I can't get it to interact with the "DrawBoard" panel that was added to the Panel panel.

I'm wondering what the best way to work this interaction is:

Window.java:

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Window extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = -8255319694373975038L;

    public static void main(String[] args){

        new Window();
    }


    public Window(){


        // Adds the custom panel
        Panel Panel = new Panel();
        this.add(Panel);


        // Basic Window Features
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(800,800);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }


}

Panel.java:

public class Panel extends JPanel{

    public Panel(){
        Button testButton = new Button("Test");
        DrawBoard drawBoard = new DrawBoard();
        Listener listener = new Listener();



        this.add(testButton);
        this.add(drawBoard);


    }
}

Button.java

import java.awt.Dimension;

import javax.swing.JButton;

public class Button extends JButton{


    public Button(String name) {
        this.setText(name);
        this.setName((String) name);
        buttonSettings();
    }

    private void buttonSettings(){
        Listener listener = new Listener();
        this.addActionListener(listener);

        int width = 200;
        int height = 50;
        Dimension dim = new Dimension(width,height);
        this.setPreferredSize(dim);
    }

}

DrawBoard.java

import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JPanel;

public class DrawBoard extends JPanel{

    public DrawBoard(){
        DrawBoardSettings();
    }

    private void DrawBoardSettings(){
        int width = 600;
        int height = 600;
        Dimension dim = new Dimension(width,height);
        this.setPreferredSize(dim);
        this.setBackground(Color.WHITE);
    }
}

Listener.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JComponent;

public class Listener implements ActionListener, MouseListener {

    @Override
    public void mouseClicked(MouseEvent e) {
        **// Draw a dot at the mouse location of the DrawBoard JPanel that was added by the Panel JPanel that was added by the Window JFrame**

    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String name = ((JComponent) e.getSource()).getName();
        **// Draw a rectangle on the DrawBoard JPanel that was added by the Panel JPanel that was added by the Window JFrame**
    }

}
Dan White
  • 27
  • 5

2 Answers2

0

Some thoughts here:

  • Currently you have several instances of that Listener class. That is probably not what you want.
  • Related to that: your code indicates that your Listener class should draw on some panel. If so ... that Listener somehow needs access to that panel.

One way to get there: you change your constructor to

private final Panel drawingBoard;
public Listener(Panel drawingBoard) { 
  this.drawingBoard = drawingBoard;
)

and then your actionPerformed() method has something to draw on.

The core thing to understand: you have to create a clear model (in your mind) about which components you have; and how they depend on each other. Because that drives your implementation; for example regarding the order in which you have to create your different objects. Given my example, you would need to first create a Panel object; so that you can then create a Listener for that Panel.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thank you. I just needed to make sure I was only initiating the class once and then having other classes call that first instance of it. – Dan White Dec 09 '16 at 18:09
0

Here is the code for my completed project. I think I made it much cleaner and only called "listener" and "drawBoard" once, which cleared up my problems:

Window.java:

import javax.swing.JFrame;


public class Window extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = -8255319694373975038L;

    // initiates the program
    public static void main(String[] args){

        new Window();
    }


    public Window(){


        // Adds the custom panel
        Panel Panel = new Panel();
        this.add(Panel);


        // Basic Window Features
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(800,800);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }


}

Panel.java:

import java.awt.FlowLayout;
import java.util.ArrayList;

import javax.swing.JPanel;

    public class Panel extends JPanel{

        /**
         * 
         */
        private static final long serialVersionUID = 5509155261502497671L;



        public Panel(){
            // This is the area where stuff will be drawn
            DrawBoard drawBoard = new DrawBoard();


            // This is the only instance of listener. Buttons now call this variable
            Listener listener = new Listener(drawBoard);


            // Invisible Overlay allows me to get mouse listener coordinates for drawing
            JPanel overlay = new JPanel();

            //gets rid of the padding on the invisible overlay layer;
            FlowLayout layout = (FlowLayout)overlay.getLayout();
            layout.setVgap(0);
            layout.setHgap(0);

            // The mouse listener is added to the overlay layer rather than the panel to ensure that X,Y coords match the drawboard panel underneath
            // I could not add the listener to the drawboard panel because the listener requires the drawboard panel to perform.
            overlay.addMouseListener(listener);
            overlay.addMouseMotionListener(listener);
            overlay.add(drawBoard);


            // Buttons that will appear on the top of the panel
            ArrayList<Button> TopButtons = new ArrayList<Button>();
            TopButtons.add(new Button("Blue", listener));
            TopButtons.add(new Button("Green", listener));
            TopButtons.add(new Button("Red", listener));
            TopButtons.add(new Button("Black", listener));


            // Buttons that will appear on the bottom of the pannel
            ArrayList<Button> BotButtons = new ArrayList<Button>();
            BotButtons.add(new Button("Small", listener));
            BotButtons.add(new Button("Medium", listener));
            BotButtons.add(new Button("Large", listener));
            BotButtons.add(new Button("Clear", listener));


            // Using for loops to clean up code a bit.
            for (int i = 0; i < TopButtons.size(); i++){
                this.add(TopButtons.get(i));
            }

            // add the overlay rather than the drawboard, to ensure that mouse functions work
            this.add(overlay);

            for (int i = 0; i < BotButtons.size(); i++){
                this.add(BotButtons.get(i));
            }
        }
    }

Button.java

import java.awt.Dimension;  
import javax.swing.JButton;

public class Button extends JButton{

    /**
     * 
     */
    private static final long serialVersionUID = -819700115106662958L;

    private final Listener listener;
    public Button(String name, Listener listener) {
        this.listener = listener;
        this.setText(name);
        this.setName((String) name);
        buttonSettings();
    }

    private void buttonSettings(){
        this.addActionListener(listener);
        int width = 150;
        int height = 50;
        Dimension dim = new Dimension(width,height);
        this.setPreferredSize(dim);
    }

}

DrawBoard.java:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;

public class DrawBoard extends JPanel{

    /**
     * 
     */
    private static final long serialVersionUID = 1368365222404381200L;


    // ArrayList will store all points drawn on the canvas
    public ArrayList<Point> points = new ArrayList<Point>();

    // Constructor initiates the settings for the board
    public DrawBoard(){
        DrawBoardSettings();

    }

    // Painting of the points happens here
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        // draws a point for every point in the "points" array.
        for (int i = 0; i < points.size(); i++){
            Point thisPoint = points.get(i);
            g.setColor(thisPoint.color);
            g.fillOval(thisPoint.x,thisPoint.y,thisPoint.size,thisPoint.size);
        }

    }

    private void DrawBoardSettings(){
        // Sets the preferred window size
        int width = 700;
        int height = 600;
        Dimension dim = new Dimension(width,height);
        this.setPreferredSize(dim);

        // background color and visibility
        this.setBackground(Color.WHITE);
        this.setVisible(true);
        this.setOpaque(true);
    }
}

Listener.java:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JComponent;

public class Listener implements ActionListener, MouseListener, MouseMotionListener {

    private final DrawBoard drawBoard;

    //sets default color and size
    private Color color;
    private int size;




    public Listener(DrawBoard drawBoard) { 
      this.drawBoard = drawBoard;

      this.color = Color.BLACK;
      this.size = 10;
    }


    // Contains settings for creating a new point
    private void drawPoint(MouseEvent e){
        Point point = new Point(e.getX(), e.getY(), this.color, this.size);
        drawBoard.points.add(point);
        drawBoard.repaint();
    }


    // Contains settings for all of the buttons
    private void setButton(String name){
        // Colors
        if (name == "Blue"){
            this.color = Color.BLUE;
        }
        if (name == "Red"){
            this.color = Color.RED;
        }
        if (name == "Green"){
            this.color = Color.GREEN;
        }
        if (name == "Black"){
            this.color = Color.BLACK;
        }

        // Sizes
        if (name == "Large"){
            this.size = 15;
        }
        if (name == "Medium"){
            this.size = 10;
        }
        if (name == "Small"){
            this.size = 5;
        }


        // Clear
        if (name == "Clear"){
            drawBoard.points.clear();
            drawBoard.repaint();
        }

    }




    // Draws a point when the mouse is pressed down
    @Override
    public void mousePressed(MouseEvent e) {
        drawPoint(e);

    }

    // Draws a point when the mouse is dragged (at every location it is dragged at)
    @Override
    public void mouseDragged(MouseEvent e) {
        drawPoint(e);
    }

    // Changes the settings of buttons
    @Override
    public void actionPerformed(ActionEvent e) {
        String name = ((JComponent) e.getSource()).getName();
        setButton(name);


    }



    //Unused Listeners
    @Override
    public void mouseClicked(MouseEvent e) {

    }
    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub

    }

}

Point.java

import java.awt.Color;

public class Point {

    protected int x, y, size;
    protected Color color;

    public Point(int x, int y, Color color, int size){

        this.x = x;
        this.y = y;
        this.color = color;
        this.size = size;
    }

}
Dan White
  • 27
  • 5