關於java下實現視窗貼邊自動縮排
阿新 • • 發佈:2019-02-07
最近要做一個類似於人人的大作業,於是有了讓視窗貼邊自動縮排這個想法,然後具體程式碼感謝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");
}
}