在创建JFrame对象的过程中,如果我们往Container容器里添加一个JPanel容器会发现,使用EventQueue异步事件指派机制来保存事件然后再用AWTEvent来获取事件时,由于AWTEvent是所有 AWT 事件的根事件类,那么在保存MouseEvent的时候将AWTEvent强制转换成MouseEvent就会发生问题,由于AWTEvent获取鼠标事件时时以JFrame为标准,在转换后会造成坐标的不一致,实验证明是因为JPanel的坐标和JFrame坐标的不一致产生的,所以我们必须知道JFrame窗口的厚度大小方便我们进行处理。
举个栗子:
某年JAVA计算机二级考试题:
创建一个窗口,窗口的按钮按下后在窗口里通过点击鼠标左键分别定义两点画出一条直线。
代码如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Demo01 {
public static void main(String[] args) {
@SuppressWarnings("unused")
JFrame frame = new myFrame();
}
}
@SuppressWarnings("serial")
class myJPanel extends JPanel implements ActionListener{
myJPanel(){
JButton button = new JButton("Draw lint");
add(button);
button.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
Graphics g = getGraphics();
Point p = this.getClick();
g.drawOval(p.x-2, p.y-2, 4, 4);
Point q = getClick();
g.drawOval(q.x-2, q.y-2, 4, 4);
g.drawLine(p.x, p.y, q.x, q.y);
g.dispose();
}
public Point getClick() {
EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
while(true) {
try {
AWTEvent evt = eq.getNextEvent();
if(evt.getID()==MouseEvent.MOUSE_PRESSED) {
MouseEvent mevt = (MouseEvent) evt;
Point p = mevt.getPoint();
//Point top = this.getRootPane().getLocation();
//p.x -= top.x;
//p.y -= top.y;
return p;
}
}catch(InterruptedException e) {}
}
}
}
@SuppressWarnings("serial")
class myFrame extends JFrame{
myFrame(){
setTitle("java");
setSize(300,200);
addWindowListener(new WindowAdapter(){
@SuppressWarnings("unused")
public void windwoClosing(WindowEvent e) {
System.exit(0);
}
});
Container containerPane = getContentPane();
containerPane.add(new myJPanel());
this.setVisible(true);
}
}
我们不难发现,如果我们注释掉getClick的三条语句,那么获取的坐标就会发生异常,所以我们只能在x轴和y轴上减去窗口框的厚度,就能解决问题。下面的代码可以算出左右下边框和标题栏的厚度。
public class Demo {
public static void main(String[] args) {
// 初始化参数
int width = 500;
int height = 200;
// 实例化窗体
JFrame window = new JFrame();
// 设置窗体大小
window.setSize(width, height);
// 点击关闭窗口强制关闭
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 显示窗体
window.setVisible(true);
// 获取标题栏高度
System.out.println("标题栏高度:"+window.getInsets().top);
// 获取窗口框左右厚度
System.out.println("窗口框左右厚度为:"+(window.getWidth()-window.getContentPane().getWidth())/2);
// 获取窗口框底部厚度
System.out.println("窗口框底部厚度为:"+(window.getHeight()-window.getContentPane().getHeight()-window.getInsets().top));
}
}
输出结果
标题栏高度:31
窗口框左右厚度为:8
窗口框底部厚度为:8
结果和Demo01所注释掉的top的xy一致。