",bg);
frame.pack( );
frame.setSize(150,100);
frame.show( );
}
通过这段代码,运行出的效果如下图6-1所示:
图6-1 展示中的半透明窗口
这段代码相当简单,却带有两个不足之处。首先,如果移动窗口,panel中的背景无法自动的更新,而paintComponent()只在改变窗口大小时被调用;其次,如果屏幕曾经发生过变化,那么我们制作的窗口将永远无法和和屏幕背景联合成整体。
谁也不想时不时地跑去更新screenshot,想想看,要找到隐藏于窗口后的东西,要获得一份新的screenshot,还要时不时的用这些screenshot来更新我们的半透明窗口,这些事情足以让用户无法安心工作。事实上,想要获取窗口之外的屏幕的变化几乎是不太可能的事,但多数变动都是发生在foreground窗口发生焦点变化或被移动之时。如果你接受这的观点(至少我接受这个观点),那么你可以只监控下面提到的几个事件,并只需在这几个事件被触发时,去更新screenshot。
public class TransparentBackground extends JComponent
implements ComponentListener, WindowFocusListener,
Runnable {
private JFrame frame;
private Image background;
private long lastupdate = 0;
public boolean refreshRequested = true;
public TransparentBackground(JFrame frame) {
this.frame = frame;
updateBackground( );
frame.addComponentListener(this);
frame.addWindowFocusListener(this);
new Thread(this).start( );
}
public void componentShown(ComponentEvent evt) { repaint( ); }
public void componentResized(ComponentEvent evt) { repaint( ); }
public void componentMoved(ComponentEvent evt) { repaint( ); }
public void componentHidden(ComponentEvent evt) { }
public void windowGainedFocus(WindowEvent evt) { refresh( ); }
public void windowLostFocus(WindowEvent evt) { refresh( ); }
Swing生成一个半透明的窗口(3)
时间:2011-07-20
首先,让我们的半透明窗口即panel实现ComponentListener接口,
WindowFocusListener接口和Runnable接口。Listener接口可以帮助我们捕获到窗口的移动,大小变化,和焦点变化。实现Runnable接口可以使得panel生成一个线程去控制定制的repaint()方法。
ComponentListener接口带有四个component开头的方法。它们都可以很方便地调用repaint()方法,所以窗口的背景也就可以随着窗口的移动,大小的变化而相应地更新。还有两个是焦点处理的,它们只调用refresh(),如下示意:
public void refresh( ) {
if(frame.isVisible( )) {
repaint( );
refreshRequested = true;
lastupdate = new Date( ).getTime( );
}
}
public void run( ) {
try {
while(true) {
Thread.sleep(250);
long now = new Date( ).getTime( );
if(refreshRequested &&
((now - lastupdate) > 1000)) {
if(frame.isVisible( )) {
Point location = frame.getLocation( );
frame.hide( );
updateBackground( );
frame.show( );
frame.setLocation(location);
refresh( );
}
lastupdate = now;
refreshRequested = false;
}
|