最近要做一个类似于人人的大作业,于是有了让窗口贴边自动缩进这个想法,然后具体代码感谢qusic童鞋,基本基于他提供的代码实现
这个是主类:
import java.awt.BorderLayout;
import java.awt.Insets;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
* @author qusic
*
*/
public class AutoHiddenFrame extends JFrame
{
public static void main(String args[])
{
new AutoHiddenFrame();
}
public static final int NORMAL = 0; //窗体的普通状态
public static final int CANHIDD = 1; //窗体位于屏幕边缘,可以隐藏的状态
public static final int HIDDEN = 2; //窗体处于隐藏状态
private int state = NORMAL; //窗体的状态,让它初始化为普通状态
private Point hiddenPoint; //隐藏窗体时,窗体的位置
private Point visiblePoint; //窗体处于显示状态时的位置
private JLabel infoLabel; //用于显示信息的JLabel;
public AutoHiddenFrame()
{
JPanel p = new JPanel(new BorderLayout()) {
public Insets getInsets()
{
return new Insets(3,3,3,3);
}
};
setContentPane(p); //替换掉原来的ContentPane,换上一个带有Insets的,至于为什么去看WindowMouseListener类
infoLabel = new JLabel();
add(infoLabel,BorderLayout.SOUTH);
setSize(300,200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
new WindowLocationListener(this);
new WindowMouseListener(this);
WindowLocationListener.checkAutoHiddenState(this);//刚出来就检查一下窗体的位置
}
/**
* @param newState 新的状态
* 一定要是此类中定义的3中状态之一
*/
public void setStates(int newState)
{
if(newState == NORMAL || newState == CANHIDD || newState == HIDDEN)
{
state = newState;
}
}
/*
* 返回状态,注意此方法和setStates方法区别与JFrame中的setState()和getState()方法
*/
public int getStates()
{
return state;
}
/*
* 设置要显示时窗体的坐标
*/
public void setVisiblePoint(Point point)
{
visiblePoint = point;
}
/*
* 设置要隐藏是窗体的坐标
*/
public void setHiddenPoint(Point point)
{
hiddenPoint = point;
}
public void moveToVisible()
{
if(visiblePoint!=null)
{
WindowMover.moveToPoint(this, visiblePoint);
setStates(CANHIDD);
}
}
public void moveToHidden()
{
if(hiddenPoint!=null)
{
WindowMover.moveToPoint(this, hiddenPoint);
setStates(HIDDEN);
}
}
public void showInfo(String info)
{
infoLabel.setText(info);
}
public void clearInfo()
{
infoLabel.setText("");
}
}
检查窗体位置:
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
public class WindowLocationListener extends ComponentAdapter
{
public static final int HIDDEN_BOUND = 3; //当窗体进入到屏幕边缘3像素以内就可以隐藏
public static final int VISIBLE_BOUND = 5; //当窗体隐藏后要有5像素的部分露出来,不能完全隐藏
AutoHiddenFrame frame;
public WindowLocationListener(AutoHiddenFrame a)
{
frame = a;
frame.addComponentListener(this);
}
public void componentMoved(ComponentEvent e)
{
checkAutoHiddenState(frame);
//当窗体移动就调用检查方法;
}
public static void checkAutoHiddenState(AutoHiddenFrame frame)
{
//当窗体状态不是隐藏的,再进行检查
if (frame.getStates() != AutoHiddenFrame.HIDDEN)
{
//首先获得屏幕的大小和窗体的坐标
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Point hiddenPoint = frame.getLocation();
Point visiblePoint = null;
boolean canhidden = false;
//当窗体位于左边边缘
if (hiddenPoint.x <= HIDDEN_BOUND)
{
hiddenPoint.move(VISIBLE_BOUND - frame.getWidth(), hiddenPoint.y);
visiblePoint = new Point(0 , hiddenPoint.y);
canhidden = true;
}
// 当窗体位于上边
else if (hiddenPoint.y <= HIDDEN_BOUND)
{
hiddenPoint.setLocation(hiddenPoint.x,VISIBLE_BOUND - frame.getHeight());
visiblePoint = new Point( hiddenPoint.x , 0 );
canhidden = true;
}
// 当窗体位于右边
else if (hiddenPoint.x + frame.getWidth() >= screenSize.width - HIDDEN_BOUND)
{
hiddenPoint.setLocation(screenSize.width - VISIBLE_BOUND, hiddenPoint.y);
visiblePoint = new Point(screenSize.width - frame.getWidth(), hiddenPoint.y);
canhidden = true;
}
if(canhidden)
{
//如果符合以上几种情况的一种就可以隐藏
frame.setVisiblePoint(visiblePoint);
frame.setHiddenPoint(hiddenPoint);
frame.setStates(AutoHiddenFrame.CANHIDD);
frame.showInfo("进入可隐藏区域!");
}else {
//如果不可以隐藏,那就是离开了边缘了
if(frame.getStates() == AutoHiddenFrame.CANHIDD)
{
frame.showInfo("离开可应藏区域!");
}
frame.setVisiblePoint(frame.getLocation());
frame.setStates(AutoHiddenFrame.NORMAL);
}
}
}
}
检查鼠标是否位于窗体上:
import java.awt.Container;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class WindowMouseListener extends MouseAdapter implements ActionListener ,WindowFocusListener
{
private Timer timer;
private AutoHiddenFrame frame;
Container container;
public WindowMouseListener(AutoHiddenFrame a)
{
frame = a;
container = frame.getContentPane();
container.addMouseListener(this);
//注册鼠标侦听器到ContentPane上,因为我们可以加大它的Insets以提高鼠标进入和离开的灵敏度
frame.addWindowFocusListener(this);
//注册一个焦点侦听器到窗体上
timer = new Timer(2000, this);
timer.setRepeats(false);
}
public void mouseEntered(MouseEvent e)
{
//当鼠标进入,就显示窗体
if (frame.getStates() == AutoHiddenFrame.HIDDEN)
{
frame.moveToVisible();
}else {
frame.clearInfo();
}
}
public void mouseExited(MouseEvent e)
{
//当鼠标离开,启动计时器
if (frame.getStates() == AutoHiddenFrame.CANHIDD)
{
if (!container.contains(e.getPoint()))
{
frame.showInfo(timer.getDelay()/1000+"秒后自动隐藏窗口!");
//System.out.println("Mouse has exited the Dialog!");
timer.restart();
}
}
}
public void actionPerformed(ActionEvent e)
{
//计时器到期,检查鼠标是不是还在此窗体里面,不再的话,再开始隐藏
Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, container);
if (!container.contains(p)
&& frame.getStates() == AutoHiddenFrame.CANHIDD)
{
frame.moveToHidden();
}else
{
frame.clearInfo();
}
}
public void windowGainedFocus(WindowEvent e)
{
//得到焦点检查鼠标是不是在窗体上
Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, container);
if (container.contains(p) && frame.getStates() == AutoHiddenFrame.HIDDEN)
{
frame.moveToVisible();
}
}
public void windowLostFocus(WindowEvent e)
{
//失去焦点,启动计时器
if(frame.getStates() == AutoHiddenFrame.CANHIDD)
{
frame.showInfo("2秒后自动隐藏窗口!");
timer.restart();
}
}
}
最后是窗体移动:
import java.awt.Point;
import java.awt.event.ComponentListener;
import javax.swing.JFrame;
public class WindowMover extends Thread
{
public static void moveToPoint(JFrame dialog,Point targetPoint)
{
new WindowMover(dialog,targetPoint).start();
}
private static final int FRAMES = 15; //最多移动多少动画帧
private JFrame window; // 要移动的窗口
private Point point; // 目的坐标
private int index; //当前帧数
private int addedX; //每次移动的X坐标增量
private int addedY; //每次移动的Y坐标的增量
ComponentListener componentListeners[];//组件侦听器数组
/*
* 定义私有的构造方法,应调用静态方法moveToPoint;
*/
private WindowMover(JFrame window, Point targetPoint)
{
this.window = window;
window.getGlassPane().setVisible(true);
//设置此窗体的GlassPane为显示的,以阻止子组件接收鼠标事件,减少事件触发
//同样,移除此窗体上的组件侦听器,防止再次触发窗体移动事件
componentListeners = window.getComponentListeners();
for(ComponentListener cl:componentListeners)
{
window.removeComponentListener(cl);
}
Point wl = window.getLocation();
point = targetPoint;
index = 0; //初始化帧书为0;
//计算每次移动量
addedX = (point.x - wl.x) / FRAMES;
if (addedX == 0 && point.x != wl.x)
{
addedX = point.x < wl.x ? -1 : 1;
}
addedY = (point.y - wl.y) / FRAMES;
if (addedY == 0 && point.y != wl.y)
{
addedY = point.y < wl.y ? -1 : 1;
}
}
public void run()
{
if (window.getLocation().equals(point))
return;// 如果已在目的点,则返回
if (!window.isVisible())
return;// 如果窗口是不可视的则返回
while (index < FRAMES)
{
Point p = window.getLocation();
if (p.x != point.x)
p.translate(addedX, 0);
if (p.y != point.y)
p.translate(0, addedY);
window.setLocation(p);
index++;
try
{
Thread.sleep(15);
} catch (Exception e)
{
}
}
window.setLocation(point);
//还原所做的操作
window.getGlassPane().setVisible(false);
for(ComponentListener cl:componentListeners)
{
window.addComponentListener(cl);
}
//释放资源,使gc可以回收此对象
window = null;
point = null;
componentListeners =null;
System.out.println("finsh Moved");
}
}