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 { private static final long serialVersionUID = 1L; 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()) { private static final long serialVersionUID = 1L; 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"); } }