我需要获得JLabel或JTextArea的镜像。
http://www.subirimagenes.net/i/150305101716451074.jpg
如果我使用JTextArea,我将需要字母是完全镜像的。 如果我使用JLabel,我需要格式和镜像字母。
该示例是在Photoshop上创建的。
我的想法是使用graphics(),但我不知道该怎么做。
答案 0 :(得分:1)
这是坏消息:它不像我们希望的那样直截了当,有一个限制。在Swing中,图形转换仅应用于绘制操作,而不是一般布局和事件处理。因此,在Swing中,镜像组件基本上是“不可用的”,除了显示主要组件的镜像之外,它不能用于任何其他操作。鼠标点击等的坐标将是错误的。
因此,这都是棘手的事情,有点 hack ish。
有多种方法可以做到这一点。
一种可能性是在一个模型上使用两个视图,并告诉其中一个视图的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()
。)
也不完整,因为镜像不会观察原始组件的大小等属性。它只能起作用,因为GridLayout
上的MirrorPanel
会使镜像大小与原始组件保持同步。
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()
调用。
答案 1 :(得分:0)
这是创建镜像的一种方法。
基本上,您在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]);
}
}
}
}
}