[英]Java Swing: Vertical Layout with fixed width and variable height
我正在寻找一个布局管理器(或一组布局管理器)来帮助我垂直安排我的组件。 所有组件(按钮)应具有相同的宽度,以下划线对话框客户区宽度为界。 这些按钮中的每个按钮都可以根据所连接的JLabel来扩展其高度(用户单击相关按钮后,标签将显示出来)-简而言之:所有组件都应拉伸到相同的固定宽度,但要可变高度取决于他们的内容。 整个对话框内容应放在JScrollPane中,以便在需要时支持垂直滚动条。
我就是这样,在那里我堆叠了许多不同的布局管理器(大多数是用于水平拉伸的borderlayout和用于垂直布置的boxlayout)来实现我的目标行为。 但它既不满足代码,也不能完全按照我的意愿运作。
我花了很多时间浏览互联网以解决这个问题,并发现垂直布局是Java中的常见问题。 很多人回答说GridBagLayout是做这项工作的最佳布局,但我没有按照我想要的方式工作。
我希望有足够的信息可以帮助我解决这个问题。
最好的问候Michael
编辑:-不再需要-
编辑2:
以下是我目前尝试的图片: http : //www.pic-upload.de/view-16978954/example-image.png.html
这几乎是我想要的结果,但在调整大小方面却有着奇怪的影响。
编辑3:
我认为我的主要问题是JScrollPane与包含JLabel的html结合使用,我需要类似setMaximumSize(...)的方法,但它不起作用,因为它应该: http : //www.pic-upload.de/view- 16988005 /示例-image3.png.html
我需要一个固定的宽度,但我找不到设置它的方法。
setPreferredSize(...)可以工作,但是我不知道JLabel的高度,因为它包含html文本。
编辑4:
我的按钮:
public class Expander extends JPanel implements ActionListener {
private static class HtmlViewer extends JLabel {
private static final long serialVersionUID = 8787130155299083869L;
public HtmlViewer(String doc) {
super(doc);
this.setBackground(Color.WHITE);
this.setOpaque(true);
}
}
private static final long serialVersionUID = 4480221797736558685L;
JToggleButton button;
JComponent component;
public Expander(String text, String doc) {
this(text, new HtmlViewer(doc));
}
public Expander(String text, JComponent expandableComponent) {
this.setLayout(new BorderLayout());
button = new JToggleButton(text) {
private static final long serialVersionUID = -3330376265192275758L;
@Override
public void paint(Graphics g) {
super.paint(g);
if (this.isSelected()) {
g.drawString("▼", this.getWidth() - 20, 15);
} else {
g.drawString("■", this.getWidth() - 20, 15);
}
}
};
button.setFocusPainted(false);
button.addActionListener(this);
component = expandableComponent;
component.setBorder(new EmptyBorder(5, 5, 5, 5));
this.add(button, BorderLayout.PAGE_START);
}
@Override
public void actionPerformed(ActionEvent e) {
if (button.isSelected()) {
this.add(component);
} else {
this.remove(component);
}
this.getTopLevelAncestor().validate();
this.getTopLevelAncestor().repaint();
this.setMaximumSize(this.getPreferredSize());
}
}
框架:
public class grid2 {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
JScrollPane scroll = new JScrollPane(p, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
addStuff(p);
frame.add(scroll);
frame.pack();
frame.setVisible(true);
}
public static void addStuff(Container container) {
container.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.weighty = 0;
Expander e = new Expander("test", "<html>fgb fdh fgfhg ifghiufdshfidsghfiufdsghiudsfhdsfiu dshiufhds if dhf idsufhdsiufhiufhiuds hfdshfiudshfuidsifudshfiudshf ufdhfiushdfiudshiufhdsiufhdsiuf udshfiudshfiudshfudshf iuhfiudshfiudshfiudshf</html>"); // long html text example
e.setMaximumSize(new Dimension(500, 10000));
c.gridx = 0;
c.gridy = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
container.add(e, c);
JButton button2 = new JButton("Button 2");
c.gridy = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
container.add(button2, c);
c.gridy = 2;
c.weighty = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
container.add(new JLabel(), c);
}
}
请参阅http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
我将使用的是GridBagLayout 。 它类似于HTML表,并且可以通过使用GridBagConstraints设置对象以在水平和垂直方向上展开(例如, constraints.fill = GridBagConstraints.BOTH
)
我相信这可以解决你在下面的图片中的问题(有一个小的黑客,通过在底部添加一个空白标签使按钮保持在顶部,但我敢肯定,更多的修补,这可以删除)
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addStuff(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public static void addStuff(Container container) {
container.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.weighty = 0;
JButton button = new JButton("Button 1");
c.gridx = 0;
c.gridy = 0;
container.add(button, c);
JButton button2 = new JButton("Button 2");
c.gridy = 1;
container.add(button2, c);
c.gridy = 2;
c.weighty = 1;
container.add(new JLabel(), c);
}
这里有几个问题:
JFrame
的BorderLayout
将拉伸你的JPanel p
weightx
,因此fill
属性是无用的 解决方案:
JPanel p
包装在另一个将它放在顶部的面板中,或者在末尾添加一个额外的隐形JPa来推动你的组件 weightx
属性设置为1.0
这是一个演示代码(基于你的),它的工作原理如下:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Gridbag {
public void initUI() {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel p = new JPanel(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
JButton button = new JButton("button 1");
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.PAGE_START;
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.weightx = 1.0;
p.add(button, constraints);
button = new JButton("button 2");
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.PAGE_START;
p.add(button, constraints);
JPanel root = new JPanel(new GridBagLayout());
constraints.weighty = 1.0;
root.add(p, constraints);
frame.add(root);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Gridbag().initUI();
}
});
}
}
好的,我让它上班了。 我完全错了,我认为JScrollPane是这个问题的麻烦制造者,但它是JLabel。 如果JLabel包含HTML文本,它将不会自动包装文本,这就是如果对话框的宽度太小,所有内容都水平拉伸的原因。 我在这里找到了一个很好的解决方案: 通过设置最大宽度使JLabel包装它的文本
答案6:
JLabel labelBeingUsed = myLabel;
View view = (View) labelBeingUsed.getClientProperty(BasicHTML.propertyKey);
view.setSize(scrollPane1.getWidth(), 0.0f);
float w = view.getPreferredSpan(View.X_AXIS);
float h = view.getPreferredSpan(View.Y_AXIS);
labelBeingUsed.setSize((int) w, (int) h);
每次调整对话框大小时,必须使用上面的代码将每个包含JLabel的HTML的宽度更新为所需的宽度。
非常感谢您提供所有有用的提示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.