Maison  >  Article  >  Java  >  Tutoriel sur la façon de créer une planche à dessin simple en utilisant Java

Tutoriel sur la façon de créer une planche à dessin simple en utilisant Java

巴扎黑
巴扎黑original
2017-07-18 14:54:392600parcourir
Je crois que beaucoup de gens ont utilisé la tablette à dessin Windows. Cette fois, nous parlerons de l'implémentation de la version Java de la planche à dessin simple.
L'idée de base est la suivante : l'implémentation de la planche à dessin est grossièrement divisée en trois parties : La première est l'implémentation de l'interface de la planche à dessin, et le deuxième est le suivi et le dessin de la planche à dessin Réalisation, le troisième est le redessin de la planche à dessin. (L'article est long, mais le code est progressif. Vous pouvez le visualiser en trois parties. Après avoir implémenté la partie actuelle, passez à la partie suivante.) La première est l'implémentation de l'interface de la planche à dessin, car je l'ai fait Je ne trouve pas l'icône spécifique, tous les composants de l'interface sont les propres composants de Swing, donc l'interface est un peu grossière, mais si vous souhaitez l'optimiser, c'est simple, il suffit de changer tous les composants de l'interface en icônes personnalisées. Une fois l'interface implémentée, vous pouvez envisager d'ajouter une surveillance aux composants de l'interface. Différents graphiques peuvent ajouter différentes méthodes de surveillance en fonction de la situation spécifique. Écrivez ensuite une classe de traitement d'événements pour écrire des algorithmes de dessin spécifiques basés sur différents graphiques. Une version simple de la planche à dessin est presque là. Je ne parlerai de redessiner ici que plus tard.
Regardons d'abord l'implémentation de l'interface de dessin :
Les classes API nécessaires pour implémenter l'interface de dessin incluent principalement : FlowLayout, GridLayout, Color, Dimension, JButton, JFrame et JPanel.
Définissez la classe Draw et laissez la classe Draw hériter de JFrame. Définissez sa taille, son titre, sa visibilité, etc. Il est à noter que s'il y a beaucoup de boutons à ajouter ici, il est recommandé d'utiliser un tableau pour compléter l'ajout de boutons, car si vous ajoutez directement des boutons un par un, cela augmentera non seulement la quantité de code, mais également nuire à la recherche, à l'ajout et à la maintenance du code. Afin de rendre l'interface moins simple, plusieurs Jpanels et différents gestionnaires de mise en page sont utilisés ici. Le formulaire principal utilise un gestionnaire de mise en page fluide, puis utilise trois panneaux pour héberger respectivement les boutons graphiques, les boutons de couleur et le canevas. Les panneaux contenant des boutons graphiques et des boutons de couleur utilisent la disposition en tableau. Ensuite, la mise en œuvre de l’interface est pratiquement terminée.
package Cbs;import java.awt.Color;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.GridLayout;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;/**
 * Draw类,用于界面的初始化
 * @author CBS */@SuppressWarnings("serial")public class Draw extends JFrame {// 界面初始化方法public void showUI() {
        setTitle("画图");//窗体名称setSize(1200, 900);//窗体大小setDefaultCloseOperation(3);
        setLocationRelativeTo(null);//窗体居中//流式布局左对齐FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
        setLayout(layout);//窗体使用流式布局管理器this.setResizable(false);//窗体大小不变        //使用数组保存按钮名String buttonName[] = { "画直线", "画椭圆", "画曲线", "多边形", 
                  "橡皮擦", "拖动线","三角形", "画球形", "笔刷", "喷枪", 
                  "色子", "立体矩形", "立体圆", "立体三角","迭代分形",                   "现代分形", "枫叶", "画树", "mandelbrot集", "L-System",                  "迭代画线","迭代三角形", "谢尔宾斯基地毯", "画字符", "清空",                  "吸管" ,"矩形","五角星","多线","字符"};//用于保存图形按钮,使用网格布局JPanel jp1=new JPanel(new GridLayout(15, 2,10,10));
        jp1.setPreferredSize(new Dimension(200, 800));        //循环为按钮面板添加按钮for (int i = 0; i 
Afficher le code
Une autre chose à noter ici est que l'ordre dans lequel les panneaux Jpanel sont ajoutés ne doit pas être modifié. Il s'agit de la taille du panneau calculée en fonction de la disposition du flux. Les lecteurs peuvent modifier et déboguer eux-mêmes. Une autre chose est que la méthode setSize du formulaire n'est valable que pour le formulaire lui-même. Si vous souhaitez modifier la taille d'autres composants, utilisez la méthode setPreferredSize. De cette manière, l'interface de base de la planche à dessin est implémentée. Les boutons et panneaux de l'interface peuvent être modifiés selon vos besoins.
Voici à quoi ressemble l'interface :

Tutoriel sur la façon de créer une planche à dessin simple en utilisant Java
Suivi de la mise en œuvre :
当然我们空有个界面并没有什么用,我们需要的是点击不同的按钮能够实现不同的功能。这里就需要用到事件的监听机制了。实现监听的主要API类有: ActionListener,MouseListener,MouseMotionListener。添加事件监听的方法根以前的步骤是一样的:确定事件源对象,编写事件处理类,添加监听方法。画图板中的事件源对象有两种,一种是按钮,另一种就是画布的面板,按钮使用的是ActionListener,而画布面板因为负责的是绘图,所以使用的是MouseListener和MouseMotionListener。为了实现事件的监听,我们需要定义一个事件处理类DrawListener,该类实现了以上的三个事件接口。之后在重写的方法中实现不同图形的绘制。图形的绘制都可以通过Graphics对象的方法来实现。但是这里有一个问题,如何分辨在Draw类中按下的是哪个按钮呢?在定义Draw类的时候,我们使用了图形按钮和颜色按钮,图形类的按钮在实例化对象的时候是使用了带参数的构造方法的,也就是图形按钮都是有文字的,而颜色按钮则没有。依据这一点就可以很容易的区分不同的按钮了。
DrawListener类:
package Cbs;import java.awt.Color;import java.awt.Graphics;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.JButton;public class DrawListener implements ActionListener, MouseListener,
        MouseMotionListener {private Color color;//颜色属性private Graphics g;//画笔属性private String str;//保存按钮上的字符串,区分不同的按钮private int x1,y1,x2,y2;//(x1,y1),(x2,y2)分别为鼠标的按下和释放时的坐标private JButton nowColor;//当前颜色按钮    //获取Draw类的画笔对象public void setG(Graphics g) {this.g = g;
    }//获取当前颜色按钮public void setNowColor(JButton nowColor) {this.nowColor = nowColor;
    }


    @Override//鼠标拖动的方法public void mouseDragged(MouseEvent e) {//画曲线的方法if ("画曲线".equals(str)) {int x, y;
            x = e.getX();
            y = e.getY();
            g.drawLine(x, y, x1, y1);
            x1 = x;
            y1 = y;
        }
    }

    @Override//鼠标移动方法public void mouseMoved(MouseEvent e) {

    }

    @Override//鼠标单击方法public void mouseClicked(MouseEvent e) {

    }

    @Override//鼠标按下方法public void mousePressed(MouseEvent e) {
        
        g.setColor(color);//改变画笔的颜色        
        x1=e.getX();//获取按下时鼠标的x坐标y1=e.getY();//获取按下时鼠标的y坐标    }

    @Override//鼠标释放方法public void mouseReleased(MouseEvent e) {
        x2=e.getX();//获取释放时鼠标的x坐标y2=e.getY();//获取释放时鼠标的y坐标//画直线的方法if ("画直线".equals(str)) {
            g.drawLine(x1, y1, x2, y2);
        }
    }

    @Override//鼠标进入方法public void mouseEntered(MouseEvent e) {

    }

    @Override//鼠标退出方法public void mouseExited(MouseEvent e) {

    }

    @Override//处理按钮上的鼠标点击动作public void actionPerformed(ActionEvent e) {//判断是颜色按钮还是图形按钮if ("".equals(e.getActionCommand())) {
            JButton jb = (JButton) e.getSource();
            color = jb.getBackground();
            nowColor.setBackground(color);//处理当前颜色} else {
            str = e.getActionCommand();
        }
    }

}
View Code

Draw类也要做一些修改,为按钮和面板添加监听:

 1 package Cbs; 2  3 import java.awt.Color; 4 import java.awt.Dimension; 5 import java.awt.FlowLayout; 6 import java.awt.Graphics; 7 import java.awt.GridLayout; 8  9 import javax.swing.JButton;10 import javax.swing.JFrame;11 import javax.swing.JPanel;12 13 /**14  * Draw类,用于界面的初始化15  * @author CBS16  */17 @SuppressWarnings("serial")18 public class Draw extends JFrame {19     private DrawListener dl;20     private Graphics g;21     // 界面初始化方法22     public void showUI() {23         setTitle("画图");//窗体名称24         setSize(1200, 900);//窗体大小25         setDefaultCloseOperation(3);26         setLocationRelativeTo(null);//窗体居中27                 //流式布局左对齐28         FlowLayout layout = new FlowLayout(FlowLayout.LEFT);29         setLayout(layout);//窗体使用流式布局管理器30         this.setResizable(false);//窗体大小不变31         32         //使用数组保存按钮名33         String buttonName[] = { "画直线", "画椭圆", "画曲线", "多边形",34                       "橡皮擦", "拖动线","三角形", "画球形", "笔刷", "喷枪", 
35                       "色子", "立体矩形", "立体圆", "立体三角","迭代分形",36                        "现代分形", "枫叶", "画树", "mandelbrot集", "L-System", 
37                        "迭代画线","迭代三角形", "谢尔宾斯基地毯", "画字符", "清空",38                       "吸管" ,"矩形","五角星","多线","字符"};39                 //用于保存图形按钮,使用网格布局40         JPanel jp1=new JPanel(new GridLayout(15, 2,10,10));41         jp1.setPreferredSize(new Dimension(200, 800));42         43         //实例化DrawListener对象44         dl=new DrawListener();45         //循环为按钮面板添加按钮46         for (int i = 0; i 
View Code
drawDrawListener里面只写了画直线和曲线的方法,读者可以根据自己的需求添加,思路和方式都是一样的。Draw类里面有些需要注意的地方在这里提一下:一个是画笔g的获取一定要在窗体的可见之后采取获取,不然获取的画笔对象返回值会是null。二是要为图形按钮添加监听,DrawListener的实例化需要在setVisible方法之前,所以不建议使用构造方法直接传入g画笔参数,我使用的是set方法。最后是注意一下使用哪个添加方法,按钮使用的是addActionListener方法,画板面板使用的是addMouseListener和addMouseMotionListener方法。使用画板面板来获取画笔并给画面面板添加监听是为了让绘图的时候图形不会跑出面板外,这里的画笔和监听都由主窗体获得也是可以的,不过绘制时会出现线画出面板的问题。
画板的重绘:
到这里画板的制作已经基本实现了,我们已经可以在上面绘制各种各样的图形了。但是细心的人可能会发现一个问题,那就是如果把窗体最小化之后再次打开,画板上原本已经画好的东西会全部都消失了。这样子肯定是不行的,辛辛苦苦画的“大作”怎么能说说没就没了呢。那么为什么会出现这样的问题呢?要回答这个问题我们就需要先了解Java的绘图机制。做画图板我们使用的是Swing组件,这套组件是基于原先的AWT组件开发,在绘制的时候会调用系统的画图函数,这就是为什么我们可以从面板或者是窗体中获取画笔对象的原因。这也就是说Java中你所能够看到窗体,按钮或者其它的所有组件其实都是画出来。所以当我们点击窗体使它最小化或者改变大小的时候,原来的画的窗体就不能适应需要了,这时系统会调用JFrame的paint方法实现窗体的重绘,也就是再次画了一个新的窗体,而JFrame的paint方法只对窗体已经添加的组件有效,我们自己绘制的东西并没有写在paint方法里面,所以窗体重绘之后,我们原先绘制的图形也就消失了。要解决这个问题我们需要重写父类的paint方法。但是这样的话问题又来了,画图是在DrawListener类里面实现的,要怎么把它们弄到paint方法里面去呢?
当然方法可能有很多,这里我只介绍我所知道的:要把画出来的图形在paint方法中再次画出来,就需要有东西来保存画过的图形。保存可以使用数组或者集合,这里推荐使用集合,可以很方便的实现添加,而不需要去考虑大小的问题。数组的实现也大同小异,这里就不多做介绍。确定了使用集合,那么集合内保存什么类型的数据呢?毫无疑问应该保存的是图形的数据,但是集合使用泛型的话也只能保存同一种类型的数据,我们却有那么多种图形?这里就可以使用接口或者抽象类,我们只需要创建不同得图形类,让它继承抽象类或者是实现接口。然后每画一个图形就实例化一个图形的对象,存入集合中,最后在paint方法中遍历集合,重新绘制图形即可。
下面直接贴最终代码(仍然只写了直线和曲线),只是添加了几行代码,注意与前面比较。
//图形接口package Cbs;//图形集合public interface NetJavaShape {public abstract void draw();
}//直线类package Cbs;import java.awt.Color;import java.awt.Graphics;import Cbs.NetJavaShape;public class ImpLine implements NetJavaShape{
    Graphics g;int x1, y1,x2, y2;
    Color c;public ImpLine(Graphics g,int x1,int y1,int x2,int y2,Color c){this.g=g;this.c=c;this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;
    }public void draw() {
        g.setColor(c);
        g.drawLine(x1, y1, x2, y2);
    }

}//DrawListener类package Cbs;import java.awt.Color;import java.awt.Graphics;import java.util.List;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 java.util.ArrayList;import Cbs.NetJavaShape;import javax.swing.JButton;public class DrawListener implements ActionListener, MouseListener,
        MouseMotionListener {private Color color=Color.BLACK;//颜色属性,初始值为黑色private Graphics g;//画笔属性private String str;//保存按钮上的字符串,区分不同的按钮private int x1,y1,x2,y2;//(x1,y1),(x2,y2)分别为鼠标的按下和释放时的坐标private JButton nowColor;//当前颜色按钮//保存图形对象的集合private List<netjavashape> shapesArray = new ArrayList<netjavashape>();//图形private NetJavaShape shape;//在draw类中获取集合public List<netjavashape> getShapesArray() {return shapesArray;
    }//获取Draw类的画笔对象public void setG(Graphics g) {this.g = g;
    }//获取当前颜色按钮public void setNowColor(JButton nowColor) {this.nowColor = nowColor;
    }


    @Override//鼠标拖动的方法public void mouseDragged(MouseEvent e) {//画曲线的方法if ("画曲线".equals(str)) {int x, y;
            x = e.getX();
            y = e.getY();//实例化对象,曲线也是直线画的所以不同新建一个曲线类了shape=new ImpLine(g,x,y,x1,y1,color);//调用画图方法            shape.draw();//将图形存入集合中            shapesArray.add(shape);//            g.drawLine(x, y, x1, y1);x1 = x;
            y1 = y;
        }
    }

    @Override//鼠标移动方法public void mouseMoved(MouseEvent e) {

    }

    @Override//鼠标单击方法public void mouseClicked(MouseEvent e) {

    }

    @Override//鼠标按下方法public void mousePressed(MouseEvent e) {
        
        g.setColor(color);//改变画笔的颜色        
        x1=e.getX();//获取按下时鼠标的x坐标y1=e.getY();//获取按下时鼠标的y坐标    }

    @Override//鼠标释放方法public void mouseReleased(MouseEvent e) {
        x2=e.getX();//获取释放时鼠标的x坐标y2=e.getY();//获取释放时鼠标的y坐标//画直线的方法if ("画直线".equals(str)) {//实例化对象,shape=new ImpLine(g,x1,y1,x2,y2,color);//调用画图方法            shape.draw();//将图形存入集合中            shapesArray.add(shape);//            g.drawLine(x1, y1, x2, y2);        }
    }

    @Override//鼠标进入方法public void mouseEntered(MouseEvent e) {

    }

    @Override//鼠标退出方法public void mouseExited(MouseEvent e) {

    }

    @Override//处理按钮上的鼠标点击动作public void actionPerformed(ActionEvent e) {        if ("".equals(e.getActionCommand())) {
            JButton jb = (JButton) e.getSource();
            color = jb.getBackground();
            nowColor.setBackground(color);//处理当前颜色} else {
            str = e.getActionCommand();
        }
    }

}//draw类package Cbs;import java.awt.Color;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.Graphics;import java.awt.GridLayout;import java.util.ArrayList;import java.util.List;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JPanel;/**
 * Draw类,用于界面的初始化
 * @author CBS */@SuppressWarnings("serial")public class Draw extends JFrame {private DrawListener dl;private Graphics g;//保存图形对象的集合private List<netjavashape> shapesArray = new ArrayList<netjavashape>();// 界面初始化方法public void showUI() {
        setTitle("画图");//窗体名称setSize(1200, 900);//窗体大小setDefaultCloseOperation(3);
        setLocationRelativeTo(null);//窗体居中FlowLayout layout = new FlowLayout(FlowLayout.LEFT);//流式布局左对齐setLayout(layout);//窗体使用流式布局管理器this.setResizable(false);//窗体大小不变        //使用数组保存按钮名String buttonName[] = { "画直线", "画椭圆", "画曲线", "多边形",     "橡皮擦", "拖动线","三角形", "画球形", "笔刷", "喷枪", "色子", "立体矩形", "立体圆", "立体三角","迭代分形", "现代分形", "枫叶", "画树", "mandelbrot集", "L-System", "迭代画线","迭代三角形", "谢尔宾斯基地毯", "画字符", "清空","吸管" ,"矩形","五角星","多线","字符"};
        JPanel jp1=new JPanel(new GridLayout(15, 2,10,10));//用于保存图形按钮,使用网格布局jp1.setPreferredSize(new Dimension(200, 800));        //实例化DrawListener对象dl=new DrawListener();//循环为按钮面板添加按钮for (int i = 0; i </netjavashape></netjavashape></netjavashape></netjavashape></netjavashape>
View Code
这里使用集合添加图形实现画板的重绘时,我是每实现一个图形就会新建一个类来保存图形的信息,这样图形类就会有很多。如果不想创建那么多的图形类可以把它们都放到一个类里面,设置一个type的参数,赋上按钮的名称。然后在draw方法中依据这个值判断是什么图形实现不同的画图方法。这样画板的所有功能基本就实现了,画板的项目也就到这里。
总结:

La production de planches à dessin utilise principalement des composants Swing, un mécanisme d'écoute d'événements, le dessin graphique et le redessin de planches à dessin et l'utilisation de classes ou d'interfaces abstraites servent de classes graphiques standard.


Cours d'écoute


package com.baidu;

importer java.awt.*;
importer java.awt.event.MouseEvent;
importer java.awt.event. ;

classe publique MyMouseListener implémente MouseListener{
//Color
Panel p;
//Canvas
Graphics g;
//Commande d'action
private SimpleDraw draw ;
//Donner les coordonnées
private int x1,y1,x2,y2;
//Méthode de construction


public MyMouseListener(SimpleDraw draw){
this . g=draw.getGraphics();//Attribuer la valeur de l'objet transmise à l'attribut g
this.draw=draw;

}


//La souris entre Appelée lorsque sur le composant
@Override
public void mouseClicked(MouseEvent e) {
}
//Appelé lorsque la souris quitte le composant
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
x1=e.getX( );
y1=e.getY();
}
@Override
public void mouseReleased(MouseEvent e) {
x2=e.getX();
y2=e .getY();
String command = draw.getCommand();
g.setColor(Color.blue);


if(command.equals("Straight line")) {
g.drawLine(x1, y1, x2, y2);

}else if(command.equals("rectangle")){
g.drawRect(x1, y1, x2- x1 , y2-y1);
 
}else if(command.equals("ellipse")){
g.drawOval(x1, y1, x2-x1, y2-y1);
}
}
}












Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn