drawString() 方法上的 MouseListener
MouseListener on a drawString() Method
如何检测文本 ("Resume", "Restart", "Quit") 我用drawString()
方法画的被点击了?
到目前为止我的代码:
public class Pause {
public Pause() {
}
public void draw(Graphics2D g) {
g.setFont(new Font("Arial", Font.BOLD, 14));
int intValue = Integer.parseInt( "ff5030",16);
g.setColor(new Color(intValue));
g.drawString("Resume", 200, 156);
g.drawString("Restart", 200, 172);
g.drawString("Quit", 200, 188);
}
}
希望你能帮助我。谢谢
@aioobe 我尽量写得简单。这里是 SSCCE:
GameFrame.java
public class GameFrame extends JFrame implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
// dimensions
public static final int WIDTH = 448;
public static final int HEIGHT = 288;
public static final double SCALE = 2.5;
// game thread
private Thread thread;
private boolean running;
private int FPS = 60;
private long targetTime = 1000 / FPS;
// image
private BufferedImage image;
private Graphics2D g;
//displays
private Pause pauseDisplay;
public GameFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.pack();
this.setLocationRelativeTo(null);
this.setPreferredSize(new Dimension((int)(WIDTH * SCALE), (int)(HEIGHT * SCALE)));
this.setBounds(100, 100, (int)(WIDTH * SCALE), (int)(HEIGHT * SCALE));
this.setLocationRelativeTo(null);
this.setFocusable(true);
this.requestFocus();
this.setVisible(true);
}
public void addNotify() {
super.addNotify();
if(thread == null) {
thread = new Thread(this);
thread.start();
}
}
private void init() {
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
}
public void run() {
init();
long start;
long elapsed;
long wait;
// game loop
while(running) {
start = System.nanoTime();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if(wait < 0) wait = 5;
try {
Thread.sleep(wait);
}
catch(Exception e) {
e.printStackTrace();
}
pauseDisplay = new Pause(this);
drawToScreen();
draw();
}
}
private void draw() {
pauseDisplay.draw(g);
}
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, (int)(WIDTH * SCALE), (int)(HEIGHT * SCALE), null);
g2.dispose();
}
public static void main(String[] args) {
GameFrame game = new GameFrame();
}
}
Pause.java
public class Pause implements MouseListener{
private Rectangle2D resumeRect;
private Rectangle2D restartRect;
public Pause(GameFrame GameFrame) {
GameFrame.addMouseListener(this);
}
public void draw(Graphics2D g) {
g.setFont(new Font("Arial", Font.BOLD, 14));
int intValue = Integer.parseInt( "ff5030",16);
g.setColor(new Color(intValue));
g.drawString("Resume", 200, 156);
resumeRect= g.getFontMetrics().getStringBounds("Resume", g);
g.drawString("Restart", 200, 172);
restartRect = g.getFontMetrics().getStringBounds("Restart", g);
g.drawString("Quit", 200, 188);
}
public void mouseClicked(MouseEvent e) {
if (resumeRect.contains(e.getPoint())) {
System.out.println("clicked");
}
System.out.println(resumeRect);
System.out.println(restartRect);
System.out.println(e.getPoint());
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
你必须记住你画线的位置。每个字符串可以有一个 Rectangle2D
。
字符串的矩形可以计算如下:
Rectangle2D r = g.getFontMetrics().getStringBounds(str, g);
(需要根据画线的位置调整rect的位置)
然后您将注册一个鼠标侦听器来检查这些矩形的点击坐标:
if (resumeRect.contains(mouseEvent.getPoint())) {
...
}
也就是说,我建议您重新考虑您的 GUI 代码,看看您是否不能为此目的使用 JLabel
或 JButton
。
关于您的修改:
您的 NullPointerException 是由于您可以在渲染图像之前(即在初始化矩形之前)单击框架。
除此之外,您还需要进行两项编辑:
您需要考虑 SCALE
。
if (resumeRect.contains(e.getPoint().getX() / GameFrame.SCALE,
e.getPoint().getY() / GameFrame.SCALE)) {
和
需要补偿drawString在基线上绘制字符串,所以矩形要从基线向上抬到文本的左上角:
g.drawString("Resume", 200, 156);
resumeRect= g.getFontMetrics().getStringBounds("Resume", g);
// Add this:
resumeRect.setRect(200,
156 - g.getFontMetrics().getAscent(),
resumeRect.getWidth(),
resumeRect.getHeight());
不要为此使用 drawString(),而是将文本放在 JLabel 中。然后你可以将监听器附加到标签上,这样就容易多了。
JLabel 还具有以下优点:您可以使用 html 进行格式化,并且它允许布局管理器定位文本。
如何检测文本 ("Resume", "Restart", "Quit") 我用drawString()
方法画的被点击了?
到目前为止我的代码:
public class Pause {
public Pause() {
}
public void draw(Graphics2D g) {
g.setFont(new Font("Arial", Font.BOLD, 14));
int intValue = Integer.parseInt( "ff5030",16);
g.setColor(new Color(intValue));
g.drawString("Resume", 200, 156);
g.drawString("Restart", 200, 172);
g.drawString("Quit", 200, 188);
}
}
希望你能帮助我。谢谢
@aioobe 我尽量写得简单。这里是 SSCCE:
GameFrame.java
public class GameFrame extends JFrame implements Runnable {
/**
*
*/
private static final long serialVersionUID = 1L;
// dimensions
public static final int WIDTH = 448;
public static final int HEIGHT = 288;
public static final double SCALE = 2.5;
// game thread
private Thread thread;
private boolean running;
private int FPS = 60;
private long targetTime = 1000 / FPS;
// image
private BufferedImage image;
private Graphics2D g;
//displays
private Pause pauseDisplay;
public GameFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.pack();
this.setLocationRelativeTo(null);
this.setPreferredSize(new Dimension((int)(WIDTH * SCALE), (int)(HEIGHT * SCALE)));
this.setBounds(100, 100, (int)(WIDTH * SCALE), (int)(HEIGHT * SCALE));
this.setLocationRelativeTo(null);
this.setFocusable(true);
this.requestFocus();
this.setVisible(true);
}
public void addNotify() {
super.addNotify();
if(thread == null) {
thread = new Thread(this);
thread.start();
}
}
private void init() {
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
}
public void run() {
init();
long start;
long elapsed;
long wait;
// game loop
while(running) {
start = System.nanoTime();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if(wait < 0) wait = 5;
try {
Thread.sleep(wait);
}
catch(Exception e) {
e.printStackTrace();
}
pauseDisplay = new Pause(this);
drawToScreen();
draw();
}
}
private void draw() {
pauseDisplay.draw(g);
}
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, (int)(WIDTH * SCALE), (int)(HEIGHT * SCALE), null);
g2.dispose();
}
public static void main(String[] args) {
GameFrame game = new GameFrame();
}
}
Pause.java
public class Pause implements MouseListener{
private Rectangle2D resumeRect;
private Rectangle2D restartRect;
public Pause(GameFrame GameFrame) {
GameFrame.addMouseListener(this);
}
public void draw(Graphics2D g) {
g.setFont(new Font("Arial", Font.BOLD, 14));
int intValue = Integer.parseInt( "ff5030",16);
g.setColor(new Color(intValue));
g.drawString("Resume", 200, 156);
resumeRect= g.getFontMetrics().getStringBounds("Resume", g);
g.drawString("Restart", 200, 172);
restartRect = g.getFontMetrics().getStringBounds("Restart", g);
g.drawString("Quit", 200, 188);
}
public void mouseClicked(MouseEvent e) {
if (resumeRect.contains(e.getPoint())) {
System.out.println("clicked");
}
System.out.println(resumeRect);
System.out.println(restartRect);
System.out.println(e.getPoint());
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
你必须记住你画线的位置。每个字符串可以有一个 Rectangle2D
。
字符串的矩形可以计算如下:
Rectangle2D r = g.getFontMetrics().getStringBounds(str, g);
(需要根据画线的位置调整rect的位置)
然后您将注册一个鼠标侦听器来检查这些矩形的点击坐标:
if (resumeRect.contains(mouseEvent.getPoint())) {
...
}
也就是说,我建议您重新考虑您的 GUI 代码,看看您是否不能为此目的使用 JLabel
或 JButton
。
关于您的修改:
您的 NullPointerException 是由于您可以在渲染图像之前(即在初始化矩形之前)单击框架。
除此之外,您还需要进行两项编辑:
您需要考虑
SCALE
。if (resumeRect.contains(e.getPoint().getX() / GameFrame.SCALE, e.getPoint().getY() / GameFrame.SCALE)) {
和
需要补偿drawString在基线上绘制字符串,所以矩形要从基线向上抬到文本的左上角:
g.drawString("Resume", 200, 156); resumeRect= g.getFontMetrics().getStringBounds("Resume", g); // Add this: resumeRect.setRect(200, 156 - g.getFontMetrics().getAscent(), resumeRect.getWidth(), resumeRect.getHeight());
不要为此使用 drawString(),而是将文本放在 JLabel 中。然后你可以将监听器附加到标签上,这样就容易多了。
JLabel 还具有以下优点:您可以使用 html 进行格式化,并且它允许布局管理器定位文本。