Java旋转非方形JPanel组件

标签 java swing user-interface rotation awt

由于操作系统限制,我正在尝试旋转填充有文本标签的 GridLayout 以模拟纵向 View 。它们所在的 JPanel 不是方形的,因此当旋转 90 度时,标签会根据 JPanel 的尺寸被切断。是否可以根据旋转调整布局大小以仍然适合 JPanel?对此进行的研究显示了许多旋转选项,但仅限于方形 JPanel。

为了进一步解释我的问题:当我旋转内部绘制的标签时,它们的格式保持为正常方向的 x,y,并且我希望它格式化布局以适合 90 度旋转的 x,y (所以基本上 y 和x 被翻转)。目前我的网格的一部分在旋转后被切断。此外,最终显示应适合当前 JPnel 中填充的所有 13 x 24 个字母。

编辑:使用模糊注释表明我需要在旋转后进行绘画,但这样做会裁剪网格并且不会填充回我喜欢的尺寸。

JPanel代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Screen extends JPanel {

   private JLabel[][] labels = new JLabel[13][24];
   private GridLayout layout;

   public Screen() {

      //setLocation(315,35);
      layout = new GridLayout(13, 24);
      layout.preferredLayoutSize(this);
      //setBounds(315, 65, 243, 350);
      setBounds(315, 65, 243, 350);
      setLayout(layout);

      for (int i = 0; i < 13; i++) {
         for (int j = 0; j < 24; j++) {
            labels[i][j] = new JLabel();
            labels[i][j].setBackground(Color.BLACK);
            add(labels[i][j]);
         }
      }

      //testing new letter
      for (int i = 0; i < 13; i++) {
         for (int j = 0; j < 24; j++) {
            labels[i][j].setText("T");
            labels[i][j].setForeground(Color.GREEN);
         }
      }

      setBackground(Color.black);
      setVisible(true);
      repaint();
   }

   @Override
   public void paintComponent(Graphics g) {
      //Rotates screen graphics to correct orientation
      Graphics2D g2d = (Graphics2D) g;
      int w2 = getWidth() / 2;
      int h2 = getHeight() / 2;
      g2d.rotate(Math.PI / 2, w2, h2);

      super.paintComponent(g);
      setSize(243,350);

   }
}

测试代码:

import javax.swing.JFrame;
import javax.swing.JLayeredPane;

public class RotateTest {

   public static class Frame extends JFrame {

      public Frame() {
         Screen screen = new Screen();

         JLayeredPane pane = new JLayeredPane();
         setUndecorated(false);
         setSize(800, 480);

         setVisible(true);
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         pane.add(screen, 0, 0);
         pane.setVisible(true);
         add(pane);
      }
   }

   public static void main(String[] args) {
      Frame frame = new Frame();
   }

}

最佳答案

旋转组件的过程比仅绘制旋转图像更复杂。有许多相互关联的层会产生契约(Contract)义务。

例如,设置到传递给组件进行绘制的 Graphics 上下文的剪切矩形的大小由组件的当前大小决定,该大小由布局管理器计算,但可以考虑各个组件的首选大小...

需要考虑很多重新布线...可以说我很懒,但如果我能找到现成的解决方案,我更愿意使用它,所以基于this example ,我可以生成以下内容...

Rotate

字段面板周围的红色 LineBorder 表明整个组件都已旋转,而不仅仅是其子组件。 pack 的使用还表明该解决方案仍然履行其对 API 其余部分的契约(Contract)义务

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;

public class RotateExample {

    public static void main(String[] args) {
        new RotateExample();
    }

    public RotateExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ExamplePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ExamplePane extends JPanel {

        private FieldPane fieldPane;
        private DefaultTransformModel transformModel;

        private JButton rotate;
        private double angle;

        public ExamplePane() {

            setLayout(new BorderLayout());

            rotate = new JButton("Rotate");
            rotate.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    transformModel.setRotation(Math.toRadians((angle += 90)));
                    SwingUtilities.getWindowAncestor(ExamplePane.this).pack();
                }
            });


            fieldPane = new FieldPane();

            transformModel = new DefaultTransformModel();
            transformModel.setRotation(Math.toRadians(0));
            transformModel.setScaleToPreferredSize(true);
            JXLayer<JComponent> rotatePane = TransformUtils.createTransformJXLayer(fieldPane, transformModel);

            JPanel content = new JPanel(new GridBagLayout());
            content.add(rotatePane);

            add(rotate, BorderLayout.SOUTH);
            add(content);

        }
    }

    public class FieldPane extends JPanel {

        public FieldPane() {
            setBorder(new LineBorder(Color.RED));
            setLayout(new GridBagLayout());

            JTextField field = new JTextField(10);
            field.setText("Hello world");

            add(field);

        }
    }
}

注意事项

这需要 JXLayer (我使用的是版本3),SwingX (我使用的是 1.6.4 版本)和 Piet Blok 的优秀示例,但似乎不再在网上提供...

我已将 JXLayer(版本 3)和 Piet 示例的所有源代码放入一个 zip 中。我建议,如果您有兴趣,请获取一份副本并将其存储在安全的地方。

您还需要JHLabs filters

已更新

并使用您的Screen面板(没有自定义绘画)...

Rotate

关于Java旋转非方形JPanel组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25252127/

相关文章:

Python 在 Tkinter GUI Canvas 中附加文本

Java:将对象保存在文本文件中?有现成的解决方案吗?

java - 为什么我的绘图面板在调整窗口大小时有时会绘画而有时不会?

java - 如何在不使用对话框框架的情况下从有界任务流中的新窗口中打开 jspx?

java - 使用java隐藏文件

java - 在 Java 中使用 AudioPlayer

Tcl 的 Java 图形用户界面

Java 在可运行 Jar 文件的内容之间来回移动

java - 按照这个简单的 GSON 示例,等效的客户端 RestyGWT 是什么样子?

java - `gradle install`如何生成 `pom.xml`文件