透明界面实现.docx
《透明界面实现.docx》由会员分享,可在线阅读,更多相关《透明界面实现.docx(19页珍藏版)》请在冰点文库上搜索。
![透明界面实现.docx](https://file1.bingdoc.com/fileroot1/2023-5/8/17e7ba78-753b-45af-a9e3-50b4542b077c/17e7ba78-753b-45af-a9e3-50b4542b077c1.gif)
透明界面实现
想做一个透明的界面,无奈Java中的虽然有JFrame.setOpacity();但是这个东西,不好用。
后来发现是通过抓取屏幕背景作为自己的背景图片。
然后实现伪透明。
桌面背景是很有可能更换的,因此要在适当的时机抓取新的屏幕背景最为自己的背景。
这个似乎可以用线程来实现,但是感觉很消耗资源,毕竟桌面背景不是每隔一段时间就更新的。
先解释一个屏幕绘制的这个过程。
首先是抓取整个屏幕,然后我们选择合适的坐标,将我们的界面所覆盖的那一部分屏幕区域,绘制上去。
这样当我们的界面移动时,只要修改适当的坐标,以取得当前覆盖的屏幕区域进行绘制。
下面是这个代码片段。
有一个地方在解释一下。
Java代码
1@Override
2
3publicvoidpaintComponent(Graphicsg){
4
5super.paintComponent(g);
6
7//this.paint(g);
8
9
10
11Pointpos=this.getLocationOnScreen();
12
13Pointoffset=newPoint(-pos.x,-pos.y);
14
15//有一个问题就是为什么这边要用复数
16
17g.drawImage(background,offset.x,offset.y,null);
18
19}
我们看到这个offset.x和offset.y是负数,也许我们感到困惑。
这个只要搞张图片,用这个方法放在JFrame上,实现一下就明白了。
我们分析一下抓取屏幕背景的过程:
当我们的界面抓取屏幕背景并作为自己的背景进行绘制后,如果屏幕的背景发生了变化,那么一定是我们的界面失去了焦点。
这个时候操作的不在是我们的界面,因此可以将其隐藏起来。
而当我们要操作我们的界面时,即获得焦点时,我们这时候再抓取屏幕背景就可以了。
因此不需要用线程的,用监听器就可以。
除了要用到焦点的监听器之外,我们还需要组件监听器,这个是监听界面的移动,大小的变化等,以及时重绘。
这个思路是没有问题的。
在实现的过程中可能会出现一些小问题。
一些让我们头痛的BUG。
第一个BUG:
我们可能会把自己本身作为背景的一部分抓取过来,这就露馅了。
于是当我们的界面失去焦点时,我们必须把这个界面隐藏起来,放在屏幕之外的位置。
这样抓取的时候,就不会露馅了。
第二个BUG:
我们思路是这样的,windowsGainedFocus(WindowEvente)即得到焦点的监听器,方法的内容是这样的,抓取屏幕背景,进行重绘。
windowsLostFocus(WindowEvente)失去焦点监听器,方法的内容是,将界面隐藏起来。
我们的步骤是这样的,我们抓取屏幕背景是在这样的情况发生的,我们失去了焦点,界面隐藏,然后得到焦点,抓取屏幕,绘制屏幕。
但是这个步骤在程序运行刚开始时是不成立的,即程序一开始我们就直接得到了焦点,这个时候我们抓取屏幕,但是由于我们的界面还没有来的及隐藏,这就会出现第一个BUG的情况。
解决方法是:
设置一个标志fresh,是否抓取屏幕。
还有第三个BUG。
这个我们先等一下,看一下解决了上述两个问题之后的效果。
下面是完整代码(两个类):
--EndFragment-->
:
Java代码
20packagetransparentUI2;
21
22importjava.awt.Point;
23importjava.awt.event.ComponentEvent;
24importjava.awt.event.ComponentListener;
25importjava.awt.event.MouseEvent;
26importjava.awt.event.MouseListener;
27importjava.awt.event.WindowEvent;
28importjava.awt.event.WindowFocusListener;
29
30importjavax.swing.JFrame;
31
32publicclassTestUIextendsJFrameimplementsWindowFocusListener,
33ComponentListener{
34privateJPaneUIjp;
35privatebooleanfresh=false;
36privatePointtem_point;
37
38
39publicstaticvoidmain(Stringargs[]){
40newTestUI();
41}
42
43publicTestUI(){
44this.setSize(200,300);
45this.setLocationRelativeTo(null);
46this.setDefaultCloseOperation(3);
47jp=newJPaneUI();
48this.add(jp);
49this.addComponentListener(this);
50this.addWindowFocusListener(this);
51
52this.setVisible(true);
53
54}
55
56@Override
57publicvoidwindowGainedFocus(WindowEvente){
58//TODOAuto-generatedmethodstub
59this.refresh();
60fresh=false;
61}
62
63@Override
64publicvoidwindowLostFocus(WindowEvente){
65//TODOAuto-generatedmethodstub
66
67fresh=true;
68tem_point=this.getLocation();//记录屏幕消失之前的坐标
69this.setLocation(-2000,-2000);
70}
71
72publicvoidrefresh(){
73
74if(fresh){
75
76jp.updateBackground();
77//此时P应该重新被赋值了p存放应该就是刷新之前的位置
78this.setLocation(tem_point);
79if(tem_point.x<0||tem_point.y<0)
80this.setLocation(0,0);
81jp.repaint();
82
83}
84}
85
86
87@Override
88publicvoidcomponentResized(ComponentEvente){
89//TODOAuto-generatedmethodstub
90
91this.repaint();
92}
93
94@Override
95publicvoidcomponentMoved(ComponentEvente){
96//TODOAuto-generatedmethodstub
97//this.updateBackground();
98this.repaint();
99}
100
101@Override
102publicvoidcomponentShown(ComponentEvente){
103//TODOAuto-generatedmethodstub
104System.out.println("是不是在执行这个方法");
105//refresh();
106this.repaint();
107}
108
109@Override
110publicvoidcomponentHidden(ComponentEvente){
111//TODOAuto-generatedmethodstub
112
113}
114
115
116}
Java代码
117packagetransparentUI2;
118
119importjava.awt.Dimension;
120importjava.awt.Graphics;
121importjava.awt.Image;
122importjava.awt.Point;
123importjava.awt.Rectangle;
124importjava.awt.Robot;
125importjava.awt.Toolkit;
126importjava.awt.event.ComponentEvent;
127importjava.awt.event.ComponentListener;
128importjava.awt.event.WindowEvent;
129importjava.awt.event.WindowFocusListener;
130
131importjavax.swing.JFrame;
132importjavax.swing.JPanel;
133
134publicclassJPaneUIextendsJPanel{
135privateJFrameframe;
136privateImagebackground;
137privatePointfinal_point;
138
139publicJPaneUI(){
140updateBackground();
141}
142
143//获得当前屏幕快照
144publicvoidupdateBackground(){
145try{
146Robotrbt=newRobot();
147Toolkittk=Toolkit.getDefaultToolkit();
148Dimensiondim=tk.getScreenSize();
149background=rbt.createScreenCapture(newRectangle(0,0,(int)dim
150.getWidth(),(int)dim.getHeight()));
151}catch(Exceptionex){
152}
153
154}
155
156@Override
157publicvoidpaintComponent(Graphicsg){
158super.paintComponent(g);
159//this.paint(g);
160
161Pointpos=this.getLocationOnScreen();
162Pointoffset=newPoint(-pos.x,-pos.y);
163//有一个问题就是为什么这边要用复数
164g.drawImage(background,offset.x,offset.y,null);
165}
现在将第三个BUG:
本来是这样的我们操作另一个界面时,我们的界面会失去焦点,而等到我们操作我们的界面时,我们才能获得焦点。
但是现在有一个例外的情况,就是我们操作的另一个界面的最小化或者是关闭的按钮,这样我们的界面在失去焦点之后,马上得到焦点。
就是因为这个时间很短,所以我们抓取屏幕的动作,抓到不改抓到的东西就是其他界面消失过程中的图像。
我们的界面消失有一个渐变的过程,这个过程被我们抓到了,然后的结果就是这个样子。
如图:
--EndFragment-->
第一张是word的界面,当最小化时,我们的界面就会捕捉到他的一个渐变的过程。
这个确实很烦人。
解决办法就是,遇到这种情况时,系统多抓几次屏幕。
但是会出另一个问题,就是屏幕会闪烁,于是双缓冲也得来。
下面是完整的代码:
Java代码
166packagetransparentUI;
167
168importjava.awt.Point;
169importjava.awt.event.ComponentEvent;
170importjava.awt.event.ComponentListener;
171importjava.awt.event.MouseEvent;
172importjava.awt.event.MouseListener;
173importjava.awt.event.WindowEvent;
174importjava.awt.event.WindowFocusListener;
175
176importjavax.swing.JFrame;
177
178publicclassTestUIextendsJFrameimplementsWindowFocusListener,
179ComponentListener,MouseListener{
180privateJPaneUIjp;
181privatebooleanfresh=false;
182privatePointtem_point;
183privateintmany_fresh;
184
185publicstaticvoidmain(Stringargs[]){
186newTestUI();
187}
188
189publicTestUI(){
190this.setSize(200,300);
191this.setLocationRelativeTo(null);
192this.setDefaultCloseOperation(3);
193jp=newJPaneUI();
194this.add(jp);
195this.addComponentListener(this);
196this.addWindowFocusListener(this);
197this.addMouseListener(this);
198this.setVisible(true);
199
200}
201
202@Override
203publicvoidwindowGainedFocus(WindowEvente){
204//TODOAuto-generatedmethodstub
205this.refresh();
206fresh=false;
207}
208
209@Override
210publicvoidwindowLostFocus(WindowEvente){
211//TODOAuto-generatedmethodstub
212
213fresh=true;
214tem_point=this.getLocation();//记录屏幕消失之前的坐标
215this.setLocation(-2000,-2000);
216}
217
218publicvoidrefresh(){
219//inti=6;
220if(fresh){
221if(many_fresh<=1){
222jp.updateBackground();
223//此时P应该重新被赋值了p存放应该就是刷新之前的位置
224this.setLocation(tem_point);
225if(tem_point.x<0||tem_point.y<0)
226this.setLocation(0,0);
227jp.repaint();
228}
229while(many_fresh>1){
230//p=this.getLocationOnScreen();
231this.setLocation(-2000,-2000);
232
233jp.updateBackground();
234//此时P应该重新被赋值了p存放应该就是刷新之前的位置
235this.setLocation(tem_point);
236if(tem_point.x<0||tem_point.y<0)
237this.setLocation(0,0);
238jp.repaint();
239try{
240Thread.sleep(5);
241}catch(InterruptedExceptione){
242//TODOAuto-generatedcatchblock
243e.printStackTrace();
244}
245
246many_fresh--;
247}
248
249}
250}
251
252
253@Override
254publicvoidcomponentResized(ComponentEvente){
255//TODOAuto-generatedmethodstub
256
257this.repaint();
258}
259
260@Override
261publicvoidcomponentMoved(ComponentEvente){
262//TODOAuto-generatedmethodstub
263//this.updateBackground();
264this.repaint();
265}
266
267@Override
268publicvoidcomponentShown(ComponentEvente){
269//TODOAuto-generatedmethodstub
270System.out.println("是不是在执行这个方法");
271//refresh();
272this.repaint();
273}
274
275@Override
276publicvoidcomponentHidden(ComponentEvente){
277//TODOAuto-generatedmethodstub
278
279}
280
281@Override
282publicvoidmouseClicked(MouseEvente){
283//TODOAuto-generatedmethodstub
284
285}
286
287@Override
288publicvoidmousePressed(MouseEvente){
289//TODOAuto-generatedmethodstub
290
291}
292
293@Override
294publicvoidmouseReleased(MouseEvente){
295//TODOAuto-generatedmethodstub
296
297}
298
299@Override
300publicvoidmouseEntered(MouseEvente){
301//TODOAuto-generatedmethodstub
302many_fresh=1;//这个是不能改的
303System.out.println("mouseEntered这个应该执行了吧"+many_fresh);
304}
305
306@Override
307publicvoidmouseExited(MouseEvente){
308//TODOAuto-generatedmethodstub
309
310many_fresh=6;//这个时候获得焦点就要多次刷新,6次是试出来的比较好的刷新效果,当然5次或者其他的这个自己设置,
311//不要纠结这个数字,可以更改
312System.out.println("这个应该执行了吧mouseExited"+many_fresh);
313}
314
315}
Java代码
316packagetransparentUI;
317
318importjava.awt.Dimension;
319importjava.awt.Graphics;
320importjava.awt.Image;
321importjava.awt.Point;
322importjava.awt.Rectangle;
323importjava.awt.Robot;
324importjava.awt.Toolkit;
325
326
327importjavax.swing.JFrame;
328importjavax.swing.JPanel;
329
330publicclassJPaneUIextendsJPanel{