gpt4 book ai didi

java - 出现滚动条时包含 JPanel 的 JScrollPane 调整大小

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:47:05 25 4
gpt4 key购买 nike

在我的 Java 应用程序中使用 JScrollPane 时遇到一个小问题。

我有一个包含 JPanelJScrollPane。此 JPanel 使用任意宽度的按钮(垂直排序)动态更新。JPanel 自动将其宽度调整为内部最大的 JButton 组件。

现在,当垂直滚动条出现时,它会占用我的 JPanel 右侧的一些空间,这会导致最大的按钮无法完全显示。除了显示整个按钮之外,我不想使用水平滚动条。

有没有一种方法可以在出现滚动条时调整我的 JPanel 的大小,使其很好地显示在我的按钮旁边?或者是否有任何其他方法可以让滚动条出现在我的 JPanel 旁边?

提前致谢!

编辑:这是我的问题的演示。当您将窗口调整到较小的高度时,右侧的一小部分按钮会被覆盖。

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.GridLayout;

/**
* @author Dylan Kiss
*/

public class Demo {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame myFrame = new JFrame("Demo");
JPanel sideBar = new JPanel();
JPanel centerPanel = new JPanel();
centerPanel.add(new JLabel("This is the center panel."));

JPanel buttonContainer = new JPanel();
JButton myButton = null;

for (int i = 0; i < 20; i++) {
buttonContainer.setLayout(new GridLayout(20, 1, 0, 0));
myButton = new JButton("This is my button nr. " + i);
buttonContainer.add(myButton);
}

sideBar.setLayout(new BorderLayout(0, 0));

JScrollPane scrollPane = new JScrollPane(buttonContainer);

sideBar.add(scrollPane);

myFrame.getContentPane().add(sideBar, BorderLayout.WEST);
myFrame.getContentPane().add(centerPanel, BorderLayout.CENTER);

myFrame.setLocationByPlatform(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.pack();
myFrame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}

最佳答案

这是一个简单但不漂亮的解决方案:

scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

编辑:我认为这可能无法解决您的问题。这是一个更好的解决方案,尽管它有很多样板文件:

private class ButtonContainerHost extends JPanel implements Scrollable {
private static final long serialVersionUID = 1L;

private final JPanel buttonContainer;

public ButtonContainerHost(JPanel buttonContainer) {
super(new BorderLayout());
this.buttonContainer = buttonContainer;
add(buttonContainer);
}

@Override
public Dimension getPreferredScrollableViewportSize() {
Dimension preferredSize = buttonContainer.getPreferredSize();
if (getParent() instanceof JViewport) {
preferredSize.width += ((JScrollPane) getParent().getParent()).getVerticalScrollBar()
.getPreferredSize().width;
}
return preferredSize;
}

@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return orientation == SwingConstants.HORIZONTAL ? Math.max(visibleRect.width * 9 / 10, 1)
: Math.max(visibleRect.height * 9 / 10, 1);
}

@Override
public boolean getScrollableTracksViewportHeight() {
if (getParent() instanceof JViewport) {
JViewport viewport = (JViewport) getParent();
return getPreferredSize().height < viewport.getHeight();
}
return false;
}

@Override
public boolean getScrollableTracksViewportWidth() {
return true;
}

@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return orientation == SwingConstants.HORIZONTAL ? Math.max(visibleRect.width / 10, 1)
: Math.max(visibleRect.height / 10, 1);
}
}

它实现了 Scrollable 以获得对滚动的完全控制,通过跟踪视口(viewport)高度来确保按钮在空间可用时扩展并始终将垂直滚动条的宽度添加到首选宽度。当垂直滚动条可见时它可能会展开,但无论如何看起来都很糟糕。像这样使用它:

scrollPane = new JScrollPane(new ButtonContainerHost(buttonContainer));

在我看来,由于 javax.swing.ScrollPaneLayout 中可能存在错误,因此需要此解决方法:

if (canScroll && (viewSize.height > extentSize.height)) {
prefWidth += vsb.getPreferredSize().width;
}

此处 extentSize 设置为视口(viewport)的首选大小,viewSize 设置为 viewport.getViewSize()。这似乎不正确,据我所知,视口(viewport)内 View 的大小应始终等于首选大小。在我看来, View 大小应该与视口(viewport)的实际大小而不是其首选大小进行比较。

关于java - 出现滚动条时包含 JPanel 的 JScrollPane 调整大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10331129/

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