我正在开发一个精灵编辑器。我有一个扩展JPanel的类,在该类中,我使用JLayeredPane作为容器。在底层,有一个带有ImageIcon的JLabel,在顶层有一个JPanel,我绘制了一个网格。当代码运行时,我做了一些基本的数学运算,将JLayeredPane的首选大小设置为等于屏幕分辨率高度的85%左右。
我的问题是,当用户想要在其上绘制新画布时,我向JOptionPane询问用户所需画布的大小。然后我调用我的类构造函数来创建一个具有指定大小的新画布。之后,我在画布上应用revalidate()和repaint()方法。不幸的是,它不起作用。另外,当我试图获得画布的宽度和高度时,两者都给出0。但是,当我将自己的大小直接设置为代码时,它运行良好。因此,我想知道如何更新JLayeredPane的大小?
On start with a size of 85% of the screen resolution
When I set the size to 640x640 directly inside my code
When I answer the JOptionPane with a size of 640x640, the grid has been adapted to the asking size. However, it's not the case for the JLayeredPane
答案 0 :(得分:1)
如果没有更多上下文,就无法知道代码出了什么问题。
但是,就个人而言,我将不再尝试重新发明轮子,并利用可用的布局管理API为您提供所需的支持。
您可以通过多种方式解决问题。我个人将网格和图像的渲染包装成单个组件,但那就是我。在这种情况下,您不需要JLayeredPane
。
让我们暂时假设JLayeredPane
是不可协商的。然后我将布局管理器应用到JLayeredPane
,这使得与其他两个组件(图像和网格)的交互更简单,因为布局管理器接管了控制权。因为你希望它们相互重叠,我很想使用GridBagLayout
。
这里的问题就是让两个组件的大小保持同步。为此,我使用setPreferredSize
动态更改大小。
“插入内部尖叫” - 任何时候我看到setPreferredSize
警报铃声。在这种情况下,我再次回到使用单个组件并提供与getPreferredSize
一起使用的“大小调整”机制,但在一天结束时,这将使我们朝着同一方向前进。
为了在父容器的85%高度处布置JLayeredPane
,再次GridBagLayout
将是我的首选。
以下示例将JLayeredPane
放置在想要填充父容器的可用空间(最多可用高度的85%)的位置。然后它允许图像和网格组件自动定位在该区域的一侧。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private JLayeredPane lp;
private ImagePane imagePane;
private GridPane gridPane;
public TestPane() throws IOException {
setLayout(new GridBagLayout());
lp = new JLayeredPane();
lp.setLayout(new GridBagLayout());
imagePane = new ImagePane();
gridPane = new GridPane();
gridPane.setForeground(new Color(255, 255, 255, 64));
imagePane.setImg(ImageIO.read(...)));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
lp.add(imagePane, gbc);
lp.add(gridPane, gbc);
lp.setLayer(imagePane, 0);
lp.setLayer(gridPane, 10);
lp.setBackground(Color.RED);
lp.setBorder(new LineBorder(Color.RED));
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 0.85;
gbc.fill = gbc.BOTH;
add(lp, gbc);
applyDesiredSize(200, 200);
JButton btn = new JButton("Change");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weighty = 0.25;
add(btn, gbc);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JTextField widthTF = new JTextField(4);
JTextField heightTF = new JTextField(4);
JPanel panel = new JPanel();
panel.add(new JLabel("Size: "));
panel.add(widthTF);
panel.add(new JLabel("x"));
panel.add(heightTF);
JOptionPane.showMessageDialog(TestPane.this, panel, "Change Size", JOptionPane.PLAIN_MESSAGE);
try {
int width = Integer.parseInt(widthTF.getText());
int height = Integer.parseInt(heightTF.getText());
applyDesiredSize(width, height);
} catch (NumberFormatException numberFormatException) {
JOptionPane.showMessageDialog(TestPane.this, "Invalid dimensions", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
}
protected void applyDesiredSize(int width, int height) {
Dimension size = new Dimension(width, height);
// lp.setPreferredSize(size);
imagePane.setPreferredSize(size);
gridPane.setPreferredSize(size);
// Stop GridBagLayout from shrinking the components
imagePane.setMinimumSize(size);
gridPane.setMinimumSize(size);
lp.revalidate();
lp.repaint();
}
}
public class ImagePane extends JPanel {
private BufferedImage img;
public ImagePane() {
}
public BufferedImage getImg() {
return img;
}
public void setImg(BufferedImage img) {
this.img = img;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
}
public class GridPane extends JPanel {
private int gridSize = 10;
public GridPane() {
setOpaque(false);
}
public int getGridSize() {
return gridSize;
}
public void setGridSize(int gridSize) {
this.gridSize = gridSize;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getForeground());
for (int x = 0; x < getWidth(); x += gridSize) {
g2d.drawLine(x, 0, x, getHeight());
}
for (int y = 0; y < getWidth(); y += gridSize) {
g2d.drawLine(0, y, getWidth(), y);
}
g2d.dispose();
}
}
}
所以,在你向我射击之前因为它“与你所做的不相符”,请明白: