JAVAの初心者です、宜しくお願いします。
下のようなプログラムを書きました。
「public void paint(Graphics g){
~ repaint();」とすると、画像がちらつきます、しかし、「repaint();」を消すとちらつかなくなります、この原因が分かりません。
一体何故このような現象が起こるのでしょうか、宜しくお願いします。
==========================================================
import java.applet.Applet;
import java.awt.Button;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class Oval_Rec_1_071128 extends Applet implements MouseListener , ActionListener
{
int x1 ;
int y1 ;
int xh = 50 ;
int yv = 50 ;
Button bt1 ;
Button bt2 ;
public void actionPerformed(ActionEvent ae){}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void init()
{
setBackground(Color.yellow);
addMouseListener(this);
bt1 = new Button("push");
bt1.setFont(new Font("SansSerif", Font.BOLD, 20));
bt1.setBackground(Color.black);
bt1.setForeground(Color.lightGray);
add(bt1);
bt1.addActionListener(this);
bt2 = new Button("change_circle");
add(bt2);
bt2.addActionListener(this);
}
public void mousePressed(MouseEvent e)
{
x1 = e.getX();
y1 = e.getY();
xh = e.getX();
yv = e.getY();
//repaint(); //comment out
}
public void paint(Graphics g)
{
g.setColor(Color.red);
g.setFont(new Font("Serif",Font.BOLD,24));
g.drawString("Hello Applet World ! !" , 50 , 50);
g.setColor(Color.blue);
g.drawLine( 100 , 100 , 500 , 500);
g.setColor(Color.cyan);
g.fillOval( x1 , y1 , xh , yv);
g.setColor(Color.magenta);
g.fillRect( xh , yv, x1/10 , y1/10 );
repaint();
}
}
No.6ベストアンサー
- 回答日時:
update()は必ず画面の消去を行うわけではありません。
参考書によっては「update()は描画面を背景色で塗りつぶす」と書いてあるものもありますが、実際にはそこまで単純なものではありません。じゃあ実際はどうなのか、は細かく説明しだすと芋づる式に難しい用語や概念が出てくるので、ここでの回答は難しいです。理解していないと困る場面もそうそうないでしょうし、「基本的な」描画の流れからは外れた高度な内容になってきます。
なのでまだ勉強を始めたばかりであれば、まずは「直接update()を呼ぶことはほとんどない」「描画をしてほしいタイミングでrepaint()を呼べばよい」「描画処理そのものはpaint()内に書けばよい」ということを覚えておき、ある程度Javaに慣れてから、Javaのソースコードを直接自分で読んでみるなり(JDKにsrc.zipというのが入っています)、描画プロセスについて細かく書かれた参考書等を読むなりされた方がよいと思います。
で、今回の背景塗りつぶしに関しては、入門書でよく見かけるのは以下の2つの方法です。お手持ちの参考書なり、勉強サイトなりにどちらか書かれていませんか?
1.Graphics.setColor()で描画色を設定し、Graphics.fillRect()で画面全体を塗りつぶす。
2.Graphics.setBackground()で背景色を設定しておき、Graphics.clearRect()で画面全体を塗りつぶす。
要は自分で描画する内容についての単純な更新は自分でやろうね、ということです。質問者様が今回書かれたclear()メソッドの最初の2行がちょうど1.に該当しますが、基本的にはそれが正しいやり方だと思っておいてよいと思いますよ。
No.8
- 回答日時:
うわ、失礼。
#6ですが#7様の回答が正解。私のは無視してください。forループに気づかなかった…アニメーションはpaint()の中でforループ使って実現してはいけません。どういう参考書をお使いなのか分かりませんが、Runnableインターフェースのことがたぶんそのうち出てくるので、それまでアニメーションには手をつけない方がいいです。
みなさん、ありがとうございます。
ひとまず締め切らせていただきます。
貴重な回答ありがとうござます。
自分でももっと勉強します。
今後とも宜しくお願いします。
No.7
- 回答日時:
#2です。
アニメーションに手を出してしまいましたか。
まだ、早いと思うのですが。
>なにか、基本的な作成方法とかアルゴリズムみたいなものが
>間違っているのでしょうか、宜しくご教示お願い致します。
残念ながら、間違っています。
clearメソッドを実装すれば、アニメーションらしきものが出てきますが、根本的に間違っています。
試しに、アニメーションが終わった後にブラウザを最小化して元に戻してみてください。
なぜか、また、アニメーションが始まります。
アプレットビューワーなら、ウィンドウの大きさを変更しただけで、アニメが始まります。
これは思い描いていた挙動ではないはずです。
ちなみにAWTでアプレットを作ったので、アニメらしきものが出ましたが、Swingで実装していれば、それすらも出ないはずです。
もし、アニメーションをしたいのであれば、
イベントディスパッチスレッドはどんな仕事をしているのか。
paintメソッドはどんなタイミングで呼ばれるのか。
そういった、基本的なことを理解しないと無理だと思います。
No.5
- 回答日時:
#2です。
> updateが単独で呼ばれる場合は(基本的には?)
>ないという考えで良いのでしょうか。
そうですね。
まとめると、
1. updateメソッド、paintメソッドは、システム(Java仮想マシン)が呼ぶもの。プログラマが明示的に呼ぶことはまずない。
2. 再描画したいならrepaintメソッドを使うべき。
3. プログラマにできることは、コンポーネントの見た目や振る舞いを変更するために、paintメソッド(SwingならpaintComponentメソッド)を書き換えること。でも、そのメソッドを呼ぶのは、あくまで、システム。
もちろん、例外はありますが、あくまで基本はこういう形です。
PecoPlusさん、何度も丁重な回答ありがとうございます。
何とか理解できました、有り難う御座いました。
ところで、下のような連続的に円が右に移動するプログラムを作成しました。
paint()は呼び出されるときは、必ず古いwindowにある絵を消して描くと思ったのですが、
そうはならなくて円が連続してしまいます。
色々と考えて「clear(g);」書いてやりましたが、「clear(g);をコメント」にすると円が連続します。
paint()は呼び出されるときには、必ず今windowにある絵を消して描くと考えたのですが、そのようにはなってくれませんでした。
メソッドの基本的な機能は何となく理解出来るのですが、実はこの辺のプログラム全体の流れ?みたいなものがなかなか理解出来ません。
何故「clear(g);」が必要なのでしょうか。宜しくお願いします。
また、「clear(g);」を書かなくても出来る方法はあるのでしょうか。
やはり、どこかに「repaint」を入れると思ったとおりに動くのでしょうか。
なにか、基本的な作成方法とかアルゴリズムみたいなものが間違っているのでしょうか、宜しくご教示お願い致します。
================================================================
public class Ball_Idou extends Applet
{
int x ;
public void paint(Graphics g)
{
for(x = 0 ; x < 180 ; ++ x)
{
//clear(g) ;
g.drawOval(x , 90 , 19 , 19) ;
sleep() ;
}
}
public void clear(Graphics g)
{
g.setColor(Color.white) ;
g.fillRect(0 , 80 , 200 , 40) ;
g.setColor(Color.black) ;
}
public void sleep(Graphics g)
{
double s = 0.0 ;
for (int j = 1 ; j<100 ; ++ j)
{
for (int k = 1 ; k < 100 ; ++ k)
{
s =+ Math.sin((double) j ) ;
}
}
}
}
No.4
- 回答日時:
#2です。
ちょっと、例えが悪かったようです。
>#新しく図形を描く命令をすると必ずパネル全体を一旦クリアして、
>背景色を再描画した後に新しく、新しい図形を描くのではないのですか。
>その場合には古い絵は残らないと思うのですが
その通りです。
私が出した例えは、「もし、repaintがupdateを呼ばなかったとしたら、こんなことになってしまうよ」という仮の話です。
># 基本的には、パネルだけの再描画だけがPaint、
>パネルに貼り付けられているものも含めた再描画が
>Updateという考えでよいのでしょうか。
違います。
端的に言えば、
update : 消しゴム
paint : 鉛筆
とでも、考えていただければ、いいと思います。
すでに画用紙に何か書かれていれば、いったん消しゴムで消してから、書かなくてはいけない場合もあれば、画用紙が白紙なので、消しゴムを使う必要がなくいきなり鉛筆で書ける場合もあるということです。
もっとも、自分で、コンポーネントを自作したり、アニメーションをさせようとしたりしない限り、この辺のことはあまり深く考える必要はないです。
普通にやっていれば、updateやpaintを明示的に呼ぶことは、まずないと思います。
それより、repaintの使い方を覚えることが先決です。
「イベントディスパッチスレッド」については、ここで一から説明するのは、ちょっと無理かもしれません。
いったん、勉強してみて、疑問点があれば、新しく質問をたててみてください。
PecoPlusさん、回答ありがとうございます。
>すでに画用紙に何か書かれていれば、いったん消しゴムで消してから、書かなくてはいけない場合もあれば、画用紙が白紙なので、消しゴムを使う必要がなくいきなり鉛筆で書ける場合もあるということです。
もっとも、自分で、コンポーネントを自作したり、アニメーションをさせようとしたりしない限り、この辺のことはあまり深く考える必要はないです。
普通にやっていれば、updateやpaintを明示的に呼ぶことは、まずないと思います。
# ということは、repainを呼んでやれば、パネルの諸状況を判断して
paintが呼ばれる場合、updateが呼ばれる場合があるということでしょうか。
updateが単独で呼ばれる場合は(基本的には?)ないという考えで良いのでしょうか。
再度ご教示宜しくお願いします。
No.3
- 回答日時:
#2です。
updateメソッドは何をしているかというと、コンポーネントの塗りつぶしを行ってから、paintメソッドを呼びます。
repaintを呼ぶと何が起こるかというと、
repaint() (再描画命令、updateメソッドを呼ぶ)
↓
update() (コンポーネントを背景色で塗りつぶしたあと、paintメソッドを呼ぶ)
↓
paint() (コンポーネントを描画)
もし、repaint()が、update()を呼ばず、直接paint()を呼んでいたら、どうなるでしょう?
今回を例に挙げれば、図形の座標が変えられ、repaint()→paint()となれば、そのまま、新しい図形を上書きしますが、上書きされなかった古い図形の断片は消されることなく、残り続けてしまいます。
これでは、いけません。
完全に、背景色で塗りつぶし、白紙の状態にしてから、一からすべて描き直す。
これが、Javaでのコンポーネント描画の基本です。
しかし、それが基本なら、なぜ、updateメソッドとpaintメソッドが一つのメソッドとして実装されておらず、別々のメソッドにしてあるのでしょう?
たとえば、パネルにボタンが配置してあるとします。
そのパネルのrepaint()が呼ばれたとします。
まず、updateメソッドにより、パネル全体が背景色で塗りつぶされます。(当然ボタンも消えます)
そのあと、パネルのpaintメソッドが呼ばれ、パネル内の子コンポーネントを描画しようとします。
そのとき、子のボタンをもう一回背景色で塗りつぶす必要があるでしょうか?
もうすでに塗りつぶされているのですから、それは冗長です。
ここでは、描画だけされればいいはずです。
よって、ボタンのpaintメソッドのみが呼ばれます。
このように、場合場合によって
塗りつぶし→描画
描画
と、するべき事柄が違うので、分けてあるのです。
>コードによっては直接Updatを呼んでいる場合もあります。
イベント処理のコードの中で、updateメソッドやpaintメソッドを直接呼ぶことは基本的にないと思います。
repaintメソッドを呼んで、イベントディスパッチスレッドに適切なタイミングでまとめて描画してもらうよう依頼するのが基本です。
PecoPlusさん、何度も明快な回答ありがとうございます。
>repaint() (再描画命令、updateメソッドを呼ぶ)
↓
update() (コンポーネントを背景色で塗りつぶしたあと、paintメソッドを呼ぶ)
↓
paint() (コンポーネントを描画)
>今回を例に挙げれば、図形の座標が変えられ、repaint()→paint()となれば、そのまま、新しい図形を上書きしますが、上書きされなかった古い図形の断片は消されることなく、残り続けてしまいます。
#新しく図形を描く命令をすると必ずパネル全体を一旦クリアして、背景色を再描画した後に新しく、新しい図形を描くのではないのですか。
その場合には古い絵は残らないと思うのですが。
(>まず、updateメソッドにより、パネル全体が背景色で塗りつぶされます。(当然ボタンも消えます))
>その辺の原理というか、描画の仕組みが良く理解できていないのですが。
何か詳しい良書があるでしょうか。
> たとえば、パネルにボタンが配置してあるとします。
そのパネルのrepaint()が呼ばれたとします。
まず、updateメソッドにより、パネル全体が背景色で塗りつぶされます。(当然ボタンも消えます)
# 基本的には、パネルだけの再描画だけがPaint、パネルに貼り付けられているものも含めた再描画がUpdateという考えでよいのでしょうか。
>repaintメソッドを呼んで、イベントディスパッチスレッドに適切なタイミングでまとめて描画してもらうよう依頼する
# 「イベントディスパッチスレッド」とは、具体的にどのような意味でしょうか。
再度宜しくご教示お願い致します。
No.2
- 回答日時:
こんにちは。
>この場合、そもそもrepaint()を書いてやる必要はあるのでしょうか。
>また、書くとすれば一体どのように(どこに)書いてやると良いのでしょうか。
#1さんの理由から paint()メソッド内に書くのはおかしいです。
書く必要があるのは、コメントアウトされていますが、mousePressedイベントのまさにそこです。
「図形の座標を変更したので、書き直しておいてね」って、ことです。
こうすることによって、一連のイベントが処理され一段落したところで、イベントディスパッチスレッドによって、再描画が必要とされたところだけが描き直されます。
(ここでは、アプレット全体が描き直されます)
PecoPlusさん、明快な回答有り難うございました。
うまく動くようになりました。
ところで、「repaint」と「update」とはどう違うのでしょうか。
APIを調べると、
>repaint
public void repaint()このコンポーネントを再びペイントします。
このメソッドは、このコンポーネントの update メソッドを可能なかぎり速やかに呼び出します。
>repaint
public void repaint(long tm)このコンポーネントを再びペイントします。tm ミリ秒以内に update メソッドを呼び出します。
>UPDATE - class java.awt.event.PaintEvent の static 変数
再描画イベントタイプです。
>UPDATE - interface javax.accessibility.AccessibleTableModelChange の static 変数
既存のデータに対する変更を識別します。
>UPDATE - class javax.swing.event.TableModelEvent の static 変数
既存のデータに対する変更を識別します。
========================================================
上記のような解説がありますが、呼んでもよく理解できません。
コードによっては直接Updatを呼んでいる場合もあります。
その使い分けが良く理解できません。
何と宜しくご教示お願いいたします。
No.1
- 回答日時:
repaint()は簡単にいえば「手が空いたらpaint()で描画してね」と描画スレッドに合図を送るためのメソッドです。
なので描画メソッドであるpaint()の中で呼ぶのはおかしいです。画面を描画している人が自分に対してもう一度描画するように依頼するようなものですから。画面描画のサイクルの中で再描画をしようとするので、描画が間に合わないかタイミングがおかしくなるかでちらつくのでしょう。
しかしpaint()の中でrepaint()を呼ぶコードを初めて見ました。なにげに斬新です。
komi1341さん、回答有り難う御座います。
この場合、そもそもrepaint()を書いてやる必要はあるのでしょうか。
また、書くとすれば一体どのように(どこに)書いてやると良いのでしょうか。
なにとぞ宜しくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- Java 直し方について教えて頂きたいです。 4 2022/08/13 02:11
- C言語・C++・C# 大量のデータを読み込んで表示する速度を改善したい 8 2023/05/07 13:29
- Java java final 1 2022/06/10 22:49
- Java Java 配列<選挙> 4 2023/07/31 15:07
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- HTML・CSS cssの display: flex;で横並びにならずに困ってます 1 2022/12/04 13:18
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VB.NETのSendMessageを教えてく...
-
音声再生/SourceDataLineの遅延
-
JAVAでの背景画像表示
-
描画してもウィンドウをリサイ...
-
Javaを使って、円を描きたい
-
C# DataGridView のCellPaintin...
-
JPanel上での描画と各コンポー...
-
C#のGraphicsクラスについてです。
-
Labelコントロールの背景をグラ...
-
Javaで割り当てられていない文...
-
BMP画像を画像処理して連続に表...
-
AWTでテキストボックスの枠線を...
-
「タイプ初期化子が例外をスロ...
-
エクセルVBAで、条件に一致する...
-
変数名の付け方
-
日本の教育って時間が無い中で...
-
インスタンス参照でアクセスで...
-
VB.NET getとsetの概念がわかり...
-
クラスのプロパティに構造体を...
-
C# インスタンスの破棄
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
JAVAでの背景画像表示
-
VB.NET フォーム上に描いたグ...
-
VB.NETのSendMessageを教えてく...
-
C# DataGridView のCellPaintin...
-
Javaで文字の角度を変えて表示...
-
canvasで表示されてる画像を1...
-
画面のちらつきの原因が知りた...
-
Labelコントロールの背景をグラ...
-
重なった要素上でのイベントで...
-
java.awt.peer?
-
Canvas等の図形を移動する時,直...
-
OpenLayersの描画を固定で表示...
-
ID3DXSprite::Drawメソッドに関...
-
描画処理が実行されない
-
C#のGraphicsクラスについてです。
-
SwingとEDT(イベントディスパッ...
-
Androidで画像の中で指定した範...
-
Androidのフォントサイズ(SP)と...
-
複数画像表示切り替え Visual c++
-
JavaScript でスライダーを作る...
おすすめ情報