gpt4 book ai didi

java - 为什么 setPreferredSize() 有时会优先于 setMinimumSize()?

转载 作者:行者123 更新时间:2023-11-29 04:41:55 28 4
gpt4 key购买 nike

昨天我在向 JScrollPane 添加 JTableJPanel(其中包含 JButton)时出错JButton 固定在表格的底部,单击时它会向 JTable 添加一行。

问题是如果表格变得比 JScrollPane 大,它只会让你滚动到 JTable 的底部;您无法再访问 JButton。今天,我制作了一个 MCVE 来尝试获得帮助,但首先我对它进行了更多的尝试并最终解决了我的问题,但是在某种程度上给我留下的问题多于答案......这是我准备的 MCVE:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class MCVE extends JFrame{

private JButton addRow;
private MCVEModel tableModel;
private JTable table;
private JScrollPane pane;
private JPanel scrollPanel, panel;

public static void main (String[] args) {
new MCVE();
}

public MCVE() {
initialize();
}

public void initialize () {
this.setTitle("Halp");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setBounds(50, 50, 500, 300);
this.setResizable(false);

JPanel mainPanel = new JPanel(new GridBagLayout());

/** The JPanel everything is put into **/
scrollPanel = new JPanel();
scrollPanel.setLayout(new BoxLayout(scrollPanel, BoxLayout.Y_AXIS));

/** The JScrollPane we're using **/
pane = new JScrollPane(scrollPanel);
pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
pane.getVerticalScrollBar().setUnitIncrement(10);

/** The button which keeps getting cut off.... **/
addRow = new JButton("...");
addRow.setBackground(Color.WHITE);
addRow.setMnemonic('R');
addRow.setFocusable(false);
addRow.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addNewRow();
}
});

/** I wrap the button into this panel so I can affix it to the left **/
panel = new JPanel();
panel.setMinimumSize(new Dimension(0, 20));
panel.setLayout(null);
addRow.setBounds(0, 0, 35, 15);
panel.add(addRow);

/** Faking some data to get the table to populate **/
ArrayList<List<String>> allData = new ArrayList<List<String>>();
ArrayList<String> fakeData = new ArrayList<String>();
fakeData.addAll(Arrays.asList(
new String[]{"this", "is", "just", "sample", "data"}));
for(int i = 0; i < 5; i++)
allData.add(fakeData);

List<String> columnNames = Arrays.asList(new String[] {"", "", "", "", ""});
tableModel = new MCVEModel(columnNames, allData);

table = new JTable();
table.setModel(tableModel);

/** Adding it all together **/
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
scrollPanel.add(table);
scrollPanel.add(panel);
mainPanel.add(pane, c);
this.add(mainPanel);

this.setVisible(true);
}

public void addNewRow () {
tableModel.addRow(tableModel.getRowCount(),
new String[]{"true", "", "", "false", "false"});
tableModel.fireTableRowsInserted(
tableModel.getRowCount(), tableModel.getRowCount());
}
}
/**
* Just here to keep things compilable. Seriously cut back for the MCVE,
* but still replicates the problem without any errors.
* Nothing below here should be relevant to the issue.
*/
class MCVEModel extends DefaultTableModel {

private static final long serialVersionUID = -6598574844380686148L;
private List<String> columnNames;
private List<List<String>> values;

public MCVEModel (List<String> columnNames, List<List<String>> strings) {
this.columnNames = columnNames;
this.values = strings;
}

public int getColumnCount() {
return columnNames.size();
}

public int getRowCount() {
return values == null || values.size() == 0 ? 0 : values.get(0).size();
}

public String getColumnName(int col) {
return columnNames.get(col);
}

public Object getValueAt(int row, int col) {
return values.get(col).get(row);
}

@SuppressWarnings({ "unchecked", "rawtypes" })
public Class getColumnClass(int c) {
return String.class;
}

public boolean isCellEditable(int row, int col) {
return true;
}

public void setValueAt(Object value, int row, int col) {
values.get(col).set(row, (String) value);
fireTableCellUpdated(row, col);
}

public void removeRow(int row) {
for(int i = 0; i < values.size(); i++)
values.get(i).remove(row);
this.fireTableRowsDeleted(row, row);
}

public void addRow(int row, String[] strings) {
for(int i = 0; i < values.size(); i++)
values.get(i).add(row, strings[i]);
fireTableRowsInserted(row, row);
}
}

问题出在这一行:

panel.setMinimumSize(new Dimension(0, 20));

更准确的说,是“最小”二字。通过将其更改为:

panel.setPreferredSize(new Dimension(0, 20));

我得到了我需要的功能。现在,当表格对于 JScrollPanel 来说太大时,我们仍然可以向下滚动并看到 JButton;它不再被切断。

我假设这意味着 JPanel 的父级不遵守其最小尺寸,但它确实遵守其首选尺寸。为什么是这样?我原以为 setPreferredSize()setMinimumSize()setMaximumSize() 的交互就像是“我宁愿这么大,但是无论如何我都不能小于我的最小值或大于我的最大值,”但似乎并非如此。我知道这些方法都不应该过于频繁地使用,但是我什么时候应该使用 setMinimumSize() 而不是 setPreferredSize() ,反之亦然?

最佳答案

神奇的是这一行:

scrollPanel.add(panel);

因此,scrollPanel 将包含此面板。然后,JScrollPane 遵循 preferredSize-s。这是有道理的,因为它的目的是通过使用滚动条为包含的组件腾出足够的空间。换句话说,JScrollPane -s 实现忽略了 minimumSize-s。

更新:

从另一个角度来看,JScrollPane -s 源代码会检查其子项的preferredSize,但不会检查minimumSize。这里没什么深意,JScrollPane就是这么实现的。

关于java - 为什么 setPreferredSize() 有时会优先于 setMinimumSize()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38875753/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com