简体   繁体   English

在java中制作绘画应用程序的更简单方法?

[英]Easier way to make a paint application in java?

So basically I have some code I was working on a couple of days ago that is kind of like Paint, which allows you to essentially draw on the screen using the mouse.所以基本上我有一些我几天前正在处理的代码,有点像 Paint,它允许你基本上使用鼠标在屏幕上绘制。 I kind of discovered this property by accident, and I realized that it is really inefficient and i'm wondering if there is a more practical way to do this.我有点偶然地发现了这个属性,我意识到它确实效率低下,我想知道是否有更实用的方法来做到这一点。 There isn't really any reason to give all of my code, but here are the important parts没有任何理由提供我所有的代码,但这里是重要的部分

private static void createAndShowGui() {
    SimpleDraw mainPanel = new SimpleDraw();
    MenuBar.createMenuBar();
    JLabel label = new JLabel();
    label.setText("Drawing prototype 0.0.1");
     // label.setHorizontalTextPosition(JLabel.NORTH);
    label.setFont(new Font("Serif", Font.BOLD, 20));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(mainPanel);
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(),BoxLayout.PAGE_AXIS));
    frame.setVisible(true);
    frame.setJMenuBar(MenuBar.getMenuBar());
    frame.setBackground(Color.WHITE);
    frame.add(label);

The code block above sets up the jframe (the window)上面的代码块设置了 jframe(窗口)

 @Override
    public void mouseDragged(MouseEvent e)
    {
    // These console outputs are just so that I know what is happening
        System.out.println("Event: MOUSE_DRAG");
        System.out.println(e.getX());
        System.out.println(e.getY());
        System.out.println(e.getComponent());
        System.out.println(e.getWhen());
        System.out.println(e.getButton());
         MOUSE_X = e.getX() - 5;  //-5 so that the cursor represents the center of the square, not the top left corner.
         MOUSE_Y = e.getY() - 5;  //^
         rect = new Rectangle(MOUSE_X, MOUSE_Y, 10, 10 ); //This doesn't ever come into action.
         repaint();  

     }

The code above pretty much just sets the MOUSE_X and MOUSE_Y variables and the repaint();上面的代码几乎只是设置了 MOUSE_X 和 MOUSE_Y 变量以及 repaint(); method方法

@Override
    protected void paintComponent(Graphics g) {

    Graphics2D g2 = (Graphics2D) g;
    if (rect != null) {

        if (!colorChoice.equals("Default"))
        {
            g2.setColor(Color.BLACK);
        }

        switch(colorChoice) {

        case "GRAY":
            g2.setColor(Color.GRAY);
            break;
        case "CYAN":
            g2.setColor(Color.CYAN);
            break;
        case "BLUE":
            g2.setColor(Color.BLUE);
            break;
        case "RED":
            g2.setColor(Color.RED);
            break;
        case "PINK":
            g2.setColor(Color.PINK);
            break;
        case "YELLOW":
            g2.setColor(Color.YELLOW);
            break;
        case "GREEN":
            g2.setColor(Color.GREEN);
            break;
        case "PURPLE":
            g2.setColor(Color.MAGENTA);
            break;
        case "RESET":
            g2.setColor(Color.WHITE);
        case "WHITE":
            g2.setColor(Color.WHITE);

        }





        g2.fillRect(MOUSE_X, MOUSE_Y, 15, 15); 

        if (colorChoice.equals("RESET")) 
        resetColorOnCursor(); 

        }
    }

    public static void clearBoard()
    {
    tempColor = colorChoice;
    setColorChoice("RESET");
    frame.repaint();




    }


    public static void resetColorOnCursor()
    {
    setColorChoice(tempColor);
    }

This is the thing I came across accidentally.这是我偶然遇到的事情。 What I was trying to do when I found this out was basically make a square follow your cursor whenever you moved your mouse.当我发现这一点时,我试图做的基本上是在您移动鼠标时使一个正方形跟随您的光标。 But I forgot to type the code part paintComponent(g);但是我忘记输入代码部分paintComponent(g); , which turns this program into the thing that I originally intended. ,这将这个程序变成了我最初想要的东西。 The bottom parts of this are essentially how I would clear the board.这的底部部分基本上是我将如何清除板。 I'm 100% sure that this isn't the proper way to clear/reset a frame like this, but I couldn't find another way.我 100% 确定这不是清除/重置这样的框架的正确方法,但我找不到其他方法。 If anyone has any tips or better methods to use to do this properly I would be very appreciative.如果有人有任何提示或更好的方法来正确执行此操作,我将不胜感激。 Thanks!谢谢! :D :D

You're current approach is basically breaking the requirements of the paint chain, by not calling super.paintComponent .您当前的方法基本上是通过不调用super.paintComponent打破绘制链的要求。 The paintComponent method does a set of operations, which you are not taking over and which could result in some very weird paint artifacts which are difficult to replicate consistently. paintComponent方法执行一组操作,您不会接管这些操作,这可能会导致一些非常奇怪的绘制工件,这些工件难以一致地复制。

Graphics is a shared resource, so the Graphics context which was used to paint some other control will be the same which is used to paint your component, unless you are "cleaning" the context before hand, what was previously painted to the context will remain (which is why you code currently "seems" to work). Graphics是共享资源,因此用于绘制其他控件的Graphics上下文将与用于绘制组件的相同,除非您事先“清理”上下文,否则先前绘制到上下文的内容将保留(这就是为什么您当前的代码“似乎”有效)。

Instead, you should use a MouseListener to define a anchor point, which represents the point at which the mouse was pressed and then use the MouseMotionListener to define the extent of the selection area, for example...相反,您应该使用MouseListener来定义一个锚点,它表示鼠标被按下的点,然后使用MouseMotionListener来定义选择区域的范围,例如...

油漆选择

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SelectExample {

    public static void main(String[] args) {
        new SelectExample();
    }

    public SelectExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Rectangle selection;

        public TestPane() {
            MouseAdapter ma = new MouseAdapter() {

                private Point clickPoint;

                @Override
                public void mousePressed(MouseEvent e) {
                    clickPoint = e.getPoint();
                    selection = null;
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    Point dragPoint = e.getPoint();
                    int x = Math.min(clickPoint.x, dragPoint.x);
                    int y = Math.min(clickPoint.y, dragPoint.y);

                    int width = Math.max(clickPoint.x, dragPoint.x) - x;
                    int height = Math.max(clickPoint.y, dragPoint.y) - y;

                    if (selection == null) {
                        selection = new Rectangle(x, y, width, height);
                    } else {
                        selection.setBounds(x, y, width, height);
                    }
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    selection = null;
                    repaint();
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (selection != null) {
                g.setColor(UIManager.getColor("List.selectionBackground"));
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                g2d.fill(selection);
                g2d.dispose();
                g2d = (Graphics2D) g.create();
                g2d.draw(selection);
                g2d.dispose();
            }
        }

    }

}

Just to highlight the issue you will face if you continue to violate the requirements of the paintComponent method, this is what happens when I don't call super.paintComponent只是为了强调如果您继续违反paintComponent方法的要求将面临的问题,这就是当我不调用super.paintComponent时会发生的情况

违反

I simply added two JButton 's to the JFrame (so not even directly to the panel).我只是在JFrame添加了两个JButton (所以甚至没有直接添加到面板中)。 paintComponent does a series of important jobs, which you neglected to perform, which is going to cause more problems and issues. paintComponent做了一系列重要的工作,你忽略了这些工作,这会导致更多的问题和问题。

Free form line example...自由形式行示例...

A free form line is actually a illusion, it's a series of (small) lines drawn between a series of points, the reason for this is because the MouseListener won't report every mouse position it moves across, depending on the speed the mouse is moved, you might get lots of call backs or a few.自由形式的线实际上是一种错觉,它是在一系列点之间绘制的一系列(小)线,这是因为MouseListener不会报告它移动的每个鼠标位置,这取决于鼠标的速度搬家,你可能会收到很多或几个回电。

So, instead of drawing to just draw the points, we store the points in a List and draw lines between them, for example...因此,我们不只是绘制点,而是将点存储在List并在它们之间画线,例如......

自由形式

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class FreeFormLines {

    public static void main(String[] args) {
        new FreeFormLines();
    }

    public FreeFormLines() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<List<Point>> points;

        public TestPane() {
            points = new ArrayList<>(25);
            MouseAdapter ma = new MouseAdapter() {

                private List<Point> currentPath;

                @Override
                public void mousePressed(MouseEvent e) {
                    currentPath = new ArrayList<>(25);
                    currentPath.add(e.getPoint());

                    points.add(currentPath);
                }

                @Override
                public void mouseDragged(MouseEvent e) {
                    Point dragPoint = e.getPoint();
                    currentPath.add(dragPoint);
                    repaint();
                }

                @Override
                public void mouseReleased(MouseEvent e) {
                    currentPath = null;
                }

            };

            addMouseListener(ma);
            addMouseMotionListener(ma);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (List<Point> path : points) {
                Point from = null;
                for (Point p : path) {
                    if (from != null) {
                        g2d.drawLine(from.x, from.y, p.x, p.y);
                    }
                    from = p;
                }
            }
            g2d.dispose();
        }

    }

}

This is a simple example for a practical paint Application, where you can control and change the size and the Color of your drawing.这是实际绘画应用程序的一个简单示例,您可以在其中控制和更改绘图的大小和颜色。

public class Main extends Application{
    @Override
    public void start(Stage stage){
        try{
            g = can.getGraphicsContext2D();
            g.setStroke(Color.BLACK);
            g.setLineWidth(1);
            c.setValue(Color.BLACK);
            c.setOnAction(e->{
                g.setStroke(c.getValue());
            });
            sli.setMin(1);
            sli.setMax(100);
            sli.setShowTickLabels(true);
            sli.setShowTickMarks(true);
            sli.valueProperty().addListener(e->{
                double val = sli.getValue();
                String str = String.format("%.1f",  val);
                lab.setText(str);
                g.setLineWidth(val);
            });
            gri.addRow(0,  c, sli, lab);
            gri.setHgap(20);
            gri.setAlignement(Pos.TOP_CENTER);
            gri.setPadding( new Insets( 20, 0, 0, 0));

            scene.setOnMousePressed(e->{.
               g.beginPath();
               g.lineTo(e.getSceneX(), e.getSceneY());
               g.stroke();
            });
            scene.setOnMoudrDragged(e->{. 
                g.lineTo(e.getSceneX(),  e.getSceneY());
                g.stroke();
            });
            pan.getChildren().addAll(can, gri);
            stage.setScene(scene);
            stage.show();
        }catch(Exception e){

            e.printStrackTrace();
        }

       Canvas can = new Canvas(760, 490);
       GraphicsContext  g ;
       ColorPicker  c =  new ColorPicker();
       Slider sli = new Slider();
       Label lab = new Label("1.0");
       GridPane gri = new GridPane();
       StackPane pan =  new StackPane();
       Scene  scene = new Scene(pan, 760, 490);
   public static void main (String [] args){
       launch(args);
   }
}

Or we can try drawing for only java code , I think it's so easy and powerful.或者我们可以尝试只绘制 java 代码,我认为它是如此简单和强大。

package drawingbymouse;

import java.awt.*;
import java.awt.event.*;

public class DrawingByMouse extends Frame 
                          implements MouseMotionListener{

    DrawingByMouse(){
        addMouseMotionListener(this);
        setSize(400, 400);
        setLayout(null);
        setVisible(true);
    }
    @Override
    public void mouseDragged(MouseEvent e){
        Graphics g = getGraphics();
        g.setColor(Color.BLACK);
        g.fillOval(e.getX(), e.getY(), 10, 10);
    }
    public void mouseMoved(MouseEvent e){
    }
    public static void main (String[]args){
        new DrawingByMouse();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM