質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

1437閲覧

JavaFXのCanvasで「消しゴム」の実装

nakamaro

総合スコア8

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/03/19 03:06

前提・実現したいこと

現在、JavaFXを使ってペイントアプリのようなものを作っています。
Windows標準ペイントでいうペンは実装できたのですが、消しゴムがうまく実装できません。

調べた範囲では削除関係はGraphicsContext.clearRectぐらいしか見つからず、
消しゴムとは言い難いので他の方法を探しています。
ちなみにレイヤー構造で背景が透明なので白で上書きという手段が使えません。

解決策や代替案等があれば教えていただけると嬉しいです。

該当のソースコード

Java

1public class AppCanvas extends Canvas{ 2 /* 3 * 書き込み専用キャンバスクラス 4 */ 5 6 //グラフィック 7 private GraphicsContext g; 8 9 //直前座標 10 private double befoer_x = -1; 11 private double befoer_y = -1; 12 13 public AppCanvas(double x,double y) { 14 15 this.setWidth(x); 16 this.setHeight(y); 17 18 g = this.getGraphicsContext2D(); 19 20 //描画設定 21 g.setLineWidth(3); 22 23 //マウスボタン押し込み時処理登録 24 EventHandler<MouseEvent> dragg = ( event ) -> draggMouse(event); 25 this.addEventHandler( MouseEvent.MOUSE_DRAGGED , dragg ); 26 27 //マウスドラッグ時処理登録 28 EventHandler<MouseEvent> press = ( event ) -> pressMouse(event); 29 this.addEventHandler( MouseEvent.MOUSE_PRESSED , press ); 30 31 //マウス離したときの処理登録 32 EventHandler<MouseEvent> release = ( event ) -> releaseMouse(event); 33 this.addEventHandler( MouseEvent.MOUSE_RELEASED , release ); 34 } 35 36 /* 37 * マウス押し込み初回 38 */ 39 void pressMouse(MouseEvent event) { 40 41 //消しゴムの場合は透過色に,それ以外は黒に 42 if(XXXX) { 43 g.setFill(Color.TRANSPARENT); //ここで透過色で塗りつぶしを試しましたが、消しゴムにはならず 44 g.setStroke(Color.TRANSPARENT); 45 }else { 46 g.setFill(Color.BLACK); 47 g.setStroke(Color.BLACK); 48 } 49 50 //現在座標で点を描画 51 g.strokeLine(befoer_x, befoer_y , befoer_x, befoer_y); 52 53 //直前座標を記録 54 befoer_x = event.getX(); 55 befoer_y = event.getY(); 56 } 57 58 /* 59 * マウスドラッグ 60 */ 61 void draggMouse(MouseEvent event) { 62 63 //直前座標が存在しない場合終了 64 if(befoer_x < 0) { 65 return; 66 } 67 68 //今回座標と直前座標を線で結ぶ 69 g.strokeLine(befoer_x, befoer_y , event.getX(), event.getY()); 70 71 //今回の座標を直前座標に登録 72 befoer_x = event.getX(); 73 befoer_y = event.getY(); 74 } 75 76 /* 77 * マウス離す 78 */ 79 void releaseMouse(MouseEvent event) { 80 81 //前回座標を無効する 82 befoer_x = -1; 83 befoer_y = -1; 84 } 85}

試したこと

・削除関係の処理はClearRect以外見つけられませんでした。
・ドラッグ部分をfillOvalにして動作確認した際、線を引いたら破線になっていたためClearRect連続実行も効果が無いと思われます。
・上記ソースに記載がありますが、透明色で上書きは効果無かったです。

補足情報(FW/ツールのバージョンなど)

Eclipse
Java11
JavaFx

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/03/19 14:51

透過色じゃなくて、白で塗れば良いのでは。
guest

回答1

0

ベストアンサー

PixelWriter#setColor()をつかってみる、とか。

java

1package fx; 2 3import javafx.application.Application; 4import javafx.scene.Scene; 5import javafx.scene.canvas.Canvas; 6import javafx.scene.canvas.GraphicsContext; 7import javafx.scene.image.PixelWriter; 8import javafx.scene.input.MouseEvent; 9import javafx.scene.layout.StackPane; 10import javafx.scene.paint.Color; 11import javafx.scene.shape.Line; 12import javafx.stage.Stage; 13 14public class HogeCanvas { 15 public static void main(final String[] args) throws Exception { 16 Application.launch(App.class, args); 17 } 18 19 static public class App extends Application { 20 @Override 21 public void start(final Stage stage) throws Exception { 22 final Canvas base = new Canvas(); 23 { 24 base.setWidth(200); 25 base.setHeight(200); 26 final GraphicsContext g = base.getGraphicsContext2D(); 27 g.setFill(Color.CYAN); 28 g.fillOval(0, 0, base.getWidth(), base.getHeight()); 29 } 30 31 final Canvas canvas = new Canvas(); 32 { 33 canvas.setWidth(200); 34 canvas.setHeight(200); 35 final GraphicsContext g = canvas.getGraphicsContext2D(); 36 g.setFill(Color.RED); 37 g.fillRect(10, 10, canvas.getWidth() - 20, canvas.getHeight() - 20); 38 39 canvas.setOnMouseMoved(ev -> { 40 clearLine(g, ev); 41 }); 42 } 43 44 stage.setScene(new Scene(new StackPane(base, canvas))); 45 stage.show(); 46 } 47 48 private MouseEvent _prevEv = null; 49 50 private void clearLine(final GraphicsContext g, final MouseEvent ev) { 51 if (_prevEv != null) { 52 final PixelWriter pw = g.getPixelWriter(); 53 final Line line = new Line(_prevEv.getX(), _prevEv.getY(), ev.getX(), ev.getY()); 54 for (int x = (int) Math.min(line.getStartX(), line.getEndX()); x <= (int) Math.max(line.getStartX(), line.getEndX()); x++) { 55 for (int y = (int) Math.min(line.getStartY(), line.getEndY()); y <= (int) Math.max(line.getStartY(), line.getEndY()); y++) { 56 if (line.contains(x, y)) { 57 pw.setColor(x, y, Color.TRANSPARENT); 58 } 59 } 60 } 61 } 62 // 63 _prevEv = ev; 64 } 65 } 66} 67

投稿2021/03/20 15:26

shiketa

総合スコア3990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nakamaro

2021/03/23 07:51

PixelWriter#setColorで1ピクセルずつクリアという方法があったのですね。 ありがとうございます、参考になります。 削除範囲は太さが欲しかったので、少しアレンジして ・描画キャンバスに重ねたダミーキャンバスに太線で描画(描画キャンバスと同処理) ・ダミーで全ピクセル走査して非透明ピクセルを検知、描画キャンバスの同じ座標をクリア ・ダミーを初期化 という処理にしてみました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問