日常使用的很多软件,里面的一些组件(图片、按钮等等)可以在窗口里面拖动。这是怎么实现的呢?下面我就来分享一下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();
}
}