2012-02-22 28 views
5

這可能看起來很愚蠢(而且很可能是),但是我怎樣才能顛倒JFrame中的所有組件? JFrame中的所有內容都必須圍繞JFrame中間的軸垂直翻轉,包括控件上的文本。最好與JTextField s,JButton s等按預期工作,即使翻轉。如何翻轉JFrame及其兒童顛倒?

我已經做了一些搜索,但沒有找到任何有用的主題。

是否有比手動更改佈局,然後擴展和覆蓋每個使用的控件的繪製方法更容易的方法?

編輯:我設法讓它工作。你可以看到my answer below

+2

* 「只是一個單純的惡作劇太多精力?」 *你有沒有想過使用你的力量.. *** ***好?*** – 2012-02-22 10:33:49

+0

它可能更容易把你的顯示器顛倒,或站在你的頭上。 ;-) – DNA 2012-02-22 11:01:03

+0

大量的圖形卡會讓你旋轉整個桌面(但不是個別的窗口),如果這將提供足夠的嘲笑和娛樂? – DNA 2012-02-22 11:02:13

回答

2

我設法創建了一個小型的工作翻轉應用程序。到目前爲止,所有使用的子控件(JTextArea,JLabel,JButton)按預期工作,事件和所有。

下面是截圖...

It's flipped!

和代碼...

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); 
    } 
} 
+0

與RepaintManager很好的伎倆,不會想到這一點。 – ARRG 2012-02-22 21:32:49

4

您可以輕鬆地翻轉GUI而無需修改所有組件,只需修改您的最頂層容器的paint方法:

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); 
    } 
} 

的錯覺是不完美的,但:當用戶將鼠標懸停在原按鈕的位置,按鈕將正確顯示。

很明顯,這不涉及倒轉事件,這是相當複雜的。

+0

感謝您的回答!這是創建完整工作示例的基石。這確實是一個使事件發生逆轉並解決繪畫問題的使命,但我終於設法讓它工作。 – ughzan 2012-02-22 21:27:10