1. 程式人生 > >關於java下實現視窗貼邊自動縮排

關於java下實現視窗貼邊自動縮排

最近要做一個類似於人人的大作業,於是有了讓視窗貼邊自動縮排這個想法,然後具體程式碼感謝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");
	}

}