java - 如何将两个 JPanel 层叠在一起?
问题描述
我尝试在地图(JPanel)的顶部分层三角形(JPanel)。我用 JLayeredPane 尝试过,但三角形和地图没有分层(见附图)。最后,我想为三角形设置一个位置并将其放置在地图上。我试图为三角形和地图设置绝对位置,setBounds()
但它对我不起作用。结果相同。这是我的代码:
import javax.swing.*;
import java.awt.*;
public class MainFrame extends JFrame {
Container mainContainer;
JLayeredPane mapLayer;
BackgroundMap bgMap;
Mesocyclone meso1;
public MainFrame() {
initUI();
}
private void initUI() {
mainContainer = getContentPane();
bgMap = new BackgroundMap();
mapLayer = new JLayeredPane();
mapLayer.setLayout(new FlowLayout());
mainContainer.setLayout(new FlowLayout(FlowLayout.LEFT));
mainContainer.add(mapLayer);
meso1 = new Mesocyclone();
mapLayer.add(bgMap, JLayeredPane.DEFAULT_LAYER);
mapLayer.add(meso1, JLayeredPane.POPUP_LAYER);
setSize(900, 1000);
setTitle("Mesodetect | v1.0 \u00A9 ");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Path2D;
public class Mesocyclone extends JPanel {
private static final int PREF_W = 100;
private static final int PREF_H = PREF_W;
private static final Color COLOR = Color.RED;
private Path2D myPath = new Path2D.Double();
public Mesocyclone() {
double firstX = (PREF_W / 2.0) * (1 - 1 / Math.sqrt(3));
double firstY = 3.0 * PREF_H / 4.0;
myPath.moveTo(firstX, firstY);
myPath.lineTo(PREF_W - firstX, firstY);
myPath.lineTo(PREF_W / 2.0, PREF_H / 4.0);
myPath.closePath();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to smooth out the jaggies
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(COLOR); // just for fun!
g2.fill(myPath); // fill my triangle
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
public class BackgroundMap extends JLabel {
private Image image;
private BevelBorder border;
private int WIDTH = 620;
private int HEIGHT = 850;
public BackgroundMap() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
try {
image = ImageIO.read(new File("res/map_bg.png"));
this.setIcon(new ImageIcon(image));
} catch (IOException e) {
e.printStackTrace();
}
border = new BevelBorder(1);
setBorder(border);
}
public Image getImage() {
return this.image;
}
}
import java.awt.*;
public class Application {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new MainFrame().setVisible(true);
}
});
}
}
解决方案
mapLayer = new JLayeredPane();
mapLayer.setLayout(new FlowLayout());
mainContainer.setLayout(new FlowLayout(FlowLayout.LEFT));
mainContainer.add(mapLayer);
meso1 = new Mesocyclone();
mapLayer.add(bgMap, JLayeredPane.DEFAULT_LAYER);
mapLayer.add(meso1, JLayeredPane.POPUP_LAYER);
您不应该为分层窗格设置布局管理器。这将导致组件显示在 FlowLayout 中,而不是分层显示,因为每个组件的位置将根据 FlowLayout 的规则设置。但是,如果您不设置布局管理器,您现在需要负责设置添加到分层窗格中的每个组件的大小/位置。
不要使用“DEFAULT_LAYER”和“POPUP_LAYER”,这些是分层面板使用的特殊图层。当您添加自己的组件时,您只是在使用“常规”层。所以你应该使用“new Integer(1)”和“new Integer(2)”。
阅读 Swing 教程中有关如何使用 LayeredPanes的部分,以获取上述两个建议的工作示例。
另一种选择是不使用分层窗格,而仅使用 Swings 组件之间的默认父/子关系。
因此,您的图像标签将成为父级,而三角形组件将成为子级。那么你的逻辑会变成:
JPanel child = new ...
child.setSize( child.getPreferredSize() );
child.setLocation(10, 10);
JLabel parent = new JLabel( new ImageIcon(...) );
parent.add( child );
请注意,您还需要在子组件上使用 setOpaque(false)。
只要子组件适合标签图像的边界,这是更简单的解决方案。
推荐阅读
- php - 有没有办法在 Symfony 中使用表单发送 GET 请求并避免在更改 URL 时重新加载页面?
- python - 在python中,niter是什么,counter有什么不同?
- javascript - 通过单击将单选按钮值插入 mysql
- python - Flake8 使用系统 python 代替 virtualenv
- c# - 使用 Unity 注入数组
- php - MySQL PHP选择“X,Y”在X,Y,Z中的位置
- sql - 在 Google BigQuery 中投射不合适?
- google-apps-script - 使用应用程序脚本更改 gsuite 签名返回“isDefault 无法切换为 false”
- javascript - 照片长度问题
- java - Jackson 将对象数组反序列化为 pojo