在 top-left 角对齐 ScrollPane 时遇到困难
Difficulties in aligning ScrollPane in top-left corner
问题是,如何在 resizeble JPane
中对齐 JScrollPane
,使其对齐 top-left 角而不是中心?
这似乎是一项显而易见的任务,但我花了几个小时尝试所有不同的布局和属性。
沮丧可以表达,因为我只有两个选择:
- 使用尊重儿童最大偏好尺寸的布局,例如
FlowLayout
。副作用 - ScrollPane
开始表现得像普通的 Panel
:
- 使用可伸缩布局,例如
BorderLayout
并将元素放入 BorderLayout.CENTER
(BorderLayout.PAGE_START
导致 1.)。我对面板的位置失去了控制,它在中心:
当 window 较小时,滚动会按预期工作:
是否有可能同时拥有两个世界:JScrollPane
不会超出最大首选大小,但不会丢失 Scroll?
如果有人需要源代码:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
public class MainPanelTest extends JFrame {
public static void main(String[] args) {
new MainPanelTest().setVisible(true);
}
public MainPanelTest() {
super();
this.setLayout(new BorderLayout());
setupGUI();
}
private void setupGUI() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
this.add(tabbedPane, BorderLayout.CENTER);
JComponent filesPanel = setupFilesPanel();
tabbedPane.addTab("Files", filesPanel);
JPanel secondPanel = new JPanel();
tabbedPane.addTab("Placeholder", secondPanel);
}
private JComponent setupFilesPanel() {
JPanel filesPanel = new JPanel();
filesPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
for(int i=0; i<15; i++) {
c.gridy = i;
filesPanel.add(new JLabel("Test row " + i), c);
}
JScrollPane scrollFilesPane = new JScrollPane(filesPanel);
scrollFilesPane.setMaximumSize(scrollFilesPane.getPreferredSize());
return scrollFilesPane;
}
}
看看这是否是您要实现的目标:
private JComponent setupFilesPanel() {
JPanel filesPanel = new JPanel();
filesPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
for(int i=0; i<15; i++) {
c.gridy = i;
filesPanel.add(new JLabel("Test row " + i), c);
}
// ---- Add this
JPanel newPanel = new JPanel(new GridBagLayout());
c.weightx = 1;
c.weighty = 1;
newPanel.setBackground(Color.yellow);
newPanel.add(filesPanel, c);
// ----
// ---- change the panel you pass to JScrollPanel constructor:
JScrollPane scrollFilesPane = new JScrollPane(newPanel); // <--------- newPanel
scrollFilesPane.setMaximumSize(scrollFilesPane.getPreferredSize());
return scrollFilesPane;
}
更改已发表评论。
GridBagLayout
将 space 划分为组件所在的逻辑单元。 anchor
仅在逻辑单元格大于其组件时才相关。如果同一 row/column 中的组件需要更大的尺寸,或者如果有额外的 space 并且关联的 weightx
或 weighty
值不为零,则可能会发生这种情况。由于您想要的行为是关于额外的 space,因此您必须相应地设置权重值。唯一列的 weightx
将是非零的,但最后一行的 weighty
将是非零的,只会占据它下面的整个 space:
GridBagLayout gridBagLayout = new GridBagLayout();
JPanel filesPanel = new JPanel(gridBagLayout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.NORTHWEST;
c.weightx = 1; // for the column
for(int i=0; i<15; i++)
filesPanel.add(new JLabel("Test row " + i), c);
// now change the last row:
c.weighty = 1;
gridBagLayout.setConstraints(
filesPanel.getComponent(filesPanel.getComponentCount()-1), c);
或者,您可以不修改单元格,但通过添加额外的空白行和列来操纵整个布局,消耗额外的 space,这将有效地将原始行和列移动到左上角:
// add all visible components which should not grow
GridBagLayout gridBagLayout = new GridBagLayout();
JPanel filesPanel = new JPanel(gridBagLayout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = GridBagConstraints.REMAINDER;
for(int i=0; i<15; i++)
filesPanel.add(new JLabel("Test row " + i), c);
// add an extra row consuming vertical extra space
int nRows=filesPanel.getComponentCount();
gridBagLayout.rowHeights=new int[nRows+1];
gridBagLayout.rowWeights=new double[nRows+1];
gridBagLayout.rowWeights[nRows]=1;
// add an extra column consuming extra horizontal space
gridBagLayout.columnWidths=new int[] { 0, 0 };
gridBagLayout.columnWeights=new double[] { 0, 1 };
问题是,如何在 resizeble JPane
中对齐 JScrollPane
,使其对齐 top-left 角而不是中心?
这似乎是一项显而易见的任务,但我花了几个小时尝试所有不同的布局和属性。
沮丧可以表达,因为我只有两个选择:
- 使用尊重儿童最大偏好尺寸的布局,例如
FlowLayout
。副作用 -ScrollPane
开始表现得像普通的Panel
:
- 使用可伸缩布局,例如
BorderLayout
并将元素放入BorderLayout.CENTER
(BorderLayout.PAGE_START
导致 1.)。我对面板的位置失去了控制,它在中心:
当 window 较小时,滚动会按预期工作:
是否有可能同时拥有两个世界:JScrollPane
不会超出最大首选大小,但不会丢失 Scroll?
如果有人需要源代码:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
public class MainPanelTest extends JFrame {
public static void main(String[] args) {
new MainPanelTest().setVisible(true);
}
public MainPanelTest() {
super();
this.setLayout(new BorderLayout());
setupGUI();
}
private void setupGUI() {
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
this.add(tabbedPane, BorderLayout.CENTER);
JComponent filesPanel = setupFilesPanel();
tabbedPane.addTab("Files", filesPanel);
JPanel secondPanel = new JPanel();
tabbedPane.addTab("Placeholder", secondPanel);
}
private JComponent setupFilesPanel() {
JPanel filesPanel = new JPanel();
filesPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
for(int i=0; i<15; i++) {
c.gridy = i;
filesPanel.add(new JLabel("Test row " + i), c);
}
JScrollPane scrollFilesPane = new JScrollPane(filesPanel);
scrollFilesPane.setMaximumSize(scrollFilesPane.getPreferredSize());
return scrollFilesPane;
}
}
看看这是否是您要实现的目标:
private JComponent setupFilesPanel() {
JPanel filesPanel = new JPanel();
filesPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
for(int i=0; i<15; i++) {
c.gridy = i;
filesPanel.add(new JLabel("Test row " + i), c);
}
// ---- Add this
JPanel newPanel = new JPanel(new GridBagLayout());
c.weightx = 1;
c.weighty = 1;
newPanel.setBackground(Color.yellow);
newPanel.add(filesPanel, c);
// ----
// ---- change the panel you pass to JScrollPanel constructor:
JScrollPane scrollFilesPane = new JScrollPane(newPanel); // <--------- newPanel
scrollFilesPane.setMaximumSize(scrollFilesPane.getPreferredSize());
return scrollFilesPane;
}
更改已发表评论。
GridBagLayout
将 space 划分为组件所在的逻辑单元。 anchor
仅在逻辑单元格大于其组件时才相关。如果同一 row/column 中的组件需要更大的尺寸,或者如果有额外的 space 并且关联的 weightx
或 weighty
值不为零,则可能会发生这种情况。由于您想要的行为是关于额外的 space,因此您必须相应地设置权重值。唯一列的 weightx
将是非零的,但最后一行的 weighty
将是非零的,只会占据它下面的整个 space:
GridBagLayout gridBagLayout = new GridBagLayout();
JPanel filesPanel = new JPanel(gridBagLayout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = GridBagConstraints.REMAINDER;
c.anchor = GridBagConstraints.NORTHWEST;
c.weightx = 1; // for the column
for(int i=0; i<15; i++)
filesPanel.add(new JLabel("Test row " + i), c);
// now change the last row:
c.weighty = 1;
gridBagLayout.setConstraints(
filesPanel.getComponent(filesPanel.getComponentCount()-1), c);
或者,您可以不修改单元格,但通过添加额外的空白行和列来操纵整个布局,消耗额外的 space,这将有效地将原始行和列移动到左上角:
// add all visible components which should not grow
GridBagLayout gridBagLayout = new GridBagLayout();
JPanel filesPanel = new JPanel(gridBagLayout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = GridBagConstraints.REMAINDER;
for(int i=0; i<15; i++)
filesPanel.add(new JLabel("Test row " + i), c);
// add an extra row consuming vertical extra space
int nRows=filesPanel.getComponentCount();
gridBagLayout.rowHeights=new int[nRows+1];
gridBagLayout.rowWeights=new double[nRows+1];
gridBagLayout.rowWeights[nRows]=1;
// add an extra column consuming extra horizontal space
gridBagLayout.columnWidths=new int[] { 0, 0 };
gridBagLayout.columnWeights=new double[] { 0, 1 };