ホームページ  >  記事  >  Java  >  Java を使用して簡単な描画ボードを作成する方法のチュートリアル

Java を使用して簡単な描画ボードを作成する方法のチュートリアル

巴扎黑
巴扎黑オリジナル
2017-07-18 14:54:392578ブラウズ
Windowsのドローイングパッドを使ったことがある人も多いと思いますが、今回はJava版の簡易ドローイングボードの実装についてお話します。
基本的な考え方は次のとおりです: 製図ボードの実装は大きく 3 つの部分に分かれています: 1 つ目は製図ボード インターフェイスの実装で、2 つ目は製図ボードの監視と描画の実装です。 3つ目は製図板の再描画です。 (記事は長いですが、コードはプログレッシブです。3 つの部分に分けることができます。現在の部分を実装したら、次の部分に進みます。) 1 つ目は、製図板のインターフェイスの実装です。見ていなかったので、特定のアイコンとインターフェイスについては、インターフェイス上のすべてのコンポーネントが Swing 独自のコンポーネントであるため、インターフェイスは少し粗雑ですが、最適化したい場合は、インターフェイス上のすべてのコンポーネントをカスタマイズしたアイコンに変更するだけです。インターフェイスを実装した後、特定の状況に応じて、さまざまなグラフィックスにさまざまな監視方法を追加することを検討できます。次に、イベント処理クラスを作成して、さまざまなグラフィックスに基づいた特定の描画アルゴリズムを作成します。製図板の簡易バージョンがもうすぐ完成します。ここでは再描画については後ほど触れません。
まず、描画インターフェースの実装を見てみましょう:
描画インターフェースの実装に必要な主な API クラスは次のとおりです: FlowLayout、GridLayout、Color、Dimension、JButton、 Jフレーム、JPパネル。
Draw クラスを定義し、Draw クラスに JFrame を継承させます。サイズ、タイトル、可視性などを設定します。なお、ここで追加するボタンが多い場合は、直接ボタンを一つずつ追加するとコード量が増えるだけでなく、配列を使用してボタンの追加を完了することをお勧めします。また、検索、追加、コードの保守にも悪影響を及ぼします。インターフェイスをそれほど単純にしないために、ここではいくつかの JPanel と異なるレイアウト マネージャーが使用されています。メイン フォームは流体レイアウト マネージャーを使用し、次に 3 つのパネルを使用してグラフィック ボタン、カラー ボタン、キャンバスをそれぞれホストします。グラフィック ボタンとカラー ボタンを保持するパネルはテーブル レイアウトを使用します。これでインターフェースの実装は基本的に完了します。
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 
View Code
ここでもう 1 つ注意すべき点は、Jpanel パネルを追加する順序を変更しないことです。これは、フローに基づいて計算されたパネル サイズです。レイアウトを変更すると、読者が自分で変更したりデバッグしたりできます。もう 1 つは、フォームの setSize メソッドはフォーム自体に対してのみ有効であるということです。他のコンポーネントのサイズを変更したい場合は、setPreferredSize メソッドを使用します。このようにして、描画ボードの基本的なインターフェイスが実装されます。インターフェイスのボタンとパネルは、必要に応じて変更できます。
インターフェイスは次のようになります:

Java を使用して簡単な描画ボードを作成する方法のチュートリアル
モニタリングの実装:
当然我们空有个界面并没有什么用,我们需要的是点击不同的按钮能够实现不同的功能。这里就需要用到事件的监听机制了。实现监听的主要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方法中依据这个值判断是什么图形实现不同的画图方法。这样画板的所有功能基本就实现了,画板的项目也就到这里。
总结:

描画ボードの作成には、主に Swing コンポーネント、イベント リスニング メカニズム、グラフィック描画と描画ボードの再描画が使用され、標準のグラフィック クラスとして機能する抽象クラスまたはインターフェイスが使用されます。


Listenerクラス


package com.baidu;

import java.awt.*;
import java.awt.event.Moイベント;
Javaをインポートします。 awt.event.MouseListener;

public class MyMouseListenerimplements MouseListener{
//カラー
パネル p;
//キャンバス
グラフィックス g;
//アクションコマンド
private SimpleDrawdraw;
//座標を与える
private int x1 , y1,x2,y2;
//構築メソッド


public MyMouseListener(SimpleDrawdraw){
this.g=draw.getGraphics();// 渡されたオブジェクトの値を属性 g に代入します
this.draw=draw;

}


//マウスがコンポーネントに入ると呼び出されます
@Override
public void MouseClicked(MouseEvent e) {
}
//マウスがコンポーネントから離れると呼び出されます
@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("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);
}
}
}












以上がJava を使用して簡単な描画ボードを作成する方法のチュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。