我花了一段时间从我的大型程序中创建一个sscce,我希望它足够小!
我的JSplitPane上面有一张桌子,下面是JPanel。
底部面板包含较小的JPanel或条目'。随着条目数量的增加,底部的SplitPane占用顶部窗格的空间。
Dimension dim = getPreferredSize();
setPreferredSize(dim);
在第一堂课中,取消注释此代码可以解决问题,但我不知道为什么。如果有人可以提供帮助,我想了解如何更好地处理调整大小问题? (我还要处理水平扩展的文本区域,这是一些限制可能看起来有些奇怪的原因之一)
这是下面的面板:
package example;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.border.Border;
public class BottomPanel extends JPanel{
private JLabel summary = new JLabel();
private EntryPanel entryPanel = new EntryPanel();
public BottomPanel() {
//Dimension dim = getPreferredSize();
//setPreferredSize(dim);
setLayout(new GridBagLayout());
entryPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
setComponents();
}
private void setComponents() {
Border test = BorderFactory.createLineBorder(Color.BLUE);
JScrollPane jsp = new JScrollPane(entryPanel);
JPanel dummy1 = new JPanel();
JPanel dummy2 = new JPanel();
JPanel dummy3 = new JPanel();
dummy1.setBorder(test);
dummy2.setBorder(test);
dummy3.setBorder(test);
int row = 0;
add(dummy1, new GBC(0,row).setWeight(0,0));
// new row
row++;
add(summary, new GBC(1,row).setAnchor(GBC.LINE_START));
// new row
row++;
add(jsp, new GBC(1,row).setWeight(50,70).setFill(GBC.BOTH));
// new row
row++;
add(dummy2, new GBC(2,row).setWeight(0,0));
}
private class EntryPanel extends JPanel{
private List<JPanel> entries = new ArrayList<>();
private int row = 0;
private EntryPanel(){
setLayout(new GridBagLayout());
for(int x = 0; x < 20; x++)
createEntryItem("TEST", "test text");
}
private void createEntryItem(String s, String text){
Border test = BorderFactory.createLineBorder(Color.GREEN);
JPanel entryItem = new JPanel();
entryItem.setBorder(test);
entryItem.setLayout(new GridBagLayout());
JLabel title = new JLabel(s);
JTextArea details = new JTextArea(text);
entryItem.add(title, new GBC(0,0).setAnchor(GBC.LINE_START));
entryItem.add(details, new GBC(0,1).setAnchor(GBC.LINE_START));
entryItem.add(new JPanel(), new GBC(1,0).setWeight(100,0));
entries.add(entryItem);
displayEntry(entryItem);
}
private void displayEntry(JPanel entry){
JPanel dummy = new JPanel();
add(entry, new GBC(0,row).setAnchor(GBC.LINE_START).setFill(GBC.HORIZONTAL));
add(dummy, new GBC(1,row).setWeight(100, 0));
row++;
}
}
}
和包含框架和面板:
package example;
import java.awt.*;
import javax.swing.*;
public class Example extends JFrame{
private GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
private int width = (int)((gd.getDisplayMode().getWidth())*0.5);
private int height = (int)((gd.getDisplayMode().getHeight())*0.75);
private JPanel mainPanel = new JPanel();
private JSplitPane sp;
private JTable table = new JTable();
private BottomPanel bp = new BottomPanel();
public Example () {
setSize(width,height);
setLayout(new BorderLayout());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,new JScrollPane(table), bp);
add(sp);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
Example ex = new Example();
}
});
}
}
和GridBagHelper:
package example;
import java.awt.GridBagConstraints;
public class GBC extends GridBagConstraints{
public GBC(int gridx, int gridy){
this.gridx = gridx;
this.gridy = gridy;
}
public GBC setAnchor(int anchor){
this.anchor = anchor;
return this;
}
public GBC setFill(int fill){
this.fill = fill;
return this;
}
public GBC setWeight(double weightx, double weighty){
this.weightx = weightx;
this.weighty = weighty;
return this;
}
}
任何帮助或建议都会非常感激 - 我自学成才,并且正在苦苦挣扎!
由于
答案 0 :(得分:2)
我太累了,无法写出正确的答案,但我正在浏览这个,我看到的第一个问题之一是setSize(width,height)
Example
的构造函数。最好在pack()
上调用JFrame
,然后让它自动调整大小。
我认为pack
JScrollPane
可能有点不可预测pack
。从记忆中,我已经做了一些奇怪的事情,比如将滚动窗格折叠到最小尺寸。
在代码示例中使用BottomPanel
似乎试图围绕public Example () {
// setSize(width,height);
// setLayout(new BorderLayout());
sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,new JScrollPane(table), bp);
sp.setResizeWeight(2.0 / 3.0);
sp.setPreferredSize(width, height);
setContentPane(sp);
// add(sp);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
中面板的总和来调整大小。 (总和会高于我的屏幕分辨率,所以我无法确定具体行为是什么。它会在屏幕高度处限制窗口的高度。)
更优雅的方式来做你想做的事情是这样的:
JScrollPane
我使用setResizeWeight
来实现拆分窗格比例,并设置窗格的首选大小而不是窗口。
这与您喜欢的结果非常相似,但它更合适一些。可能是这里经验丰富的Swing用户之一知道更好的方式来使用setPreferredSize
,例如不涉及明确的{{1}}。
答案 1 :(得分:1)
我想我的问题是为什么获取preferredSize,然后设置preferredSize会有所不同?
如果我们深入挖掘代码,您就会发现......
public void setPreferredSize(Dimension preferredSize) {
Dimension old;
// If the preferred size was set, use it as the old value, otherwise
// use null to indicate we didn't previously have a set preferred
// size.
if (prefSizeSet) {
old = this.prefSize;
}
else {
old = null;
}
this.prefSize = preferredSize;
prefSizeSet = (preferredSize != null);
firePropertyChange("preferredSize", old, preferredSize);
}
您可以查看getPreferredSize
的工作原理......
public boolean isPreferredSizeSet() {
return prefSizeSet;
}
/**
* Gets the preferred size of this component.
* @return a dimension object indicating this component's preferred size
* @see #getMinimumSize
* @see LayoutManager
*/
public Dimension getPreferredSize() {
return preferredSize();
}
/**
* @deprecated As of JDK version 1.1,
* replaced by <code>getPreferredSize()</code>.
*/
@Deprecated
public Dimension preferredSize() {
/* Avoid grabbing the lock if a reasonable cached size value
* is available.
*/
Dimension dim = prefSize;
if (dim == null || !(isPreferredSizeSet() || isValid())) {
synchronized (getTreeLock()) {
prefSize = (peer != null) ?
peer.getPreferredSize() :
getMinimumSize();
dim = prefSize;
}
}
return new Dimension(dim);
}
这将返回用户设置preferredSize(如果已设置),而不是计算自己的。
我当然要分配一个已经存在的值吗?
但是在将任何组件添加到容器
之前,请调用setPreferredSize
如果您将代码更改为......
Dimension dim = getPreferredSize();
System.out.println(dim);
setPreferredSize(dim);
它会打印出像java.awt.Dimension[width=10,height=10]
这样的东西,所以,是的,小......
但是,如果你使用类似的东西......
public BottomPanel() {
setLayout(new GridBagLayout());
entryPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
setComponents();
Dimension dim = getPreferredSize();
System.out.println(dim);
setPreferredSize(dim);
}
打印出java.awt.Dimension[width=105,height=710]
故事的基本道德是,除非你有非常非常好的理由,否则不要打电话给setPreferred/Minimum/MaximumSize
,即便如此,也要考虑覆盖getPreferredSize
。计算组件的大小并不是其他人的责任,而是组件本身