我正在为屡获殊荣的密码保护系统开发Java Swing应用程序,并且我需要一个大型自定义光标[80 x 80],您可能会问为什么这么大,有一个在线Web演示您可以查看以了解为什么需要很大:http : //gatecybertech.net
上面的链接在登录页面上使用了那个大光标。当然,您需要先创建测试密码,然后才能尝试登录过程。
但是无论如何,在我的Swing应用程序中,对于最大可能的自定义光标,我达到了32 x 32的限制,我的代码如下所示:
Image cursorImage = toolkit.getImage("Cursor_Crosshair.PNG");
Tabular_Panel.setCursor(Toolkit.getDefaultToolkit().createCustomCursor(cursorImage,new Point(0,0),"custom cursor"));
Cursor_Crosshair.PNG的图像大小为:80 x 80
但是屏幕上显示的是它的缩小版本:32 x 32
所以我的问题是:如何绕过客户光标图像的大小限制,并使光标显示为80 x 80的大小?
我知道操作系统可能是限制的原因,有没有办法克服它?
这是我对玻璃窗格绘画方法的看法。设置它的行为就像设置自定义光标一样。当显示自定义光标时,默认的“箭头”光标被隐藏,而当组件设置了其他光标(例如文本框)时,自定义光标被隐藏。
不幸的是,它最终似乎需要大量的Swing黑魔法,所以我不太喜欢它,但它确实可以正常工作。我之前已经做过这样的游标,但这是为了更简单一些,所以我没有遇到这些问题。
我遇到的一些问题是:
玻璃窗格拦截光标更改(例如,在此处对此进行了描述)。我已经能够找到的唯一解决办法是重写Component.contains(int,int)
返回false
(形容这里,显示这里),但为什么作品似乎并没有打破任何东西是神秘的。
鼠标退出事件有时会在组件范围内返回一个位置,因此我认为除了使用计时器之外,没有一种可靠的方法来知道鼠标何时离开窗口。
package mcve;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.*;
import java.io.*;
public class LargeCursor {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
JPanel glass = new CustomGlassPane();
glass.add(new CursorPanel(), BorderLayout.CENTER);
frame.setGlassPane(glass);
// This next call is necessary because JFrame.setGlassPane delegates to the root pane:
// - https://docs.oracle.com/javase/9/docs/api/javax/swing/RootPaneContainer.html#setGlassPane-java.awt.Component-
// - http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/javax/swing/JFrame.java#l738
// And JRootPane.setGlassPane may call setVisible(false):
// - https://docs.oracle.com/javase/9/docs/api/javax/swing/JRootPane.html#setGlassPane-java.awt.Component-
// - http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/javax/swing/JRootPane.java#l663
glass.setVisible(true);
JPanel content = createTestPanel();
content.setCursor(BlankCursor.INSTANCE);
frame.setContentPane(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
static class CustomGlassPane extends JPanel {
CustomGlassPane() {
super(new BorderLayout());
super.setOpaque(false);
}
@Override
public boolean contains(int x, int y) {
return false;
}
}
static class CursorPanel extends JPanel {
final BufferedImage cursorImage;
Point mouseLocation;
CursorPanel() {
try {
cursorImage = createTransparentImage(
ImageIO.read(new URL("https://i.stack.imgur.com/9h2oI.png")));
} catch (IOException x) {
throw new UncheckedIOException(x);
}
setOpaque(false);
long mask = AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener((AWTEvent e) -> {
switch (e.getID()) {
case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED:
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
capturePoint((MouseEvent) e);
break;
}
}, mask);
// This turned out to be necessary, because
// the 'mouse exit' events don't always have
// a Point location which is outside the pane.
Timer timer = new Timer(100, (ActionEvent e) -> {
if (mouseLocation != null) {
Point p = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(p, this);
if (!contains(p)) {
setMouseLocation(null);
}
}
});
timer.setRepeats(true);
timer.start();
}
void capturePoint(MouseEvent e) {
Component comp = e.getComponent();
Point onThis = SwingUtilities.convertPoint(comp, e.getPoint(), this);
boolean drawCursor = contains(onThis);
if (drawCursor) {
Window window = SwingUtilities.windowForComponent(this);
if (window instanceof JFrame) {
Container content = ((JFrame) window).getContentPane();
Point onContent = SwingUtilities.convertPoint(comp, e.getPoint(), content);
Component deepest = SwingUtilities.getDeepestComponentAt(content, onContent.x, onContent.y);
if (deepest != null) {
if (deepest.getCursor() != BlankCursor.INSTANCE) {
drawCursor = false;
}
}
}
}
setMouseLocation(drawCursor ? onThis : null);
}
void setMouseLocation(Point mouseLocation) {
this.mouseLocation = mouseLocation;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (mouseLocation != null) {
int x = mouseLocation.x - (cursorImage.getWidth() / 2);
int y = mouseLocation.y - (cursorImage.getHeight() / 2);
g.drawImage(cursorImage, x, y, this);
}
}
}
static final class BlankCursor {
static final Cursor INSTANCE =
Toolkit.getDefaultToolkit().createCustomCursor(
new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB),
new Point(),
"BLANK");
}
static JPanel createTestPanel() {
JPanel panel = new JPanel(new GridLayout(3, 3));
panel.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
for (int i = 0; i < 9; ++i) {
if ((i % 2) == 0) {
JTextField field = new JTextField("Text Field");
field.setHorizontalAlignment(JTextField.CENTER);
panel.add(field);
} else {
panel.add(new JButton("Button"));
}
}
return panel;
}
static BufferedImage createTransparentImage(BufferedImage img) {
BufferedImage copy =
GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration()
.createCompatibleImage(img.getWidth(),
img.getHeight(),
Transparency.TRANSLUCENT);
for (int x = 0; x < img.getWidth(); ++x) {
for (int y = 0; y < img.getHeight(); ++y) {
int rgb = img.getRGB(x, y) & 0x00FFFFFF;
int bright = (((rgb >> 16) & 0xFF) + ((rgb >> 8) & 0xFF) + (rgb & 0xFF)) / 3;
int alpha = 255 - bright;
copy.setRGB(x, y, (alpha << 24) | rgb);
}
}
return copy;
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句