Java 是否使用BoxLayout将面板之间的间距强制为0?
目前,作为我正在进行的一个项目的一部分,我正在实现一个组件,该组件可用于可视化位的排列(作为加密算法的一部分)。我这样做是通过创建两行“针”,并通过在尖端之间画线连接它们,在它们之间创建一种网络 这其中的一个重要部分是,我正在使用这个可视化本身以及其他可视化的一部分(例如,我可能希望包括S盒),因此我需要能够打开和关闭引脚。我的解决方案是使用Java 是否使用BoxLayout将面板之间的间距强制为0?,java,swing,layout-manager,java-2d,boxlayout,Java,Swing,Layout Manager,Java 2d,Boxlayout,目前,作为我正在进行的一个项目的一部分,我正在实现一个组件,该组件可用于可视化位的排列(作为加密算法的一部分)。我这样做是通过创建两行“针”,并通过在尖端之间画线连接它们,在它们之间创建一种网络 这其中的一个重要部分是,我正在使用这个可视化本身以及其他可视化的一部分(例如,我可能希望包括S盒),因此我需要能够打开和关闭引脚。我的解决方案是使用JPanels将多行插针放入页眉和页脚面板中,使其不可见 我将它们垂直放置在一个BoxLayout中,但即使在页眉上方和页脚下方添加胶水,它们之间也会留有空
JPanel
s将多行插针放入页眉和页脚面板中,使其不可见
我将它们垂直放置在一个BoxLayout
中,但即使在页眉上方和页脚下方添加胶水,它们之间也会留有空间
我的示例在初始化时如下所示:
当我调整它的大小时,它们会聚集在一起,但仍然只接触一面:
我猜这是一个愚蠢的错误,从组件大小和布局的角度将我的用户空间转换为设备空间,但就我的一生而言,我找不到它。这是我的代码,尽管我为混乱道歉:
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Ellipse2D;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PermutationWeb extends JPanel
{
private static enum EndPanelType
{
HEADER, FOOTER
}
private final JPanel header;
private final JPanel mainPanel;
private final JPanel footer;
private double widthFactor;
private double heightFactor;
private int widthMax;
private int heightMax;
private int[] indexMappings;
private Point2D.Double[] endpoints;
private Line2D.Double[] drawingLines;
public PermutationWeb(int indices, boolean endPanelsOn)
{
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
widthMax = (indices + 1)*2;
heightMax = (int)Math.round(widthMax*(3.0/17.0));
widthFactor = 1;
heightFactor = 1;
endpoints = new Point2D.Double[indices * 2];
drawingLines = new Line2D.Double[indices];
for(int i=0; i<indices; i++)
{
endpoints[i] = new Point2D.Double(i*2+2, 0);
endpoints[i+indices] = new Point2D.Double(i*2+2, heightMax);
drawingLines[i] = new Line2D.Double();
}
header = new WebEndPanel(EndPanelType.HEADER);
mainPanel = new WebMainPanel();
footer = new WebEndPanel(EndPanelType.FOOTER);
add(Box.createVerticalGlue());
add(header);
add(mainPanel);
add(footer);
add(Box.createVerticalGlue());
setEndPanelsOn(endPanelsOn);
}
public Point2D getEndpoint(int index)
{
return endpoints[index];
}
public void updateMappings(int[] mappings)
{
this.indexMappings = mappings;
for(int i=0; i<indexMappings.length; i++)
{
drawingLines[i].setLine(endpoints[i], endpoints[indexMappings.length + indexMappings[i]]);
}
//paint();
}
public void setEndPanelsOn(boolean endPanelsOn)
{
header.setVisible(endPanelsOn);
footer.setVisible(endPanelsOn);
}
@Override
public Dimension getMaximumSize()
{
int height = mainPanel.getHeight();
if(header.isVisible())
{
height += (header.getHeight() * 2);
}
int width = mainPanel.getWidth();
return new Dimension(width, height);
}
@Override
public Dimension getPreferredSize()
{
return getMaximumSize();
}
public static void main(String[] args)
{
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(800, 600);
int[] mappings = {0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15};
PermutationWeb webTest = new PermutationWeb(16, true);
jf.add(webTest);
jf.setVisible(true);
webTest.setVisible(true);
webTest.updateMappings(mappings);
System.out.printf("Header: [%s]\nMainPanel: [%s]\nFooter: [%s]\n",
webTest.header.getSize().toString(),
webTest.mainPanel.getSize().toString(),
webTest.footer.getSize().toString());
}
private class WebMainPanel extends WebSubPanel
{
private static final double HEIGHT_RATIO = 0.25;
@Override
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g2);
scaleTo(getSize());
g2.scale(widthFactor, widthFactor);
g2.setStroke(new BasicStroke((float)(2.0/widthFactor)));
for(Line2D line: drawingLines)
{
g2.draw(line);
}
}
@Override
public Dimension getMaximumSize()
{
return new Dimension(MAX_WIDTH_PX, (int)(MAX_WIDTH_PX*HEIGHT_RATIO));
}
}
private class WebEndPanel extends WebSubPanel
{
private static final double HEIGHT_RATIO = 0.125;
private static final double PIN_RADIUS = 0.5;
private final EndPanelType endType;
private Line2D.Double[] edgeLines;
private Ellipse2D.Double[] pinHeads;
public WebEndPanel(EndPanelType endType)
{
super();
this.endType = endType;
this.edgeLines = new Line2D.Double[endpoints.length/2];
this.pinHeads = new Ellipse2D.Double[endpoints.length/2];
for(int i=0; i<edgeLines.length; i++)
{
Point2D pointA;
Point2D pointB;
if(EndPanelType.HEADER.equals(this.endType))
{
pointA = new Point2D.Double(i*2+2, 4);
pointB = new Point2D.Double(i*2+2, 2);
pinHeads[i] = new Ellipse2D.Double(
pointB.getX()-PIN_RADIUS,
pointB.getY()-PIN_RADIUS*2,
PIN_RADIUS*2,
PIN_RADIUS*2);
}
else // FOOTER
{
pointA = new Point2D.Double(i*2+2, 0);
pointB = new Point2D.Double(i*2+2, 2);
pinHeads[i] = new Ellipse2D.Double(
pointB.getX()-PIN_RADIUS,
3-PIN_RADIUS*2,
PIN_RADIUS*2,
PIN_RADIUS*2);
}
edgeLines[i] = new Line2D.Double(pointA, pointB);
}
}
@Override
public Dimension getMaximumSize()
{
return new Dimension(MAX_WIDTH_PX, (int)(MAX_WIDTH_PX*HEIGHT_RATIO));
}
@Override
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g2);
scaleTo(getSize());
g2.scale(widthFactor, widthFactor);
g2.setStroke(new BasicStroke((float)(2.0/widthFactor)));
for(Line2D line: edgeLines)
{
g2.draw(line);
}
for(Ellipse2D pin: pinHeads)
{
g2.draw(pin);
}
}
}
private abstract class WebSubPanel extends JPanel
{
protected static final int MAX_WIDTH_PX = 800;
public WebSubPanel()
{
super();
setBorder(null);
setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
}
public void scaleTo(Dimension d)
{
widthFactor = d.getWidth() / (double)widthMax;
heightFactor = d.getHeight() / (double)heightMax;
}
@Override
public Dimension getPreferredSize()
{
return getMaximumSize();
}
}
}
import java.awt.BasicStroke;
导入java.awt.Dimension;
导入java.awt.FlowLayout;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.geom.Line2D;
导入java.awt.geom.Point2D;
导入java.awt.geom.Ellipse2D;
导入javax.swing.Box;
导入javax.swing.BoxLayout;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共类置换Web扩展了JPanel
{
私有静态枚举EndPanelType
{
页眉、页脚
}
专用最终JPanel报头;
私人最终JPanel主面板;
私有最终JPanel页脚;
私人双因素;
私人双高度系数;
私有int-widthMax;
私人海特马克斯酒店;
私有int[]索引映射;
私有点2D。双[]端点;
专用线条2D。双[]绘制线条;
公共置换网络(整数索引,布尔ENDPOLENDSON)
{
超级();
setLayout(新的BoxLayout(这是BoxLayout.Y_轴));
最大宽度=(指数+1)*2;
heightMax=(int)数学圆(widthMax*(3.0/17.0));
宽度因子=1;
高度系数=1;
端点=新点2d.Double[索引*2];
drawingLines=新线2D.双[索引];
对于(int i=0;iABoxLayout
,如果空间可用,将调整组件的大小,使其达到最大尺寸
因此,您首先需要实现组件的getPreferredSize()
方法,以便可以按正常大小打包组件
然后,如果它能够增长(并且您的自定义绘图支持这一点),您可以覆盖getMaximumSize()
方法以返回大小
这幅画需要以面板的实际尺寸为基础,如果你希望它与其他面板相邻。
我必须检查代码多一点,但乍一看,看起来你应该考虑把所有这些画成一个单一的面板。你仍然可以达到所有想要的效果,并且不依赖于布局管理器。(对于“普通图形用户界面”来说,这很好,但对于定制绘画来说,这可能非常脆弱)@Marco13我肯定会选择一种更简单的解决方案,即一次绘制所有图形,但该项目需要根据用户的定义按需绘制不同自定义形状的不同配置,因此,如果我没有在这里面对这个问题,我以后将不可避免地面对它。我知道BoxLayout尊重最大尺寸,但您的答案是这让我尝试了最终解决问题的方法:我重写getMaximumSize(),使其宽度始终为MAX_值,高度由我为首选尺寸的高度设置的值决定,然后使用与实际宽度的比率来限制首选高度。