日常使用的很多軟件,裏面的一些組件(圖片、按鈕等等)可以在窗口裏面拖動。這是怎麼實現的呢?下面我就來分享一下Java的可拖動組件演示。
我們主要要用到Java裏面的鼠標事件。
首先要弄清楚,Java中,我們的屏幕內有一個座標系。其中屏幕的左頂點爲(0,0),自左向右爲x軸正方向,自上而下爲y軸正方向,例如這個屏幕截圖:
我們常用的JFrame方法setLocation方法(設置窗口位置)中,設置的座標就是相對於這個屏幕內座標系而言。窗口左頂點位置即爲窗口位置。
當然,鼠標監聽器可以獲取鼠標在屏幕內的座標。
然後,Java中對於一個窗口而言,其窗口內部是有一個座標系的。其中窗口的左頂點爲(0,0),自左向右爲x軸正方向,自上而下爲y軸正方向,例如這個窗口:
明白了窗口內的座標系,我們就可以設置窗口組件的位置了。
設置組件位置都用setBounds方法,例如給JLabel對象設置位置:
JLabel l=new JLabel("組件");
l.setBounds(10,10,120,169);
//setBounds用法:組件對象名.setBounds(x座標,y座標,組件寬,組件高); 座標是指這個窗口的座標系的座標
上面組件的位置指組件的左頂點所在位置(座標)。
組件和窗口座標系如下圖:
通過窗口的鼠標監聽器,我們還可以獲取鼠標在窗口裏面的座標是多少。
同樣的,任何一個窗口組件也有它的內部座標系,組件左頂點爲(0,0),自左向右爲x軸正方向,自上而下爲y軸正方向,如圖:
這樣給組件添加鼠標監聽器,還可以獲取鼠標在這個組件內位置。
上面就介紹了屏幕座標系(整個電腦屏幕而言)、窗口座標系(整個窗口而言)和窗口組件座標系(只對這個組件而言)三種座標系,大家千萬不能混淆!
明白了這些座標的含義,那麼思路就很清晰了:我們只要通過監聽器獲取鼠標點擊、拖動時在各個座標系內的實時位置座標,再通過計算,然後setBounds實時設置組件位置,不就可以了嗎?
首先,我們先設置兩個全局int值,代表鼠標在組件內按下時的位置:
static int mlx; //代表鼠標在組件裏面的x座標(組件座標系)
static int mly; //代表鼠標在組件裏面的y座標(組件座標系)
再建立一個全局JLabel對象:
static JLabel l=new JLabel(new ImageIcon("圖片路徑"));
JLabel對象既可以設置文字內容也可以設置圖片內容,此處不過多贅述。
我們用鼠標拖一個東西,肯定是先點擊再(按住鼠標不放)拖動,所以先獲取點擊時位置,再獲取拖動時的實時位置。(常識2333)
那麼,先給JLabel對象添加一個鼠標監聽器,獲取鼠標先點擊這個組件時鼠標所在組件座標系內的位置座標:
l.addMouseListener(new MouseAdapter() { //鼠標點擊事件
public void mousePressed(MouseEvent e) {
mlx=e.getPoint().x;
mly=e.getPoint().y;
}
});
然後,再給JLabel對象添加一個鼠標動作監聽器,獲取鼠標在拖動這個組件時鼠標所在組件座標系內和屏幕座標系內的實時位置座標,並獲取窗口在屏幕內的座標,加以計算實時設置組件在窗口中的位置:
l.addMouseMotionListener(new MouseMotionAdapter() { //鼠標拖動事件
public void mouseDragged(MouseEvent e) {
l.setBounds(e.getXOnScreen()-jf.getX()-mlx,e.getYOnScreen()-jf.getY()-mly,120,169);
}
});
上面,e.getXOnScreen()是獲取鼠標在屏幕的x座標,e.getYOnScreen()是獲取鼠標在屏幕的y座標(屏幕座標系內)
jf是我的窗口對象(JFrame)的名稱,jf.getX()是獲取窗口在屏幕內x座標,jf.getY()是獲取窗口在屏幕內y座標(屏幕座標系內)
根據這三個座標,即可得出拖動後組件應該在的位置。
設置了這麼兩個鼠標監聽器,就成功實現了組件拖動了!
效果:
完整代碼:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class ActCoTest {
static int mlx;
static int mly;
static JLabel l=new JLabel(new ImageIcon("res\\drgt.png"));
public static void main(String[] args) {
JFrame jf=new JFrame();
jf.setUndecorated(true); //窗口去邊框
jf.setSize(750,500);
jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
Toolkit kit=Toolkit.getDefaultToolkit();
Dimension sc=kit.getScreenSize();
jf.setLocation(sc.width/2-200,sc.height/2-100);
l.setBounds(30,65,120,169); //先初始化JLabel位置
l.addMouseListener(new MouseAdapter() { //鼠標點擊事件
public void mousePressed(MouseEvent e) {
mlx=e.getPoint().x; //獲取鼠標在組件內x座標並賦值給mlx(組件座標系)
mly=e.getPoint().y; //獲取鼠標在組件內y座標並賦值給mly(組件座標系)
}
});
l.addMouseMotionListener(new MouseMotionAdapter() { //鼠標拖動事件
public void mouseDragged(MouseEvent e) {
l.setBounds(e.getXOnScreen()-jf.getX()-mlx,e.getYOnScreen()-jf.getY()-mly,120,169);
}
});
JPanel jp=new JPanel();
jp.add(l);
jp.setLayout(null);
jf.getContentPane().add(jp);
jf.show();
}
}