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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaFX

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

Q&A

解決済

1回答

3286閲覧

javafxにおけるCanvasスケール拡大時のぼやけ対策

peacecigarettes

総合スコア7

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaFX

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

0グッド

0クリップ

投稿2017/02/19 11:02

編集2017/02/19 11:03

###前提・実現したいこと
javafxのCanvasのスケールを拡大した際に、描画内容がぼやけてしまいます。
スケールを拡大しても、描画内容がぼやけないようにする方法を見つけたいです。

###発生している問題・エラーメッセージ
Canvasのスケールを縦横2倍にするクリックイベントがあり、
クリックするたびに描画内容(例えばfillrect)が2倍ずつ拡大するのですが、
同時に、徐々に描画内容もぼやけていきます。
アンチエイジングがかかるように、境界線があいまいになる感じです。

エラーメッセージ 特になし

###該当のソースコード

java

1 2<クリックイベント(抜粋)> 3canvas.setScaleX(canvas.getScaleX()*2); 4canvas.setScaleY(canvas.getScaleY()*2); 5

###試したこと

###補足情報(言語/FW/ツール等のバージョンなど)
拡大前の画像
8倍に拡大
32倍に拡大

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

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

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

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

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

guest

回答1

0

ベストアンサー

自分もやってみましたがうまくいきませんでした。

SceneはデフォルトでSceneAntialiasing.DISABLEDになっているはずですのでこれに影響されているわけではないはずです。(一応明示的に指定してみましたが、結果はかわらずでした)
GraphicsContextのリファレンスで関連しそうなものを見てみましたがペンの境界を表現するようなものは見当たりません。Strokeならば線分の属性が指定できますがfillRectなどの場合は境界について制御するようなものはない気がします。

推測ですがこれはJavaFXの座標系がintではなくdoubleを基本としているという事実に関係しているのではないかと思えました。つまりシーン上に描画した内容がデバイスピクセル上にどのように反映させるかについては「少なくともNodeのスケールプロパティーを用いた拡大縮小についてはJavaFXが適当にスムーズにレンダリングするのでプログラマーは気にしないでほしい」ということではないかと。

この推測を肯定 or 否定できる情報を見つけることはできませんでした。間違っている可能性もあるかと思います。


代案:

それはさておき、もしスケールプロパティーでくっきりとした描画ができのなら代案がほしいところですね。それは次のようにすると一応できました。

  • NodeのscaneX, scaleYプロパティーは用いない
  • GraphicsContextのtransformのscaleを用いる

拡大縮小の度にcanvasへの描画しなおしが必要な点が若干面倒ですね。ただ、描画の際にはGraphicsContext#save/restoreを用いてやると割合単純に書けます。

java

1void redraw(Canvas canvas, double scale) { 2 GraphicsContext gc = canvas.getGraphicsContext2D(); 3 gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); 4 gc.save(); // 変換座標他を内部スタックへ退避 5 gc.scale(scale, scale); 6 try { 7 //ここでgcへ描画する。もちろんスケールの違いは意識せずに描画する。 8 gc.setColor(Color.BLUE); 9 gc.fillRect(0, 0, 20, 20); 10 ... 11 } finally { 12 gc.restore(); // 変換座標他を内部スタックから回復 13 } 14}

投稿2017/02/19 12:36

KSwordOfHaste

総合スコア18394

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

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

peacecigarettes

2017/02/19 14:19

KSwordOfHaste様 どうもありがとうございます。 代案まで頂き、とても勉強になりました。 Nodeスケールに関するご洞察、言われてみると、そういう気がしますね。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問