絵を描く板の完備——再描画
前編でまとめたのは,グラフィックボードのインタフェースと基本機能を実現することである.では、私たちが絵を描くときに問題が見つかります.私たちが絵を描いた後、窓の大きさを変えたり、最小化したりすると、私たちが描いた絵は消えてしまいます.私たちが描いたものが小さいのは、描いた形をメモリに保存していないからです.また、上記の操作(フォームサイズの変更...)を実行すると、paintのメソッドが自動的に呼び出されます.私たちはpaintを再描画するこの方法を定義していないので、再描画を実行する前に描いたものは存在しません.だから自分が描いた図案を永遠に存在させる方法はpaintの方法を実行する時に私たちが描いた図案をもう一度彼に描き直すことです!これが再描画です.
再描画の方法はたくさんありますが、私は今でも1次元配列または2次元配列の2つの方法を使用して再描画操作を完了することができます.
1 D配列の再描画
1 D配列は確かに再描画方法を完成させることができますが、面倒で面倒で不安定です.これは彼が簡単に言っただけだ.彼は実用的ではないからだ.
私たちが絵を描くときに最も重要な要素は、何を描くか、どこで描くか、色です.この3点、どこで描くかの鍵は取得したxy座標です.したがって,1次元配列を用いて描画した図形座標をすべて格納し,再描画の方法で格納した座標に従って再描画すれば,再描画の操作が完了する.直線だけで例を挙げましょう.
新しい1次元配列int[]array_line = new int[];では、配列を作成するときに問題を発見しました.配列の長さはいくらに設定されていますか.これは、前述した1次元配列の再描画が完了する欠点であり、面倒であるだけでなく、ここで配列長を定義する場合、例えば100と定義する.では、25本の直線を保存してから描くのはまず保存できません.定義が大きすぎるとメモリの無駄になります.
それはともかく.1 D配列が座標をどのように格納して復元するかを見てみましょう.
これで各直線の座標を4つの4つのグループに従ってarrayに格納します.lineという配列にあります.
では、再描画方法ではどう書きますか?
dpaperはキャンバスのパネルで、super.paint(g)の匿名の内部クラスを使用しています.この文の役割は、親クラスのpaintメソッドを呼び出してフォームを描画することです. forループを使用してarray_を取得するには4つの4つのグループがあります.lineのデータを直線で描くと再描画が完了します.
1次元配列を使用して再描画するのは本当に面倒で不便であることは明らかです.次に、2 D配列で再描画を行います.
2 D配列の再描画
二次元配列の再描画の考え方は、大体、私たちのコンピュータの画面は小さな画素点で構成されているので、グラフィックボードの真ん中のキャンバスも行が何個、縦が何個の画素点のような点陣で構成されているので、1つの二次元配列を利用して各画素点の色を記憶すれば、再描画時に画素点の色を元に戻すと、再描画機能も完了しているのではないでしょうか.
次は試してみましょう.
ここでは今まで使ったことのないクラスRobotを使う必要があります.彼には方法がある:createScreenCapture.彼の役割はスクリーン上の画像の一部を切り取ることです.したがって、この方法で図面キャンバスの部分を切り取り、1つの点で面を掃き、画素点の色データを2次元配列に格納すればよい.
その中にはgetLocationOnScreenという方法があります.彼の役割はキャンバスの左上隅座標を取得し、その後、createScreenCaptureとして使用されるパッケージクラスを行うパラメータを確立し、キャンバス部分を画像で保存することです.
次にpaintメソッドを書き換えるときは、ポイントカラーを1つずつ復元すればいいです.
これで2 D配列の再描画が完了します.1次元配列の再描画と比較すると、これはその方法より10086番街に強いと言えるのは明らかですが...
グラフィックボードのキャンバスを再描画するには、キューの再描画と画像の再描画という新しい方法があります.
まず、キューの再描画について説明します.
カスタムキューの使用に慣れた後、カスタムキューは1次元配列であるが、1次元配列には比べものにならない多くの利点があることがわかります.まず、配列を定義するときは配列の長さを設定し、javaはシステムメモリを操作できないため、その後の操作で配列の長さを変更することはできません.キューは異なり、キュー内の要素データを複数回追加または削除できます.配列のもう一つの欠点は、定義した後、1つのデータ型のデータしか格納できないことです.しかし、キューは汎用型を使用すれば、この問題を解決することができます.
では、キューを使用してグラフィックボードを再描画します.まず、大きな問題の考え方を理解してみましょう.私たちが画板に描く図形は、直線矩形でも鉛筆でも塗装しても、それぞれのオブジェクトと言えるので、キューを使ってこれらのオブジェクトを保存し、再描画方法でキューの要素を最初から繰り返してキャンバスに再描画することができます.これでキューの再描画が完了します.やる前に、いくつかの準備が必要です.
1.まず、カスタムキューが必要です.
キューを使用してグラフィックをキューに追加するだけのオブジェクトを再描画し、遍歴するときにキューの長さと位置ごとのデータ内容を知る必要があるため、このカスタムキューではこれら3つの方法があります.~
2.それらのグラフィックにクラスを作成する
私たちはそれらの図形をオブジェクトとして格納するので、図形クラスを作成し、異なる図形を作成するには、このクラスを継承するだけでいいです.
これは定義されたグラフィッククラスで、図を描くときに取得した始点のxy座標と、図を描くときに選択した色の5つの属性が含まれています.
次に、直線と矩形の2つだけを例に、それぞれのツールでパターンを描くグラフィッククラスをどのように作成するかを見てみましょう.
この2つのクラスは、私たちが直線と矩形を描いたときに描いた図形を格納するためのクラスです.以下では、リスナーで変更するだけで、これらのグラフィックを保存できます.
これは、グラフィックを描くと同時にshapeにグラフィックを保存し、事前に定義したlistキューに追加します.
これらの準備はすべてできました.次に、図に基づいて再描画操作を行います.簡単です.
ここで再描画方法を書き直し、キュー内の要素をループして、各要素を描けばいいだけです.
これでキューの再描画が完了します.
これに加えて、画像を再描画する方法もあります.
この方法は私たちが以前使っていた2次元配列の再描画とよく似ています.2次元配列の再描画は、私たちのキャンバスを1枚の画像として切り取り、その後、その画像の各画素の色を記憶し、再描画するときに1つずつ描画することで完成しますが、画像の再描画は直接画像全体を貼り直すのと同じです.ここでは、1つの方法を使用します.
drawImage(Image img, int x, int y, ImageObserver observer);
この方法はGraphicsの1つで、指定された位置に画像を描くことです.だから、画像を再描画するには、前に2次元配列で再描画して切り取った画像を再描画するだけです.この方法で、再描画時にキャンバスに貼るといいです.しかし、ここには間違いを犯しやすい場所があります.私たちがこの画像を再描画するxy座標は何ですか.その関数の2番目と3番目のパラメータです.APIドキュメントを見るとxyは、画像の左上隅がグラフィックコンテキスト座標空間にある(x、 y).キャンバスに再描画するので、xy座標は0でいいです.ここでは、私たちの絵板のスクリーン上の座標だと勘違いしないでください.そうすれば、先に再描画するときに画像の位置が間違っている場合があります.
このように~~私たちが描いた様々な図案~窓を閉じない限り、最大化や最小化に伴って消えることはありません!
これで私が知っている4つの再描画方法はすでにここにありますが、これらの方法を少しまとめて比較してみましょう.
明らかに、最初の1次元配列の再描画は最もよくないと思います.配列定義を小さすぎると、画像を描くことが多いときに後で描いたものは保存できません.定義が大きいとメモリの浪費になります.
2 D配列の再描画は、配列よりも確かに利点がありますが、この再描画は点描画であり、実行速度が速くないに違いありません.
キューの再描画は1次元配列の再描画の欠点を完全に回避しますが、そのようにグラフィックごとにクラスを作るのも面倒だと思います.の
..だからね.個人的に一番簡単なのはやはり画像の再描画だと思います.ねえ.
再描画についてのまとめはこれくらいにしましょう.この文章を読んでいる皆さんに少し助けてほしいです~~
再描画の方法はたくさんありますが、私は今でも1次元配列または2次元配列の2つの方法を使用して再描画操作を完了することができます.
1 D配列の再描画
1 D配列は確かに再描画方法を完成させることができますが、面倒で面倒で不安定です.これは彼が簡単に言っただけだ.彼は実用的ではないからだ.
私たちが絵を描くときに最も重要な要素は、何を描くか、どこで描くか、色です.この3点、どこで描くかの鍵は取得したxy座標です.したがって,1次元配列を用いて描画した図形座標をすべて格納し,再描画の方法で格納した座標に従って再描画すれば,再描画の操作が完了する.直線だけで例を挙げましょう.
新しい1次元配列int[]array_line = new int[];では、配列を作成するときに問題を発見しました.配列の長さはいくらに設定されていますか.これは、前述した1次元配列の再描画が完了する欠点であり、面倒であるだけでなく、ここで配列長を定義する場合、例えば100と定義する.では、25本の直線を保存してから描くのはまず保存できません.定義が大きすぎるとメモリの無駄になります.
それはともかく.1 D配列が座標をどのように格納して復元するかを見てみましょう.
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getY();
}
public void mouseReleased(MouseEvent e) {
int x2 = e.getX();
int y2 = e.getY();
if(command.equals("line")){
//
db.g.drawLine(x1,y1,x2,y2);
array_line[4*i_line] = x1;
array_line[4*i_line+1] = y1;
array_line[4*i_line+2] = x2;
array_line[4*i_line+3] = y2;
i_line++;
}
これで各直線の座標を4つの4つのグループに従ってarrayに格納します.lineという配列にあります.
では、再描画方法ではどう書きますか?
dpaper = new DrawPanel(dListener){public void paint(Graphics g){
super.paint(g);
for(int i = 0;i<DrawListener.array_line.length/4;i++){
g.drawLine(DrawListener.array_line[4*i], DrawListener.array_line[4*i+1], DrawListener.array_line[4*i+2], DrawListener.array_line[4*i+3]);
}
};
dpaperはキャンバスのパネルで、super.paint(g)の匿名の内部クラスを使用しています.この文の役割は、親クラスのpaintメソッドを呼び出してフォームを描画することです. forループを使用してarray_を取得するには4つの4つのグループがあります.lineのデータを直線で描くと再描画が完了します.
1次元配列を使用して再描画するのは本当に面倒で不便であることは明らかです.次に、2 D配列で再描画を行います.
2 D配列の再描画
二次元配列の再描画の考え方は、大体、私たちのコンピュータの画面は小さな画素点で構成されているので、グラフィックボードの真ん中のキャンバスも行が何個、縦が何個の画素点のような点陣で構成されているので、1つの二次元配列を利用して各画素点の色を記憶すれば、再描画時に画素点の色を元に戻すと、再描画機能も完了しているのではないでしょうか.
次は試してみましょう.
ここでは今まで使ったことのないクラスRobotを使う必要があります.彼には方法がある:createScreenCapture.彼の役割はスクリーン上の画像の一部を切り取ることです.したがって、この方法で図面キャンバスの部分を切り取り、1つの点で面を掃き、画素点の色データを2次元配列に格納すればよい.
public void getScrean(){
point1 = DrawBoard.dpaper.getLocationOnScreen();
Rectangle rect = new Rectangle((int) point1.getX(), (int) point1.getY(),DrawBoard.dpaper.getWidth(), DrawBoard.dpaper.getHeight());
BufferedImage image = robot.createScreenCapture(rect);
for(int i=0;i<image.getWidth();i++){
for(int j=0;j<image.getHeight();j++){
// 。
DrawBoard.array_paint[i][j] = image.getRGB(i, j);
}
}
}
その中にはgetLocationOnScreenという方法があります.彼の役割はキャンバスの左上隅座標を取得し、その後、createScreenCaptureとして使用されるパッケージクラスを行うパラメータを確立し、キャンバス部分を画像で保存することです.
次にpaintメソッドを書き換えるときは、ポイントカラーを1つずつ復元すればいいです.
paper = new DrawPanel(dListener){
public void paint(Graphics g){
super.paint(g);
for(int i=0;i<array_paint.length;i++){
for(int j=0;j<array_paint[i].length;j++){
Color color = new Color(array_paint[i][j]);
g.setColor(color);
g.drawLine(i, j, i, j);
}
}
}
};
これで2 D配列の再描画が完了します.1次元配列の再描画と比較すると、これはその方法より10086番街に強いと言えるのは明らかですが...
グラフィックボードのキャンバスを再描画するには、キューの再描画と画像の再描画という新しい方法があります.
まず、キューの再描画について説明します.
カスタムキューの使用に慣れた後、カスタムキューは1次元配列であるが、1次元配列には比べものにならない多くの利点があることがわかります.まず、配列を定義するときは配列の長さを設定し、javaはシステムメモリを操作できないため、その後の操作で配列の長さを変更することはできません.キューは異なり、キュー内の要素データを複数回追加または削除できます.配列のもう一つの欠点は、定義した後、1つのデータ型のデータしか格納できないことです.しかし、キューは汎用型を使用すれば、この問題を解決することができます.
では、キューを使用してグラフィックボードを再描画します.まず、大きな問題の考え方を理解してみましょう.私たちが画板に描く図形は、直線矩形でも鉛筆でも塗装しても、それぞれのオブジェクトと言えるので、キューを使ってこれらのオブジェクトを保存し、再描画方法でキューの要素を最初から繰り返してキャンバスに再描画することができます.これでキューの再描画が完了します.やる前に、いくつかの準備が必要です.
1.まず、カスタムキューが必要です.
public class DuiLie {
Object [] list = new Object[0];
/*
*
*/
public void add(Object m){
// , +1
Object [] newlist = new Object[list.length+1];
//
System.arraycopy(list, 0, newlist, 0, list.length);
newlist[list.length] = m;
list = newlist;
}
/*
*
*/
public int getSize(){
return list.length;
}
/*
*
*/
public Object getItem(int index){
return list[index];
}
}
キューを使用してグラフィックをキューに追加するだけのオブジェクトを再描画し、遍歴するときにキューの長さと位置ごとのデータ内容を知る必要があるため、このカスタムキューではこれら3つの方法があります.~
2.それらのグラフィックにクラスを作成する
私たちはそれらの図形をオブジェクトとして格納するので、図形クラスを作成し、異なる図形を作成するには、このクラスを継承するだけでいいです.
import java.awt.Color;
import java.awt.Graphics;
public abstract class Shape {
/*
*
*/
public int x1,x2,y1,y2;
public Color color;
/*
*
*/
public Shape(int x1,int y1,int x2,int y2,Color color){
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.color = color;
}
public abstract void draw(Graphics g);
}
これは定義されたグラフィッククラスで、図を描くときに取得した始点のxy座標と、図を描くときに選択した色の5つの属性が含まれています.
次に、直線と矩形の2つだけを例に、それぞれのツールでパターンを描くグラフィッククラスをどのように作成するかを見てみましょう.
import java.awt.Color;
import java.awt.Graphics;
public class Line extends Shape{
public Line(int x1, int y1, int x2, int y2, Color color) {
super(x1, y1, x2, y2, color);
}
public void draw(Graphics g) {
g.setColor(color);
g.drawLine(x1, y1, x2, y2);
}
}
import java.awt.Color;
import java.awt.Graphics;
public class Rect extends Shape{
public Rect(int x1, int y1, int x2, int y2, Color color) {
super(x1, y1, x2, y2, color);
}
public void draw(Graphics g) {
g.setColor(color);
g.drawRect(Math.min(x1,x2),Math.min(y1,y2),Math.abs(x1-x2),Math.abs(y1-y2));
}
}
この2つのクラスは、私たちが直線と矩形を描いたときに描いた図形を格納するためのクラスです.以下では、リスナーで変更するだけで、これらのグラフィックを保存できます.
if(command.equals("line")){
//
shape = new Line(x1,y1,x2,y2,col);
}
else if(command.equals("rect")){
//
shape = new Rect(x1,y1,x2,y2,col);
}
shape.draw(db.g);
list.add(shape);
これは、グラフィックを描くと同時にshapeにグラフィックを保存し、事前に定義したlistキューに追加します.
これらの準備はすべてできました.次に、図に基づいて再描画操作を行います.簡単です.
dpaper = new DrawPanel(dListener){
public void paint(Graphics g){
super.paint(g);
for(int i=0;i<DrawListener.list.getSize();i++){
// ,
((Shape)DrawListener.list.getItem(i)).draw(g);
}
}
};
ここで再描画方法を書き直し、キュー内の要素をループして、各要素を描けばいいだけです.
これでキューの再描画が完了します.
これに加えて、画像を再描画する方法もあります.
この方法は私たちが以前使っていた2次元配列の再描画とよく似ています.2次元配列の再描画は、私たちのキャンバスを1枚の画像として切り取り、その後、その画像の各画素の色を記憶し、再描画するときに1つずつ描画することで完成しますが、画像の再描画は直接画像全体を貼り直すのと同じです.ここでは、1つの方法を使用します.
drawImage(Image img, int x, int y, ImageObserver observer);
この方法はGraphicsの1つで、指定された位置に画像を描くことです.だから、画像を再描画するには、前に2次元配列で再描画して切り取った画像を再描画するだけです.この方法で、再描画時にキャンバスに貼るといいです.しかし、ここには間違いを犯しやすい場所があります.私たちがこの画像を再描画するxy座標は何ですか.その関数の2番目と3番目のパラメータです.APIドキュメントを見るとxyは、画像の左上隅がグラフィックコンテキスト座標空間にある(x、 y).キャンバスに再描画するので、xy座標は0でいいです.ここでは、私たちの絵板のスクリーン上の座標だと勘違いしないでください.そうすれば、先に再描画するときに画像の位置が間違っている場合があります.
このように~~私たちが描いた様々な図案~窓を閉じない限り、最大化や最小化に伴って消えることはありません!
これで私が知っている4つの再描画方法はすでにここにありますが、これらの方法を少しまとめて比較してみましょう.
明らかに、最初の1次元配列の再描画は最もよくないと思います.配列定義を小さすぎると、画像を描くことが多いときに後で描いたものは保存できません.定義が大きいとメモリの浪費になります.
2 D配列の再描画は、配列よりも確かに利点がありますが、この再描画は点描画であり、実行速度が速くないに違いありません.
キューの再描画は1次元配列の再描画の欠点を完全に回避しますが、そのようにグラフィックごとにクラスを作るのも面倒だと思います.の
..だからね.個人的に一番簡単なのはやはり画像の再描画だと思います.ねえ.
再描画についてのまとめはこれくらいにしましょう.この文章を読んでいる皆さんに少し助けてほしいです~~