マウスドラッグイベントを使用してJavaアプレットに四角形を描画する方法
質問
私はJavaを使用しています。マウスドラッグイベントに基づいて長方形を描画したい。ユーザーがマウスをドラッグした場合、アプレット上の四角形は現在のマウス座標に基づいて増加または減少する必要があります。次のコードがあります。
次のコードでは、描画操作を実行しているキャンバスを拡張する [b]SelectionArea[/b] クラスを使用しています。私はこのクラスで [b]image[/b] 変数を使用して二重バッファリングを行い、ちらつきを軽減し、アプレットの以前の状態(つまり、アプレットの描画コンテンツ)を保存しています。
しかし、最初の四角形を描画すると、コードは正常に機能します。2 番目の長方形を描画し始めると、前に描画した長方形が消えてしまいます。以前に描画した長方形を画面上に表示したい
誰かこれを解決する方法を教えてください。
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;
/*
* This displays a framed area. When the user drags within
* the area, this program displays a rectangle extending from
* where the user first pressed the mouse button to the current
* cursor location.
*/
public class RectangleDemo extends Applet {
SelectionArea drawingPanel;
Label label;
public void init() {
GridBagLayout gridBag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridBag);
drawingPanel = new SelectionArea(this);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1.0;
c.gridwidth = GridBagConstraints.REMAINDER; //end row
gridBag.setConstraints(drawingPanel, c);
add(drawingPanel);
label = new Label("Drag within the framed area.");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.weighty = 0.0;
gridBag.setConstraints(label, c);
add(label);
drawingPanel.setVisible(true);
validate();
}
public void paint(Graphics g){
drawingPanel.repaint();
}
public void update(Graphics g){
paint(g);
}
}
class SelectionArea extends Canvas implements ActionListener, MouseListener, MouseMotionListener{
Rectangle currentRect;
RectangleDemo controller;
//for double buffering
Image image;
Graphics offscreen;
public SelectionArea(RectangleDemo controller) {
super();
this.controller = controller;
addMouseListener(this);
addMouseMotionListener(this);
}
public void actionPerformed(ActionEvent ae){
repaintoffscreen();
}
public void repaintoffscreen(){
image = createImage(this.getWidth(), this.getHeight());
offscreen = image.getGraphics();
Dimension d = getSize();
if(currentRect != null){
Rectangle box = getDrawableRect(currentRect, d);
//Draw the box outline.
offscreen.drawRect(box.x, box.y, box.width - 1, box.height - 1);
//repaint();
}
}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me){ }
public void mouseClicked(MouseEvent me){}
public void mouseMoved(MouseEvent me){}
public void mousePressed(MouseEvent me) {
currentRect = new Rectangle(me.getX(), me.getY(), 0, 0);
repaintoffscreen();
}
public void mouseDragged(MouseEvent me) {
System.out.println("here in dragged()");
currentRect.setSize(me.getX() - currentRect.x, me.getY() - currentRect.y);
repaintoffscreen();
repaint();
}
public void mouseReleased(MouseEvent me) {
currentRect.setSize(me.getX() - currentRect.x, me.getY() - currentRect.y);
repaintoffscreen();
repaint();
}
public void update(Graphics g){
paint(g);
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, this);
}
Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) {
int x = originalRect.x;
int y = originalRect.y;
int width = originalRect.width;
int height = originalRect.height;
//Make sure rectangle width and height are positive.
if (width < 0) {
width = 0 - width;
x = x - width + 1;
if (x < 0) {
width += x;
x = 0;
}
}
if (height < 0) {
height = 0 - height;
y = y - height + 1;
if (y < 0) {
height += y;
y = 0;
}
}
//The rectangle shouldn't extend past the drawing area.
if ((x + width) > drawingArea.width) {
width = drawingArea.width - x;
}
if ((y + height) > drawingArea.height) {
height = drawingArea.height - y;
}
return new Rectangle(x, y, width, height);
}
}
また、このコードを全画面モードで実行すると、マウスを放した後にのみ四角形が画面上に表示されることがわかります。しかし、マウスをドラッグしているときに長方形を画面上に表示したいのですが、現在のマウス座標に応じてその寸法が変更されるはずです。誰か助けてもらえませんか?
解決
宿題?
基本的に行う必要があるのは次のとおりです。
- マウスダウン時にマウスダウン座標を保持して再描画します
- マウス移動時に現在のマウス座標を保持して再描画します
- マウスを上に置くと、マウスダウンの座標を無効にして四角形がないことを示し、再描画します。
- ペイントで背景を描画し、マウスダウン座標とマウスカーソル座標の間の四角形を描画します。
背景画像を保持したくない場合は、Graphics xor 関数を使用してトリックを行うことができます。同じ四角形を 2 回描画すると古い四角形が消去されるため、これを使用して古い画像をグラフィックス オブジェクト上に直接復元できます。
編集:コード XOR の使用例:
public void paint(Graphics g)
{
g.setXORMode(Color.black);
// draw old rect if there is one. this will erase it
// draw new rect, this will draw xored
g.setDrawMode(); // restore normal draw mode
}
Xor には興味深い特性があります。
xor(xor(x)) = x
したがって、同じピクセルを 2 回 XOR すると、元の色が復元されます。
他のヒント
対処する必要がある問題がいくつかあります。
まず、描画できる四角形は 1 つだけですが、これはプログラムの設計によるものです。コード内では常に、 repaintoffscreen
メソッドが呼び出されると、 currectRect
フィールドは長方形を描画するために使用されます。ただし、過去に作成された長方形を保持し続けるための規定はありません。
過去の長方形を保持しておく 1 つの方法は、おそらく、たとえば、 List<Rectangle>
過去の長方形を保存するために使用されます。そして、マウスを放すと、 add
現在の四角形をそのリストに追加します。
次に、すべての長方形に対して、 currentRect
過去の長方形が表示されます。 repaintoffscreen
実行するだけでなく、 getDrawableRect
そして offscreen.drawRect
を使用して currentRect
に保存されている過去の四角形も使用します。 List<Rectangle>
. 。(ヒント: for
リストを反復処理するループ)。
次に、マウス ボタンを放すまで四角形が表示されないことについては、 mouseDragged
メソッド、おそらく使用 mouseMoved
この方法と、マウス ボタンが押されていることを確認するチェックが回避策になる可能性があります。(私も対応に苦労したと思います) mouseDragged
過去の方法です。)
の MouseEvent
に渡されました mouseMoved
メソッドを使用して、ボタンが押されたかどうかを確認できます。 getButton
方法:
public void mouseMoved(MouseEvent e)
{
// Check if button1 is pressed.
if (e.getButton() == MouseEvent.BUTTON1)
{
// Perform sizing of rectangle and off-screen drawing, and repaint.
}
}
私の質問は、およそ選択長方形反転マウスクリックの位置を作成しましたが、、最後に私はこの方法でこれを行いました。
... //to set the selection area
private int iniSelX;
private int iniSelY;
private int endSelX;
private int endSelY;
private JPanel myJPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
g.drawLine(260, 5, 260, 260);
g.setColor(Color.BLUE);
//verify if go draw the rectangle
if (iniSelX != 0 || endSelX != 0) {
boolean revertX = iniSelX < endSelX;
boolean revertY = iniSelY < endSelY;
//Simple way
//g.drawRect(iniSelX, iniSelY, endSelX - iniSelX, endSelY - iniSelY);
//reverse way
g.drawRect(revertX ? iniSelX : endSelX, revertY ? iniSelY : endSelY,
revertX ? endSelX - iniSelX : iniSelX - endSelX, revertY ? endSelY - iniSelY : iniSelY - endSelY);
}
}
}; ...
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent m) {
//update selection area
endSelX = m.getX();
endSelY = m.getY();
repaint();
}
@Override
public void mouseMoved(MouseEvent m) {
repaint();
}
});
addMouseListener(new MouseListener() {
...
@Override
public void mousePressed(MouseEvent e) {
//start drawing the selection
iniSelX = e.getX() - 15;
iniSelY = e.getY() - 20;
}
@Override
public void mouseReleased(MouseEvent e) {
//start drawing the selection
iniSelX = 0;
iniSelY = 0;
endSelX = 0;
endSelY = 0;
}
...
});
}
public void log() {
System.out.println("iniSelX" + iniSelX);
System.out.println("iniSelY" + iniSelY);
System.out.println("endSelX" + endSelX);
System.out.println("endSelY" + endSelY);
} ...
私はこれが有用であると思います。