问题描述
由于操作系统限制,我试图旋转填充有文本标签的 GridLayout 以模拟纵向视图.它们所在的 JPanel 不是方形的,因此当旋转 90 度时,标签会根据 JPanel 的尺寸切断.是否可以根据旋转调整布局大小以仍然适合 JPanel?对此的研究显示了许多旋转选项,但仅适用于方形 JPanel.
为了进一步解释我的问题:当我旋转绘制在里面的标签时,它们保持格式为正常方向的 x,y,并且我希望它格式化布局以适应 90 度旋转的 x,y(所以基本上是 y 和x 被翻转).目前,我的网格的一部分在旋转后被切断.此外,最终的显示应该适合当前 JPnel 中所有 13 x 24 的字母.
使用模糊注释表明我需要在旋转后绘画,但这样做会裁剪网格并且不会填充回我喜欢的大小.
JPanel 代码:
import java.awt.Color;导入 java.awt.Graphics;导入 java.awt.Graphics2D;导入 java.awt.GridLayout;导入 javax.swing.JLabel;导入 javax.swing.JPanel;公共类屏幕扩展 JPanel {私有 JLabel[][] 标签 = 新 JLabel[13][24];私有 GridLayout 布局;公共屏幕(){//设置位置(315,35);布局 = 新的 GridLayout(13, 24);layout.preferredLayoutSize(this);//setBounds(315, 65, 243, 350);setBounds(315, 65, 243, 350);设置布局(布局);for (int i = 0; i
测试代码:
import javax.swing.JFrame;导入 javax.swing.JLayeredPane;公共类 RotateTest {公共静态类框架扩展 JFrame {公共框架(){屏幕屏幕=新屏幕();JLayeredPane 窗格 = new JLayeredPane();设置未装饰(假);setSize(800, 480);设置可见(真);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);窗格.添加(屏幕, 0, 0);窗格.setVisible(真);添加(窗格);}}公共静态无效主(字符串 [] args){框架框架 = 新框架();}}
解决方案
旋转组件的过程比绘制旋转图像要复杂得多.有许多相互关联的层会产生合同义务.
例如,设置为
Graphics
上下文的剪切矩形的大小由组件的当前大小决定,该大小由布局管理器计算,但可以考虑单个组件的首选大小...
有很多需要考虑的重新布线...称我为懒惰,但如果我能找到现成的解决方案,我更愿意使用它,因此基于 (我使用的是版本 3),SwingX(我使用的是 1.6.4 版)和 Piet Blok 的优秀示例,这些示例似乎不再在网络上可用...
我已将 JXLayer(第 3 版)和 Piet 示例的所有源代码放入一个 zip 我建议,如果您有兴趣,可以拿一份副本并将其存放在安全的地方.
您还需要 JHLabs 过滤器
更新
并使用您的
Screen
面板(没有自定义绘画)...
I am attempting to rotate a GridLayout filled with text labels to simulate a portrait orientation view due to an OS restriction. The JPanel they are inside of is not square, so when rotating 90 degrees the labels cut off based on dimensions of the JPanel. Is it possible to resize the layout based on the rotation to still fit within the JPanel? Researching into this showed many options for rotations, but only for square JPanels.
To further explain my problem: when I rotate the labels painted inside they stay formatted to the normal oriented x,y, and I want it to format the layout to fit into the 90 degree rotated x,y (so basically y and x are flipped). currently a portion of my grid is cut off after rotating. Also the final display should fit all 13 by 24 letters filled in the current JPnel.
edit: Using vague comments shows I need to paint after rotating, but doing so crops the grid and does not fill back to my preferred size.
JPanel code:
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);
}
}
test code:
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();
}
}
解决方案
The process of rotating a component is more complicated then just painting the rotated image. There are a number of interconnected layers which generate contractual obligations.
For example, the size of the clipping rectangle set to the
Graphics
context that is passed to your component for painting is determined by the current size of the component, this size is calculated by the layout manager, but may consider the preferred size of the individual component...
That's a lot of re-wiring that needs to be considered...call my lazy, but if I can find a ready made solution, I'd prefer to use it, so based on this example, I can generate the following...
The red
LineBorder
around the field panel is there to show that the entire component is been rotated, not just it's children. The use of pack
also demonstrates that this solution is still honouring it's contractual obligations to the rest of the API
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);
}
}
}
Caveats
This requires JXLayer (I was using version 3), SwingX (I was using version 1.6.4) and Piet Blok's excellent examples, which no longer seem to be available on the net...
I've put all the source code of JXLayer (version 3) and Piet's examples into a single zip and I would suggest, if you are interested, you grab a copy and store it some where safe.
You will also need JHLabs filters
Updated
And using your
Screen
panel (without the custom painting)...
这篇关于Java旋转非方形JPanel组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!