




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、窗体顶端关于Swing实现透明窗体的。我也很喜欢,收藏! Editor's note: The following example from Swing Hacks is one of the book's most visually daring hacks-mimicking the arbitrarily shaped window you might see in an native MP3 player skin. The hack here is necessitated by the
2、 fact that Java doesn't support non-rectangular windows, so the only option to make this work is for the Java window to be aware of what's under it, and to handle the imaging of areas within the window's rectangle but not within its arbitrary shape. Read on for how this is accomplished.
3、Create translucent and shaped windows, while avoiding native code, with clever use of a screenshot.One of the most commonly requested Swing features is transparent windows. Also called shaped windows, these are windows that have transparent portions, allowing the desktop background and other program
4、s to shine through. Java doesn't provide any way of creating transparent windows without using the Java Native Interface (JNI) (and even then the native platform must support transparency as well), but that's not going to stop us. We can cheat using one of my favorite techniques, the screens
5、hot.The process of faking a transparent window is basically:1. Take a screenshot before the window is shown.2. Use that screenshot as the background of the window.3. Adjust the position so that the screenshot and the real screen line up, creating the illusion of transparency.This is the easy part. T
6、he hard part is updating the screenshot when the window moves or changes.To start off, create a JPanel subclass that can capture the screen and paint it as the background, as shown in Example 6-1Example 6-1. A transparent background componentpublic class TransparentBackground exte
7、nds Jcomponent private JFrame frame; private Image background; public TransparentBackground(JFrame frame) this .frame = frame;
8、60; updateBackground( );public void updateBackground( ) try Robot rbt = new Robot( ); Toolkit t
9、k = Toolkit.getDefaultToolkit( ); Dimension dim = tk.getScreenSize( ); background = rbt.createScreenCapture(
10、; new Rectangle( 0 , 0 ,( int )dim.getWidth( ),( int )dim.getHeight( ); catch (Exception ex) p(ex.toString( ); ex.printStackTrace( );
11、 public void paintComponent(Graphics g) Point pos = this .getLocationOnScreen( ); Point offset = new Point( - pos.x, - pos.y); g.drawImag
12、e(background,offset.x,offset.y, null );First, the constructor saves a reference to the parent JFrame; then it calls updateBackground( ), which captures the entire screen using . createScreenCapture( ), and saves the capture in the background variable. paintComponent( ) gets the panel's absolute
13、position on screen and then fills the panel with the background image, shifted to account for the panel's location. This makes the fake background image line up with the real background, giving the appearance of transparency.You can run this with a simple main( ) method, dropping a few component
14、s onto the panel and putting it into a frame:public static void main(String args) JFrame frame = new JFrame( " Transparent Window " ); TransparentBackground bg = new
15、 TransparentBackground(frame); bg.setLayout( new BorderLayout( ); JButton button = new JButton( " This is a button " ); bg.add( " North " ,button); JLabel
16、160;label = new JLabel( " This is a label " ); bg.add( " South " ,label); frame.getContentPane( ).add( " Center " ,bg); frame.pack( );
17、;frame.setSize( 150 , 100 ); frame.show( ); The code produces a window that looks like Figure 6-1. The code is pretty simple, but it has two big flaws. First, if the window is moved, the background won't be refreshed automatically. paintComponent( ) only gets called w
18、hen the user resizes the window. Second, if the screen ever changes, it won't match up with the background anymore.You really don't want to update the screenshot often, though, because that involves hiding the window, taking a new screenshot, and then reshowing the windowall of which is disc
19、oncerting to the user. Actually detecting when the rest of the desktop changes is almost impossible, but most changes happen when the foreground window changes focus or moves. If you accept this idea (and I do), then you can watch for those events and only update the screenshot when that happens:pub
20、lic class TransparentBackground extends JComponent implements ComponentListener, WindowFocusListener, Runnable private JFrame fr
21、ame; private Image background; private long lastupdate = 0 ; public boolean refreshRequested = true ; public TransparentBackground(JFra
22、me frame) this .frame = frame; updateBackground( ); frame.addComponentListener( this ); &
23、#160; frame.addWindowFocusListener( this ); new Thread( this ).start( ); public void componentShown(ComponentEvent evt) repaint( );
24、; public void componentResized(ComponentEvent evt) repaint( ); public void componentMoved(ComponentEvent evt) repaint( ); public void componentHidd
25、en(ComponentEvent evt) public void windowGainedFocus(WindowEvent evt) refresh( ); public void windowLostFocus(WindowEvent evt) refresh( )
26、; First, make the panel, TransparentWindow, implement ComponentListener, WindowFocusListener, and Runnable. The listener interfaces will let the panel catch events indicating that the window has moved, been resized, or the focus changes. Implementing Runnable will let the panel create a thread
27、 to handle custom repaint( )s.The implementation of ComponentListener involves the four methods beginning with component. They each simply call repaint( ) so that the background will be updated whenever the user moves or resizes the window. Next are the two window focus handlers, which just call ref
28、resh( ), as shown here:public void refresh( ) if (frame.isVisible( ) repaint( ); refreshRequested = true ;
29、; lastupdate = new Date( ).getTime( ); public void run( ) try while ( true )
30、0; Thread.sleep( 250 ); long now = new Date( ).getTime( ); if (refreshRequested &&
31、amp; (now - lastupdate) > 1000 ) if (frame.isVisible( )
32、160; Point location = frame.getLocation( ); frame.hi
33、de( ); updateBackground( ); frame.show( );
34、; frame.setLocation(location); refresh( );
35、60; lastupdate = now; refreshRequested =
36、60; false ; catch (Exception ex)
37、; p(ex.toString( ); ex.printStackTrace( ); refresh( ) ensures that the frame is visible and schedule
38、s a repaint. It also sets the refreshRequested boolean to true and saves the current time, which will become very important shortly.The run( ) method sleeps constantly, waking up every quarter-second to see if a refresh has been requested, and whether it has been more than a second since the last re
39、fresh. If more than a second has passed and the frame is actually visible, then run( ) will save the frame location, hide it, update the background, then put the frame back in place and call refresh( ). This ensures that the background is never updated more than needed.So, why all of this rigmarole
40、about using a thread to control refreshing? One word: recursion. The event handlers could simply call updateBackground( ) and repaint( ) directly, but hiding and showing the window to generate the screenshot would cause more focus-changed events. These would then trigger another background update, c
41、ausing the window to hide again, and so on, creating an infinite loop. The new focus events are generated a few milliseconds after refresh( ) is processed, so simply checking for an isRecursing flag wouldn't stop a loop.Additionally, any user action that would change the screen will probably cre
42、ate lots of events, not just one. It's just the last event that should trigger updateBackground( ), not the first. To handle all these issues, the code creates a thread that watches for repaint requests and only processes a new screenshot if it hasn't already been done in the last 1,000 mill
43、iseconds. If the user generates events continuously for five seconds (searching for that lost browser window, for example), then only when everything else has settled down for a second will the refresh actually happen. This ensures that users won't have a window disappear out from under them whi
44、le they are moving things around.Another annoyance is that the window still has its border, which sort of ruins the effect of having a transparent background. Unfortunately, removing the borders with setUndecorated(true) would also remove the titlebar and window controls. This probably isn't too
45、 much of a problem, though, because the types of applications that typically use shaped windows usually have draggable backgrounds Hack #34.Here's a simple test program to put this into action:public static void main(String args) JFrame
46、frame = new JFrame( " Transparent Window " ); frame.setUndecorated( true ); TransparentBackground bg = new TransparentBackground(frame); bg.snapBackground( ); bg.setLayout( new BorderLayout( ); &
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教师教育教学反思的创新路径试题及答案
- 如何解读2025年创业扶持政策的变化试题及答案
- 河北检察院试题及答案
- 智能网联汽车技术的商业模式探讨试题及答案
- 新房装修家具设计中的流行元素解析试题及答案
- 旅游景区2025年旅游与环境保护社会稳定风险评估报告
- 王牌战士考试试题及答案
- 安全工程师知识更新与实务结合2025年试题及答案
- 智能化与新能源融合趋势试题及答案
- 政策对创业实践的指导意义试题及答案
- 成都青羊小升初5+4考试习题真题
- (正式版)JBT 14582-2024 分户减压阀
- 演唱会安保方案及应急预案
- 《新闻评论》课件 第四章 新闻评论的基本类型
- 《齿轮介绍》课件
- 民营医院分析报告
- 知心慧学提分宝-数学
- 吉祥航空飞行报告
- 《曼陀罗绘画疗愈-初三减压》PPT
- 彩钢板屋面监理细则
- 文艺复兴史学习通超星课后章节答案期末考试题库2023年
评论
0/150
提交评论