[英]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
类的东西,那就太好了。 据我所知,还没有。 (实际上,它确实有,但是没有相应的PaintListener
和addPaintListener()
。)由于镜像未观察到原始组件的属性(如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.