当前位置: 首页 > 面试题库 >

通过JLayer和LayerUI缩放JLayeredPane

富辰阳
2023-03-14
问题内容

在这个问题上,有人建议在Swing应用程序中实现缩放的最佳方法是通过JLayerJava
7附带的装饰器。

我一直在关注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<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);
        }
    }
}

在此示例中,我期望单击和缩放以正确响应鼠标事件时,放大/缩小按钮的大小会增加。不必单击它们曾经驻留的位置即可触发事件。

可悲的是,我什至无法通过更改注释行来放大它们,因此,我非常感谢您的帮助!


问题答案:

您的直接问题是,您正在混合重量级/ 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<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);
        }
    }
}

您的下一个问题将是研究如何转换鼠标事件;)



 类似资料:
  • 问题内容: 我需要实现变焦为包含在。我已经通过覆盖方法和调用来成功进行缩放。 这是不正常:对的和的规模如预期,但一定会得到的和这样的寄存器在预分频的位置。我能做什么?感谢您的阅读。 问题答案: 显示了如何使用明确的转化方法扩展鼠标坐标:,,和。)。

  • JLayer是一个库,可为JAVA(tm)平台实时解码/播放/转换MPEG 1/2 / 2.5 Layer 1/2/3(即MP3)。这是一个非商业项目,任何人都可以添加自己的贡献。JLayer已获得LGPL许可。  

  • null 关键是我使用jLayer的实现不起作用:当我执行play-pause-resume时,音频被暂停,但随后从文件中的随机点恢复。 我该怎么修好它?

  • 问题内容: 我有几个对象在不同状态下具有不同的纹理,因此我使用了TexturePacker制造的对象,并在需要的地方调整了大小。我必须调整大小,因为我不仅要同时支持720p和1080p,而且我的一些对象是根据板子的宽度和高度来调整大小的图块或光标,因为在我的游戏中这可能会改变,而板子总是占据屏幕的相同百分比。 使用,我可以这样做: 但是,当我使用时,没有设置过滤器的选项。这导致这些大小调整为尖锐,

  • 我写了一个应用程序来播放mp3文件,我有控制和一切滚动,只是一个问题,每个mp3文件是单独播放,我必须触发一个新的文件播放。 我想知道我如何(按语法)判断玩家是否已经完成了一个文件的播放,这样我就可以继续下一个文件了? 这是线程代码

  • 问题内容: 注意:这与放大时如何渲染现有画布元素有关,而与在画布表面上渲染线条或图形无关。换句话说,这与缩放元素的插值有关,而与在画布上绘制的图形的抗锯齿无关。我不关心浏览器如何画线;我关心的是浏览器在放大时如何渲染canvas元素本身。 是否可以通过编程更改画布属性或浏览器设置以在缩放 元素时禁用插值?跨浏览器解决方案是理想的,但不是必需的。基于Webkit的浏览器是我的主要目标。性能非常重要。