[英]Updating custom cursor in java swing window
I want to set custom cursor in my java swing app, and then edit it.我想在我的 java swing 应用程序中设置自定义 cursor,然后编辑它。
I set a custom cusrsor after showing window (in "Window" class).在显示 window(在“Window”类中)后,我设置了一个自定义光标。 Later in code (in the other class), I want to chainge it again, so i call this
updateCursor()
funcion (in "Window" class again), and it and it won't work.稍后在代码中(在另一个类中),我想再次链接它,所以我调用了这个
updateCursor()
再次在“Window”class 中),并且它不起作用。 There is no errors or warnings, but the cursor isn't changing - just stays the same.没有错误或警告,但 cursor 没有改变——只是保持不变。 I tried, and I can't find answer anywhere.
我试过了,但我无法在任何地方找到答案。 I appreciate any help.
我感谢任何帮助。
This is full code - Window.java :这是完整代码 - Window.java :
import MainMenu;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
public class Window {
public static final int WIDTH = 817, HEIGHT = 640;
JFrame frame = new JFrame("");
public void open() {
frame.pack();
frame.setVisible(true);
frame.setResizable(false);
frame.setSize(WIDTH - 33, HEIGHT - 25);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setFocusable(true);
frame.requestFocus();
frame.setFocusTraversalKeysEnabled(true);
frame.addKeyListener(new InputManager());
frame.addMouseListener(new InputManager());
frame.add(new MainMenu());
frame.add(new Game());
loadCursors();
updateCursor(0);
}
public static final int NORMAL = 0, ACTIVE = 1, INACTIVE = 2;
Cursor cursor_normal, cursor_active, cursor_inactive;
public void loadCursors() {
try {
cursor_normal = Toolkit.getDefaultToolkit().createCustomCursor(ImageIO.read(new File(new SpritesManager().cursor_normal)), new Point(0, 0), "custom cursor (normal)");
cursor_active = Toolkit.getDefaultToolkit().createCustomCursor(ImageIO.read(new File(new SpritesManager().cursor_active)), new Point(0, 0), "custom cursor (active)");
cursor_inactive = Toolkit.getDefaultToolkit().createCustomCursor(ImageIO.read(new File(new SpritesManager().cursor_inactive)), new Point(0, 0), "custom cursor (inactive)");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void updateCursor(int cursorType) {
switch (cursorType) {
case NORMAL -> frame.setCursor(cursor_normal);
case ACTIVE -> frame.setCursor(cursor_active);
case INACTIVE -> frame.setCursor(cursor_inactive);
}
}
}
MainMenu.java :主菜单.java :
import Window;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class MainMenu extends JPanel implements KeyListener {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// testing
new Window().updateCursor(Window.ACTIVE);
}
@Override
public void keyReleased(KeyEvent e) {
}
}
You are creating an new instance of your Window class in your keyPressed(..) method, therefore your cursor update does not work:您正在 keyPressed(..) 方法中创建 Window class 的新实例,因此您的 cursor 更新不起作用:
new Window().updateCursor(Window.ACTIVE);
新窗口().updateCursor(Window.ACTIVE);
You need to pass your existing Window instance to your MainMenu class and call this instance.您需要将现有的 Window 实例传递给 MainMenu class 并调用此实例。
Here's a working example:这是一个工作示例:
Main App :主要应用程序:
public class MyApp extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyApp app = new MyApp();
app.setVisible(true);
}
});
}
private MyApp() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 600);
// Create cursors
Cursor c1 = Util.getCursor("c1.png");
Cursor c2 = Util.getCursor("c2.png");
setCursor(c1);
JButton button1 = new JButton("Change to Cursor1");
button1.setActionCommand("c1");
button1.addActionListener(new MyActionListener(this));
JButton button2 = new JButton("Change to Cursor2");
button2.setActionCommand("c2");
button2.addActionListener(new MyActionListener(this));
add(button1, BorderLayout.NORTH);
add(button2, BorderLayout.SOUTH);
}
}
ActionListener (handles the button clicks): ActionListener (处理按钮点击):
public class MyActionListener implements ActionListener {
private JFrame jFrame;
public MyActionListener(JFrame jFrame) {
this.jFrame = jFrame;
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()){
case "c1":
jFrame.setCursor(Util.getCursor("c1.png"));
System.out.println("switch to c1");
break;
case "c2":
jFrame.setCursor(Util.getCursor("c2.png"));
System.out.println("switch to c2");
break;
}
}
}
Util (read cursor image): Util (读取cursor图像):
public class Util {
public static Cursor getCursor(String fileName) {
BufferedImage img = null;
try {
img = ImageIO.read(Util.class.getResourceAsStream(fileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
return Toolkit.getDefaultToolkit().createCustomCursor(img, new Point(0, 0), fileName);
}
}
You can't do...你不能做...
new Window().updateCursor(Window.ACTIVE);
and magically expect the other instance of Window
to be updated, in fact, you don't need to do this at all.并神奇地期望更新
Window
的另一个实例,实际上,您根本不需要这样做。
This is going to create another instance/copy of Window
, which is not present on the screen and it will have no effect on the instance which is been displayed.这将创建
Window
的另一个实例/副本,它不在屏幕上,并且对显示的实例没有影响。
You could call setCursor
directly on the instance MainMenu
.您可以直接在实例
MainMenu
上调用setCursor
。
Now, if you want to "centralise" the functionality, I would start by creating a "manager" class, for example...现在,如果你想“集中”功能,我会先创建一个“经理”class,例如......
public class CursorManager {
public enum CusorType {
NORMAL, ACTIVE, INACTIVE;
}
private Cursor cursorNormal, cursorActive, cursorInactive;
public CursorManager() throws IOException {
cursorNormal = Toolkit.getDefaultToolkit().createCustomCursor(ImageIO.read(new File(new SpritesManager().cursor_normal)), new Point(0, 0), "custom cursor (normal)");
cursorActive = Toolkit.getDefaultToolkit().createCustomCursor(ImageIO.read(new File(new SpritesManager().cursor_active)), new Point(0, 0), "custom cursor (active)");
cursorInactive = Toolkit.getDefaultToolkit().createCustomCursor(ImageIO.read(new File(new SpritesManager().cursor_inactive)), new Point(0, 0), "custom cursor (inactive)");
}
public void setCursor(CusorType cursorType, Component comp) {
switch (cursorType) {
case NORMAL ->
comp.setCursor(cursorNormal);
case ACTIVE ->
comp.setCursor(cursorActive);
case INACTIVE ->
comp.setCursor(cursorInactive);
}
}
}
I would then create this instance of the manager during the initialisation phase of your code然后我会在你的代码的初始化阶段创建这个管理器实例
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
CursorManager cursorManager = new CursorManager();
//.. Every thing else...
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
And then pass this instance to every class that might need it...然后将此实例传递给可能需要它的每个 class ...
// You'll need to update Window to accept this parameter
new Window(cursorManager).open();
And...和...
public class MainMenu extends JPanel implements KeyListener {
private CursorManager cursorManager;
private MainMenu(CursorManager cursorManager) {
this.cursorManager = cursorManager;
}
@Override
public void keyPressed(KeyEvent e) {
// testing
cursorManager.setCursor(CursorManager.CusorType.ACTIVE, this);
}
//...
}
This is commonly known as "dependency injection" and is VERY powerful这通常被称为“依赖注入”并且非常强大
Just as a side note, if I was doing something like this, it would be very different, but I tried to keep it simple.附带说明一下,如果我正在做这样的事情,那将是非常不同的,但我尽量保持简单。
JFrame
, as stated, JFrame
is not a simple component and you're not actually adding any new functionality to the class and in the process, locking yourself into a single use, there by reducing re-usability.JFrame
等顶级容器扩展,如前所述, JFrame
不是一个简单的组件,您实际上并没有向 class 添加任何新功能,并且在这个过程中,将自己锁定在一次使用中,因此减少可重用性。 Better to start with a JPanel
as your base component and simply create an instance of JFrame
or `JDialog or what ever top level container you want to use, when you need itJPanel
作为基础组件开始,然后在需要时简单地创建一个JFrame
或 `JDialog 或您想要使用的任何顶级容器的实例KeyListener
is a poor choice for monitoring keyboard input (seriously, just do a search for "my key listener won't work". Instead, take a look at How to Use Key Bindings KeyListener
是监视键盘输入的一个糟糕选择(说真的,只需搜索“我的密钥侦听器将无法工作”。相反,请查看如何使用密钥绑定
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.