【问题标题】:How to flip a JFrame and its children upside down?如何将 JFrame 及其子项倒置?
【发布时间】:2012-02-22 09:52:24
【问题描述】:

这可能看起来很愚蠢(而且很可能是),但我如何才能将JFrame 中的所有组件倒置? JFrame 中的所有内容都必须围绕JFrame 中间的轴垂直翻转,包括控件上的文本。最好使用JTextFields、JButtons 等,即使翻转也能按预期工作。

我已经进行了一些搜索,但没有发现任何关于该主题的有用信息。

有没有比手动更改布局然后扩展和覆盖所用每个控件的绘制方法更简单的方法?

编辑:我设法让它工作。你可以看到my answer below

【问题讨论】:

  • “仅仅为了一个恶作剧而付出太多的努力吗?”你有没有考虑过用你的力量......为了好?
  • 将显示器倒置或倒立可能更容易。 ;-)
  • 很多显卡可以让你旋转整个桌面(但不能旋转单个窗口),如果这样可以提供足够的嘲笑和娱乐?
  • @Andrew Thompson 嘿,我在声明中看到了错误。我的意思是即使尝试也太费劲了。 :)
  • @DNA 感谢您的提示,我会记住的。但最好只在特定应用程序中发生。

标签: java swing user-interface paint


【解决方案1】:

您无需修改​​所有组件即可轻松翻转 GUI,只需修改最顶层容器的绘制方法:

class ReversedPanel extends Component {
    @Override
    public void paint(Graphics g) {
        BufferedImage im = new BufferedImage(this.getWidth(), this.getHeight(),
                BufferedImage.TYPE_3BYTE_BGR);
        // Paint normally but on the image
        super.paint(im.getGraphics());

        // Reverse the image
        AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -im.getHeight());
        AffineTransformOp op = new AffineTransformOp(tx,
                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        im = op.filter(im, null);

        // Draw the reversed image on the screen
        g.drawImage(im, 0, 0, null);
    }
}

这种错觉并不完美:当用户将鼠标悬停在按钮的原始位置时,按钮将正确显示。

显然,这并没有处理反转事件,这要复杂得多。

【讨论】:

  • 感谢您的回答!它是创建完整工作示例的基石。扭转事件并解决绘画问题确实是一项任务,但我最终设法让它发挥了作用。
【解决方案2】:

我设法创建了一个小型工作翻转应用程序。到目前为止,所有使用的子控件(JTextAreaJLabelJButton)都按预期工作,事件和所有。

这是截图...

还有代码……

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTextArea;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class FlipUpsideDown {

    public static void main(String[] args) {
        JTextArea textArea = new JTextArea("This is a working text area\n\nI LOVE SWING", 4, 0);
        // The cursor still use the wrong mouse position so...
        textArea.setCursor(Cursor.getDefaultCursor());

        final JPanel mainPanel = new JPanel(new BorderLayout(5, 5));

        mainPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
        mainPanel.add(new JLabel("A Normal Label"), BorderLayout.NORTH);
        mainPanel.add(textArea, BorderLayout.CENTER);
        mainPanel.add(new JButton("Hello World!"), BorderLayout.SOUTH);

        // The root pane is responsible for drawing all the children of the 
        // frame. All the paint calls go through the root pane since dirty
        // painting of individual controls are blocked (see below). So we can 
        // use the paint method of the root pane to flip the painted controls.
        final JFrame f = new JFrame("FlipUpsideDown") {

            protected JRootPane createRootPane() {
                JRootPane rp = new JRootPane() {

                    public void paint(Graphics g) {
                        BufferedImage im = new BufferedImage(this.getWidth(), this.getHeight(),
                                BufferedImage.TYPE_3BYTE_BGR);
                        // Paint normally but on the image
                        super.paint(im.getGraphics());

                        // Reverse the image
                        AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
                        tx.translate(0, -im.getHeight());
                        AffineTransformOp op = new AffineTransformOp(tx,
                                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
                        im = op.filter(im, null);

                        // Draw the reversed image on the screen
                        g.drawImage(im, 0, 0, null);
                    }
                };
                rp.setOpaque(true);
                return rp;
            }
        };

        // Override the RepaintManager so that we always repaint the entire 
        // frame when a region is set to dirty.
        RepaintManager repaintManager = new RepaintManager() {

            public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
                schedulePaint();
            }

            public void addDirtyRegion(Window window, int x, int y, int w, int h) {
                schedulePaint();
            }

            public void paintDirtyRegions() {
                schedulePaint();
            }

            private void schedulePaint() {
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        f.paint(f.getGraphics());
                    }
                });
            }
        };
        RepaintManager.setCurrentManager(repaintManager);

        // Intercept mouse events and flip their positions around in the JFrame
        EventQueue queue = new EventQueue() {

            protected void dispatchEvent(AWTEvent event) {
                if (event instanceof MouseEvent) {
                    MouseEvent me = (MouseEvent) event;
                    MouseEvent evt = new MouseEvent(
                            me.getComponent(),
                            me.getID(),
                            me.getWhen(),
                            me.getModifiers(),
                            f.getWidth() - me.getX() + f.getInsets().right - f.getInsets().left,
                            f.getHeight() - me.getY() + f.getInsets().top - f.getInsets().bottom,
                            me.getClickCount(),
                            false,
                            me.getButton());
                    event = evt;
                }
                super.dispatchEvent(event);
            }
        };
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(queue);

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLocationByPlatform(true);
        f.add(mainPanel);
        f.pack();
        f.setVisible(true);
    }
}

【讨论】:

  • RepaintManager 的绝妙技巧,没想到会这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多