通过JLayer和LayerUI缩放JLayeredPane

在Stack Overflow问题上已经提出,在Swing应用程序中实现缩放的最佳方法是通过Java 7提供的JLayer装饰器。

我一直在关注Oracle教程并认为最好的方法是创建我自己的ZoomUI来扩展LayerUI 。 到目前为止,我的想法是这个类将有一个zoom成员变量,在绘制实际组件之前应用它。

然后我可以使用这个相同的类来捕获鼠标事件并将它们发送到未缩放的坐标。

我在第一步遇到一些麻烦,无法理解为什么g2.scale(zoom, zoom)调用在我的SSCCE下面没有效果。

 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 jLayer = new JLayer(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 { 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); } } } 

在这个例子中,我希望放大/缩小按钮在单击时以及在缩放以正确响应鼠标事件时增大。 这不必单击它们曾经驻留的位置以触发事件。

可悲的是,我甚至无法让他们在点击之前通过改变评论线进行缩放,所以我真的很感激一些帮助!

你当前的问题是你正在混合重量/ AWT组件与轻量/ Swing组件……

Button是一个原生组件,这意味着它的绘画不受Swing控制,因此不受其影响。

相反,请改用JButton

 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 jLayer = new JLayer(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 { 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); } } } 

你接下来的问题将是如何翻译鼠标事件;)