我使用的时候有一个小问题JScrollPane
在我的Java应用程序。
我有一个JScrollPane
包含JPanel
。 此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);
}
}
它实现滚动来获得滚动的完全控制,确实看中招与跟踪视口高度,以保证钮扣扩大时的可用空间,并在任何时候垂直滚动条的首选宽度的宽度增加了。 当垂直滚动条是可见的,但看起来不错反正它可能会扩大。 使用这样的:
scrollPane = new JScrollPane(new ButtonContainerHost(buttonContainer));
它看起来对我来说,是因为在javax.swing.ScrollPaneLayout中一个可能的错误所需要的这种解决方法:
if (canScroll && (viewSize.height > extentSize.height)) {
prefWidth += vsb.getPreferredSize().width;
}
这里EXTENTSIZE设置为视口的最佳尺寸和viewSize设置为viewport.getViewSize()。 这似乎并不正确,据我所知视口内的视图的大小应该总是等于首选大小。 在我看来,该视图的大小应该是比较视口,而不是其首选大小的实际大小。
一个简单的解决办法,以满足您的需求有关
Is there a way to resize my JPanel when a scrollbar appears, so it
appears nicely next to my buttons?
是使用EmptyBorder ,这将让你实现你想吃什么,应该发生,如下面的图所示:
我刚添加该线这条线以下后写入JPanel buttonContainer = new JPanel();
添加的行
buttonContainer.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
下面是与添加一行代码:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
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();
buttonContainer.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
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.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myFrame.pack();
myFrame.setLocationByPlatform(true);
myFrame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
你可以通过调用了setPreferredSize调整的JPanel时的JPanel需要调整大小。
buttonContainer.setPreferredSize(Dimension d);