It's been suggested on this Stack Overflow question that the best way to implement zooming in Swing applications is via the JLayer
decorators provided with Java 7.
I've been following the Oracle tutorial and think the best way to do this is by creating my own ZoomUI
that extends the LayerUI
. My thoughts so far are that this class will have a zoom
member variable that is applied before painting the actual component.
Then later on I can then use this same class to catch mouse events and dispatch them to their un-zoomed coordinates.
I'm having a little trouble with the first step and cannot understand why the g2.scale(zoom, zoom)
call is having no effect in my SSCCE below.
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
public class Demo {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JLayeredPane panel = new JLayeredPane();
final ZoomUI layerUI = new ZoomUI();
final JLayer<JComponent> jLayer = new JLayer<JComponent>(panel, layerUI);
Button zoomIn = new Button("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom += 0.1;
jLayer.repaint();
}
});
zoomIn.setBounds(0,0,100,50);
panel.add(zoomIn);
Button zoomOut = new Button("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom -= 0.1;
jLayer.repaint();
}
});
zoomOut.setBounds(100,0,100,50);
panel.add(zoomOut);
frame.setPreferredSize(new Dimension(400,200));
frame.add(jLayer);
frame.pack();
frame.setVisible(true);
}
});
}
private static class ZoomUI extends LayerUI<JComponent> {
public int zoom = 1.5; // Changing this value seems to have no effect
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D) g.create();
g2.scale(zoom, zoom);
super.paint(g2, c);
g2.dispose();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
JLayer jlayer = (JLayer)c;
jlayer.setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.ACTION_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK
);
}
@Override
public void uninstallUI(JComponent c) {
JLayer jlayer = (JLayer)c;
jlayer.setLayerEventMask(0);
super.uninstallUI(c);
}
}
}
In this example I'm expecting the zoom in/out buttons to grow in size when clicked and when zoomed to respond to mouse events correctly. That is not having to click where they used to reside in order to trigger an event.
Sadly I can't even get them to zoom before clicked by changing the commented line so I'd really appreciate some help!
You immediate problem is you are mixing heavy weight/AWT components with light weight/Swing components...
Button
is a native component, meaning that it's painting is out side the control of Swing and therefore is not affected by it.
Instead, use JButton
instead.
public class TestJLayerZoom {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
final ZoomUI layerUI = new ZoomUI();
final JLayer<JComponent> jLayer = new JLayer<JComponent>(panel, layerUI);
JButton zoomIn = new JButton("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom += 0.1;
jLayer.repaint();
}
});
panel.add(zoomIn);
JButton zoomOut = new JButton("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
layerUI.zoom -= 0.1;
jLayer.repaint();
}
});
panel.add(zoomOut);
frame.setPreferredSize(new Dimension(400, 200));
frame.add(jLayer);
frame.pack();
frame.setVisible(true);
}
});
}
private static class ZoomUI extends LayerUI<JComponent> {
public double zoom = 2; // Changing this value seems to have no effect
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D) g.create();
g2.scale(zoom, zoom);
super.paint(g2, c);
g2.dispose();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
JLayer jlayer = (JLayer) c;
jlayer.setLayerEventMask(
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.ACTION_EVENT_MASK
| AWTEvent.MOUSE_MOTION_EVENT_MASK
);
}
@Override
public void uninstallUI(JComponent c) {
JLayer jlayer = (JLayer) c;
jlayer.setLayerEventMask(0);
super.uninstallUI(c);
}
}
}
You're next problem will be working out how to translate the mouse events ;)
来源:https://stackoverflow.com/questions/21439341/zooming-jlayeredpane-via-jlayer-and-the-layerui