Zooming JLayeredPane via JLayer and the LayerUI

假如想象 提交于 2019-12-17 16:55:11

问题


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!


回答1:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!