0
\$\begingroup\$

(Sorry this is a repeat post, I hadn't logged in on my initial question and am unable to respond)

I currently have a working code for a simple paint application but it is all in one file and very long. I'm unsure of how to break the code up into smaller pieces and create classes with them. I tried to research Java classes but I'm not coming up with anything comprehensive. My main issue is figuring out how to break up the code I already have, I'm not sure what should be grouped together or how to define and call them.

package paint;

import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.Image;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import javafx.scene.shape.Circle;
import javafx.scene.control.Slider;


public class Paint extends Application {

@Override
public void start(Stage primaryStage) {

//Create menu buttons
ToggleButton drawbtn = new ToggleButton("Draw");
ToggleButton linebtn = new ToggleButton("Line");
ToggleButton erasebtn = new ToggleButton("Eraser");
ToggleButton recbtn = new ToggleButton("Rectangle");
ToggleButton circbtn = new ToggleButton("Circle");

ToggleButton[] toolsArr = {drawbtn, linebtn, erasebtn, recbtn, circbtn};

ToggleGroup tools = new ToggleGroup();

for (ToggleButton tool : toolsArr) {
tool.setMinWidth(90);
tool.setToggleGroup(tools);
}
//Initializing Color Picker and Color fills selections  
ColorPicker cpLine = new ColorPicker(Color.BLACK);
ColorPicker cpFill = new ColorPicker(Color.TRANSPARENT);

//Creating label names      
Label line_color = new Label("Line Color");
Label fill_color = new Label("Fill Color");

//Creating line width selector       
Slider slider = new Slider(1, 25, 3);
slider.setShowTickLabels(true);
slider.setShowTickMarks(true);

Button saveas = new Button("Save As");
Button open = new Button("Open");

//Menu with buttons
VBox btns = new VBox(10);
btns.getChildren().addAll(drawbtn, linebtn, line_color, cpLine, fill_color,       cpFill, open, saveas, erasebtn, recbtn, circbtn, slider);
btns.setPadding(new Insets(5));
btns.setPrefWidth(100);

//Setting up the blank canvas
Canvas canvas = new Canvas(1080, 790);
GraphicsContext gc;
gc = canvas.getGraphicsContext2D();
gc.setLineWidth(1);

Line line = new Line();
Rectangle rec = new Rectangle();
Circle circ = new Circle();

//Was the mouse button pressed on the canvas..                  
canvas.setOnMousePressed(e->{
if(drawbtn.isSelected()) {          //While the draw button is selected
    gc.setStroke(cpLine.getValue());
    gc.beginPath();
    gc.lineTo(e.getX(), e.getY());
}
else if(linebtn.isSelected()) {     //While the line button is selected
    gc.setStroke(cpLine.getValue());
    line.setStartX(e.getX());       //Start line at this x value
    line.setStartY(e.getY());       //Start line at this y value
}
else if(erasebtn.isSelected()) {    //While the eraser button is selected
    double lineWidth = gc.getLineWidth();
    gc.clearRect(e.getX() - lineWidth / 2, e.getY() - lineWidth / 2, lineWidth, lineWidth);
}
else if(recbtn.isSelected()) {      //While the rectangle button is selected
    gc.setStroke(cpLine.getValue());
    gc.setFill(cpFill.getValue());  //Fill the rectangle with fill color
    rec.setX(e.getX());             //Start rectangle at this x
    rec.setY(e.getY());             //Start rectangle at this y
}
else if(circbtn.isSelected()) {
    gc.setStroke(cpLine.getValue());
    gc.setFill(cpFill.getValue());
    circ.setCenterX(e.getX());
    circ.setCenterY(e.getY());
}
});

//Draws and creates line based on mouse clicks    
canvas.setOnMouseDragged(e->{
if(drawbtn.isSelected()) {
    gc.lineTo(e.getX(), e.getY());
    gc.stroke();
}
//Erases areas where the mouse is clicked and dragged over
else if(erasebtn.isSelected()){
    double lineWidth = gc.getLineWidth();
    gc.clearRect(e.getX() - lineWidth / 2, e.getY() - lineWidth / 2, lineWidth, lineWidth);
}
});

//Was the mouse button released...
canvas.setOnMouseReleased(e->{
if(drawbtn.isSelected()) {      //while the draw button was selcted
    gc.lineTo(e.getX(), e.getY());
    gc.stroke();
    gc.closePath();
}
else if(linebtn.isSelected()) { //while the line button was selcted
    line.setEndX(e.getX());
    line.setEndY(e.getY());
    gc.strokeLine(line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY());
}
else if(erasebtn.isSelected()) {    //while the erase button was selcted
    double lineWidth = gc.getLineWidth();
    gc.clearRect(e.getX() - lineWidth / 2, e.getY() - lineWidth / 2, lineWidth, lineWidth);
}
else if(recbtn.isSelected()) {      //while the rectangle button was selcted
    rec.setWidth(Math.abs((e.getX() - rec.getX())));
    rec.setHeight(Math.abs((e.getY() - rec.getY())));
//If X value of rectangle is greater than the X value of e, make e = rectangle value
    if(rec.getX() > e.getX()) {
        rec.setX(e.getX());
    }
//If Y value of rectangle is greater than the Y value of e, make e = rectangle value
    if(rec.getY() > e.getY()) {
        rec.setY(e.getY());
    }
//Filling the rectangle with color
    gc.fillRect(rec.getX(), rec.getY(), rec.getWidth(), rec.getHeight());
    gc.strokeRect(rec.getX(), rec.getY(), rec.getWidth(), rec.getHeight());               
}
else if(circbtn.isSelected()) {
    circ.setRadius((Math.abs(e.getX() - circ.getCenterX()) + Math.abs(e.getY() - circ.getCenterY())) / 2);

    if(circ.getCenterX() > e.getX()) {
        circ.setCenterX(e.getX());
    }
    if(circ.getCenterY() > e.getY()) {
        circ.setCenterY(e.getY());
    }

    gc.fillOval(circ.getCenterX(), circ.getCenterY(), circ.getRadius(), circ.getRadius());
    gc.strokeOval(circ.getCenterX(), circ.getCenterY(), circ.getRadius(), circ.getRadius());
}
});

//Setting up the color picker for line/drawing
cpLine.setOnAction(e->{
    gc.setStroke(cpLine.getValue());
});
//Setting up the color fill
cpFill.setOnAction(e->{
    gc.setFill(cpFill.getValue());
});
//Setting up the width slider
slider.valueProperty().addListener(e->{
double width = slider.getValue();
gc.setLineWidth(width);
});

//Open a file from desktop
open.setOnAction((e)->{
FileChooser openFile = new FileChooser();
openFile.setTitle("Open File");
File file = openFile.showOpenDialog(primaryStage);
if (file != null) {
    try {
        InputStream io = new FileInputStream(file);
        Image img = new Image(io);
        gc.drawImage(img, 0, 0);
    } catch (IOException ex) {
        System.out.println("Error!");
    }
}
});

//Save Canvas
saveas.setOnAction((e)->{
FileChooser savefile = new FileChooser();
savefile.setTitle("Save File");
File file = savefile.showSaveDialog(primaryStage);
if (file != null) {
    try {
        WritableImage writableImage = new WritableImage(1080, 790);
        canvas.snapshot(null, writableImage);
        RenderedImage renderedImage = SwingFXUtils.fromFXImage(writableImage, null);
        ImageIO.write(renderedImage, "png", file);
    } catch (IOException ex) {
        System.out.println("Error!");
    }
}

});

BorderPane pane = new BorderPane();
pane.setRight(btns);
pane.setCenter(canvas);

Scene scene = new Scene(pane, 1200, 800);   //Sets size of window
primaryStage.setTitle("Paint");
primaryStage.setScene(scene);
primaryStage.show();
}

//Launch Program
public static void main(String[] args) {
launch(args);
}
}
\$\endgroup\$
1
\$\begingroup\$

1) Create PrimaryStage class that will include state of the stage:

    public class PrimaryStage {
        private Stage stage;
        private List<ToggleButton> buttons;
        private ToggleGroup tools;
        private ColorPicker cpLine;
        private ColorPicker cpFill;
        private Label lineColor;
        private Label fillColor;
        private Slider slider;
        private Button saveAsBtn;
        private Button openBtn;
        private VBox buttons;
        private Canvas canvas;
        private GraphicsContext gc;
        private Line line = new Line();
        private Rectangle rec = new Rectangle();
        private Circle circ = new Circle();
        private BorderPane pane;
        private Scene scene;

        public PrimaryStage(Stage stage) {
            super();
            this.stage = stage;
            //initialization code here
            //Create menu buttons
            ToggleButton drawbtn = new ToggleButton("Draw");
            // ... initialize other components
            // don't call stage.show() yet.

            //initialize button handlers
            initOpenButton();
            // ... continue for other buttons
        }

        private void initOpenButton() {
        // ... init button handlers here ...
            openBtn.setOnAction((e)->{
                FileChooser openFile = new FileChooser();
                openFile.setTitle("Open File");
                File file = openFile.showOpenDialog(primaryStage);
                if (file != null) {
                    try {
                        InputStream io = new FileInputStream(file);
                        Image img = new Image(io);
                        gc.drawImage(img, 0, 0);
                    } catch (IOException ex) {
                        System.out.println("Error!");
                    }
                }
            });
        }

        public void show() {
            this.stage.show();
        } 
    } 

Then

public class Paint extends Application {
    @Override
    public void start(Stage stage) {
         PrimaryStage primaryStage = new PrimaryStage(stage);
         primaryStage.show();
    }
    public static void main(String[] args) {
         launch(args);
    }
}

At least it will add some readability to your code without breaking it. Buttons can be extracted in separate classes but there is no big reason to do this as handlers are highly coupled with other components of primary stage.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.