繁体   English   中英

镜像JLabel或JTextArea

[英]Mirroring JLabel or JTextArea

我需要获取JLabel或JTextArea的镜像。

http://www.subirimagenes.net/i/150305101716451074.jpg

如果我使用JTextArea,则需要完整地镜像字母。 如果使用JLabel,则需要格式和镜像字母。

该示例是在Photoshop上创建的。

我的想法是使用graphics(),但是我不知道该怎么做。

这是个坏消息:这并不像我们希望的那样直接,有一个局限性。 在Swing中,图形转换仅应用于绘制操作,而不应用于常规布局和事件处理。 因此,在Swing中,镜像组件基本上是“不可用的”,除显示主要组件的镜像外,不能用于其他任何用途。 鼠标单击等的坐标将是错误的。

因此,这是所有棘手的问题,有点十岁上下。

有多种方法可以做到这一点。 一种可能是在一个模型上使用两个视图,并告诉其中一个视图的Graphics水平翻转。

这是一个示例,演示了翻转的JEditorPane

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class MirrorText {
    public static void main(final String... args) {
        SwingUtilities.invokeLater(MirrorText::setupUI);
    }
    public static void setupUI() {
        final JEditorPane editor = new JEditorPane("text/html", "<h1>Mirrored</h1><p>This is mirrored text.</p>");
        final JEditorPane mirroredEditor = new JEditorPane("text/html", "") {
            protected Graphics getComponentGraphics(final Graphics g) {
                return horizontalFlip(super.getComponentGraphics(g), getWidth());
            }
        };
        mirroredEditor.setDocument(editor.getDocument());

        final JFrame frame = new JFrame("mirrored label");
        final JPanel mirrorPanel = new JPanel(new GridLayout(1, 2));
        mirrorPanel.add(new JScrollPane(editor));
        mirrorPanel.add(new JScrollPane(mirroredEditor));
        frame.add(mirrorPanel);
        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
    }
    public static Graphics horizontalFlip(final Graphics g, final int width) {
        final Graphics2D g2d = (Graphics2D) g;
        final AffineTransform tx = g2d.getTransform();
        tx.scale(-1.0, 1.0);
        tx.translate(-width, 0);
        g2d.setTransform(tx);
        return g2d;
    }
}

该解决方案的优势在于,它完全镜像了原始组件的MVC和观察者,因为它是同一模型上相同类型的组件(视图/控制器)。 该解决方案的缺点是,您以非常特定于镜像组件的方式创建了镜像组件。

另一种可能性是创建一个装饰器 JComponent Mirror ,它可以镜像任意其他JComponent 这有点棘手,因为在Java中,装饰器无法覆盖装饰对象的方法,并且每当原始组件更新(重新绘制)时,都需要更新(重新绘制) Mirror

这是一个不完整的示例,该示例使用挂接到相应事件的Mirror 不完整的,因为它仅挂钩到DocumentEvent还应该挂钩到其他事件,例如CaretEvent 如果Swing带有PaintEvent类的东西,那就太好了。 据我所知,还没有。 (实际上,它确实有,但是没有相应的PaintListeneraddPaintListener() 。)由于镜像未观察到原始组件的属性(如size),因此它也不完整。 它之所以起作用,是因为MirrorPanel上的GridLayout可使镜像大小与原始组件保持同步。

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;

public class MirrorText {
    public static void main(final String... args) {
        SwingUtilities.invokeLater(MirrorText::setupUI);
    }
    public static void setupUI() {
        final JEditorPane editor = new JEditorPane("text/html", "<h1>Mirrored</h1><p>This is mirrored text.</p>");
        final MirrorPanel mirrorPanel = new MirrorPanel(new JScrollPane(editor));

        editor.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(final DocumentEvent e) { mirrorPanel.updateMirror(); }
            public void insertUpdate(final DocumentEvent e) { mirrorPanel.updateMirror(); }
            public void removeUpdate(final DocumentEvent e) { mirrorPanel.updateMirror(); }
        });

        final JFrame frame = new JFrame("mirrored label");
        frame.add(mirrorPanel);
        frame.pack();
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
    }
}

class MirrorPanel extends JPanel {
    public MirrorPanel(final JComponent c) {
        super(new GridLayout(1, 2));
        add(c);
        add(new Mirror(c));
    }
    public void updateMirror() {
        repaint();
    }
}

class Mirror extends JComponent {
    private final JComponent mirroredComponent;
    public Mirror(final JComponent mirroredComponent) {
        this.mirroredComponent = mirroredComponent;
    }
    public static Graphics horizontalFlip(final Graphics g, final int width) {
        final Graphics2D g2d = (Graphics2D) g;
        final AffineTransform tx = g2d.getTransform();
        tx.scale(-1.0, 1.0);
        tx.translate(-width, 0);
        g2d.setTransform(tx);
        return g2d;
    }
    public void paint(final Graphics g) {
        mirroredComponent.paint(horizontalFlip(g, mirroredComponent.getWidth()));
    }
}

可能还有更多的可能性。 例如,可以覆盖镜像组件的paint()方法来更新镜像组件。 这样可以避免得到通知,但是如果由于内容更改而是由于缓冲区破坏(即其他窗口被移走)而导致绘画未完成,则会导致不必要的paint()调用。

这是创建镜像的一种方法。

基本上,您在BufferedImage上打印JTextArea的内容。 然后在X轴上反转BufferedImage的像素。

package com.ggl.testing;

import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class MirrorImage implements Runnable {

    private JFrame frame;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MirrorImage());
    }

    @Override
    public void run() {
        frame = new JFrame("Mirror Image Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new FlowLayout());

        JPanel textPanel = new JPanel();

        JTextArea textArea = new JTextArea(15, 30);
        textPanel.add(textArea);

        mainPanel.add(textPanel);

        MirrorPanel mirrorPanel = new MirrorPanel();
        mirrorPanel.setPreferredSize(textPanel.getPreferredSize());

        mainPanel.add(mirrorPanel);

        TextListener listener = new TextListener(textArea, mirrorPanel);
        textArea.getDocument().addDocumentListener(listener);

        frame.add(mainPanel);

        frame.pack();
        frame.setLocationByPlatform(true);

        listener.createImage(textArea);

        frame.setVisible(true);
    }

    private class MirrorPanel extends JPanel {

        private static final long serialVersionUID = 2496058019297247364L;

        private Image image;

        public void setImage(Image image) {
            this.image = image;
            repaint();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, (getWidth() - image.getWidth(this)) / 2,
                    (getHeight() - image.getHeight(this)) / 2, this);
        }
    }

    private class TextListener implements DocumentListener {

        private JTextArea textArea;

        private MirrorPanel mirrorPanel;

        public TextListener(JTextArea textArea, MirrorPanel mirrorPanel) {
            this.textArea = textArea;
            this.mirrorPanel = mirrorPanel;
        }

        @Override
        public void insertUpdate(DocumentEvent event) {
            createImage(textArea);
        }

        @Override
        public void removeUpdate(DocumentEvent event) {
            createImage(textArea);
        }

        @Override
        public void changedUpdate(DocumentEvent event) {
            createImage(textArea);
        }

        public void createImage(JTextArea textArea) {
            BufferedImage img = new BufferedImage(textArea.getWidth(),
                    textArea.getHeight(), BufferedImage.TYPE_INT_RGB);

            Graphics2D g2d = img.createGraphics();
            textArea.printAll(g2d);
            g2d.dispose();

            createMirrorImage(img);
            mirrorPanel.setImage(img);
        }

        private void createMirrorImage(BufferedImage img) {
            int width = img.getWidth();
            int height = img.getHeight();

            int[][] pixels = new int[width][height];

            for (int i = width - 1; i >= 0; i--) {
                int j = width - i - 1;
                for (int k = 0; k < height; k++) {
                    pixels[j][k] = img.getRGB(i, k);
                }
            }

            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    img.setRGB(i, j, pixels[i][j]);
                }
            }
        }

    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM