为什么在这段代码中调用重绘?
如果将 jpanel 实例添加到内容窗格,则会调用 PaintComponent 方法,对吧?
content_pane.add(fDrawingPanel);
那么为什么要在 run() 方法的第一行调用“repaint”呢? (它说“绘制加载消息,但它应该已经被绘制,因为 paintComponent
之前被调用过,一旦 fShow
为 true,我们就不会将其设置回来为 false,所以我认为这段代码应该被调用一次):
public class MediaTrackApplet extends JApplet
implements Runnable
{
// Need a reference to the panel for the
// thread loop.
DrawingPanel fDrawingPanel;
// Parameters to track the image
MediaTracker fTracker;
Image fImg;
int fImageNum = 0;
boolean fShow = false;
String fMessage ="Loading...";
/** Use a MediaTracker to load an image.**/
public void init () {
Container content_pane = getContentPane ();
// Create an instance of DrawingPanel
fDrawingPanel = new DrawingPanel (this);
// Add the DrawingPanel to the contentPane.
content_pane.add (fDrawingPanel);
// Get image and monitor its loading.
fImg = getImage (getCodeBase (), "m20.gif.jpg" );
fTracker = new MediaTracker (this);
// Pass the image reference and an ID number.
fTracker.addImage (fImg, fImageNum);
} // init
/** If the image not yet loaded, run the thread
* so the run() will monitor the image loading.
**/
public void start () {
if (!fTracker.checkID (fImageNum) ) {
Thread thread = new Thread (this);
thread.start ();
} else
// Unloading/reloading web page can will leave
// checkID true but fShow will be false.
fShow = true;
} // start
/** Use a thread to wait for the image to load
* before painting it.
**/
public void run () {
// Paint the loading message
repaint ();
// The wait for the image to finish loading
try {
fTracker.waitForID (fImageNum );
} catch (InterruptedException e) {}
// Check if there was a loading error
if (fTracker.isErrorID (fImageNum ))
fMessage= "Error";
else
fShow = true;
// Repaint with the image now if it loaded OK
repaint ();
} // run
}// class MediaTrackApplet
/** This JPanel subclass draws an image on the panel if
* the image is loaded. Otherwise, it draws a text message.
**/
class DrawingPanel extends JPanel {
MediaTrackApplet parent = null;
DrawingPanel (MediaTrackApplet parent) {
this.parent = parent;
}// ctor
public void paintComponent (Graphics g) {
super.paintComponent (g);
// Add your drawing instructions here
if (parent.fShow)
g.drawImage (parent.fImg,10,10,this);
else
g.drawString (parent.fMessage, 10,10);
} // paintComponent
} // class DrawingPanel
谢谢
if you add a jpanel instance to the content pane, the paintComponent method is called, right?
content_pane.add (fDrawingPanel);
so why would you call "repaint" at the first line in the run()
method? (it says "to paint the loading message, but it should already be painted, because paintComponent
was called before, and once fShow
is true, we don't set it back to false, so this code is, i think, supposed to be called once ) :
public class MediaTrackApplet extends JApplet
implements Runnable
{
// Need a reference to the panel for the
// thread loop.
DrawingPanel fDrawingPanel;
// Parameters to track the image
MediaTracker fTracker;
Image fImg;
int fImageNum = 0;
boolean fShow = false;
String fMessage ="Loading...";
/** Use a MediaTracker to load an image.**/
public void init () {
Container content_pane = getContentPane ();
// Create an instance of DrawingPanel
fDrawingPanel = new DrawingPanel (this);
// Add the DrawingPanel to the contentPane.
content_pane.add (fDrawingPanel);
// Get image and monitor its loading.
fImg = getImage (getCodeBase (), "m20.gif.jpg" );
fTracker = new MediaTracker (this);
// Pass the image reference and an ID number.
fTracker.addImage (fImg, fImageNum);
} // init
/** If the image not yet loaded, run the thread
* so the run() will monitor the image loading.
**/
public void start () {
if (!fTracker.checkID (fImageNum) ) {
Thread thread = new Thread (this);
thread.start ();
} else
// Unloading/reloading web page can will leave
// checkID true but fShow will be false.
fShow = true;
} // start
/** Use a thread to wait for the image to load
* before painting it.
**/
public void run () {
// Paint the loading message
repaint ();
// The wait for the image to finish loading
try {
fTracker.waitForID (fImageNum );
} catch (InterruptedException e) {}
// Check if there was a loading error
if (fTracker.isErrorID (fImageNum ))
fMessage= "Error";
else
fShow = true;
// Repaint with the image now if it loaded OK
repaint ();
} // run
}// class MediaTrackApplet
/** This JPanel subclass draws an image on the panel if
* the image is loaded. Otherwise, it draws a text message.
**/
class DrawingPanel extends JPanel {
MediaTrackApplet parent = null;
DrawingPanel (MediaTrackApplet parent) {
this.parent = parent;
}// ctor
public void paintComponent (Graphics g) {
super.paintComponent (g);
// Add your drawing instructions here
if (parent.fShow)
g.drawImage (parent.fImg,10,10,this);
else
g.drawString (parent.fMessage, 10,10);
} // paintComponent
} // class DrawingPanel
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的。这个古老但已过时的示例来自一个早于我们现代理解的时代,即 Swing GUI 对象应该仅在 事件调度线程。初始调用
repaint()
的效果是在EventQueue
上发布新的Runnable
,同时允许后台线程完成在对后续repaint()
的预期。另请参阅内存一致性属性以及此相关的示例。Yes. This venerable, but superannuated, example hails from an era that predates our modern understanding that Swing GUI objects should be constructed and manipulated only on the event dispatch thread. The initial invocation of
repaint()
has the effect of posting a newRunnable
on theEventQueue
, while allowing the background thread to finish loading images in anticipation of the subsequentrepaint()
. See also Memory Consistency Properties and this related example.