首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中的裸骨画家应用

Java中的裸骨画家应用
EN

Code Review用户
提问于 2016-06-08 12:15:43
回答 2查看 974关注 0票数 7

请参见下一次迭代:Java中的裸骨画家应用程序

我有一个小小的绘图程序:

PaintCanvas.java

代码语言:javascript
复制
package net.coderodde.javapaint;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;

/**
 * This class implements a GUI component for drawing.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.6 (Jun 8, 2016)
 */
public class PaintCanvas extends Canvas {

    /**
     * The actual image being drawn to.
     */
    private final BufferedImage image;

    /**
     * The graphics context of the above.
     */
    private final Graphics2D imageGraphics;

    public PaintCanvas(final int width, final int height) {
        super();
        super.setBounds(0, 0, width, height);

        this.image  = new BufferedImage(width, 
                                        height, 
                                        BufferedImage.TYPE_INT_RGB);
        this.imageGraphics = this.image.createGraphics();
        this.imageGraphics.setColor(Color.WHITE);
        this.imageGraphics.fillRect(0, 0, width, height);
        this.imageGraphics.setColor(Color.BLACK);

        final PaintCanvasMouseListener listener =
                new PaintCanvasMouseListener();

        this.addMouseListener(listener);
        this.addMouseMotionListener(listener);
    }

    @Override
    public void paint(final Graphics g) {
        update(g);
    }

    @Override
    public void update(final Graphics g) {
        g.drawImage(this.image, 0, 0, null);
    }

    private class PaintCanvasMouseListener 
    extends MouseAdapter implements MouseMotionListener  {

        @Override
        public void mouseClicked(final MouseEvent event) {
            processEvent(event);
        }

        @Override
        public void mouseDragged(final MouseEvent event) {
            processEvent(event);
        }

        private void processEvent(final MouseEvent event) {
            PaintCanvas.this.imageGraphics.fillOval(event.getX(), event.getY(), 5, 5);
            PaintCanvas.this.repaint();
        }
    }
}

App.java

代码语言:javascript
复制
package net.coderodde.javapaint;

import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;

/**
 * This class implements an application for simple drawing.
 * 
 * @author Rodion "rodde" Efremov
 * @version 1.6 (Jun 8, 2016)
 */
public class App {

    private final JFrame frame = new JFrame("JavaPaint");

    public App() {
        frame.getContentPane().add(new PaintCanvas(640, 480));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        setFrameLocationToCenter();
        frame.setVisible(true);
    }

    private void setFrameLocationToCenter() {
        final Dimension screenDimension = Toolkit.getDefaultToolkit()
                                                 .getScreenSize();
        final int screenWidth  = screenDimension.width;
        final int screenHeight = screenDimension.height;

        frame.setLocation((screenWidth - frame.getWidth()) / 2, 
                          (screenHeight - frame.getHeight()) / 2);
    }

    public static void main(final String... args) {
        final App app = new App();
    }
}

它使我得以画出以下杰作:

我最感兴趣的是关于内部的事情,但是你可以告诉我任何我想到的事情。

EN

回答 2

Code Review用户

回答已采纳

发布于 2016-06-08 13:15:57

几个注意事项:

  • 您不使用JavaFX有什么原因吗?见这个答案,为什么要使用它。
  • 由于我主要是重写您的代码,所以我将尽我所能解释在JavaFX:中实现应用程序的所有组件
    1. JavaFX应用程序中有几个层:应用程序、舞台、场景和画布。如果您想了解更多,我将让您自己做更多关于所有这些的阅读,但是这些是创建GUI的基本组件。
    2. 在画布中,我们添加事件处理程序来处理所有不同的鼠标事件。这些都是非常不言自明的,因为你的应用程序中也有它们。
    3. 现在我们必须处理画布上的实际绘画。同样,您的代码中也有类似的方法,所以我不需要深入讨论这个问题。

  • 用户体验小笑话:不要在屏幕中央启动程序。经常被看作是广告软件。

最终代码:

代码语言:javascript
复制
package javafx_drawoncanvas;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class JavaFX_DrawOnCanvas extends Application {

    @Override
    public void start(Stage primaryStage) {

        Canvas canvas = new Canvas(400, 400);
        final GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        initDraw(graphicsContext);

        canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, 
                new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {
                graphicsContext.beginPath();
                graphicsContext.moveTo(event.getX(), event.getY());
                graphicsContext.stroke();
            }
        });

        canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, 
                new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {
                graphicsContext.lineTo(event.getX(), event.getY());
                graphicsContext.stroke();
            }
        });

        canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, 
                new EventHandler<MouseEvent>(){

            @Override
            public void handle(MouseEvent event) {

            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(canvas);
        Scene scene = new Scene(root, 400, 400);
        primaryStage.setTitle("Paint");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void initDraw(GraphicsContext gc){
        double canvasWidth = gc.getCanvas().getWidth();
        double canvasHeight = gc.getCanvas().getHeight();

        gc.setFill(Color.LIGHTGRAY);
        gc.setStroke(Color.BLACK);
        gc.setLineWidth(5);

        gc.fill();
        gc.strokeRect(
                0,              //x of the upper left corner
                0,              //y of the upper left corner
                canvasWidth,    //width of the rectangle
                canvasHeight);  //height of the rectangle

        gc.setFill(Color.RED);
        gc.setStroke(Color.BLUE);
        gc.setLineWidth(1);    
    }

    public static void main(String... args) {
        launch(args);
    }

}
票数 10
EN

Code Review用户

发布于 2016-06-08 12:41:56

代码语言:javascript
复制
    this.imageGraphics.setColor(Color.WHITE);
    this.imageGraphics.fillRect(0, 0, width, height);
    this.imageGraphics.setColor(Color.BLACK);

可以将构造函数的这一部分移动到私有函数clearScreen中。

剩下的代码看起来很好。你可以对各种事情发表评论,比如

代码语言:javascript
复制
    frame.setLocation((screenWidth - frame.getWidth()) / 2, 
                      (screenHeight - frame.getHeight()) / 2);
  • 也许把这个(a - b) / 2放在一个单独的函数中.
代码语言:javascript
复制
    frame.getContentPane().add(new PaintCanvas(640, 480));

代码语言:javascript
复制
    PaintCanvas.this.imageGraphics.fillOval(event.getX(), event.getY(), 5, 5);

代码语言:javascript
复制
    private final JFrame frame = new JFrame("JavaPaint");
  • 把你的常量放在类的主题上,魔法字符串/数字是不好的.

但是你做的是一个快速的应用程序。在我看来,你花在编码质量上的时间是正确的。..。我不知道你在这上面花了多长时间,但基本上,这已经足够干净了。添加更多的特性,然后在重复的代码弹出时进行必要的清理。

票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/131422

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档