9

JScrollPaneJava アプリケーションで使用するときに小さな問題があります。

JScrollPane含む がありJPanelます。これJPanelは、任意の幅のボタン (垂直方向に並べられたもの) で動的に更新されます。は、その幅を内部JPanelの最大のコンポーネントに合わせて自動的に調整します。JButton

垂直スクロールバーが表示されると、 my の右側のスペースが取り除かれ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();
                }
            }
        });
    }
}
4

3 に答える 3

6

これは単純ですが、きれいではありませんが、解決策です。

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 を実装してスクロールを完全に制御し、ビューポートの高さを追跡して空想的なトリックを実行して、スペースが利用可能になったときにボタンが拡張されるようにし、垂直スクロール バーの幅を常に適切な幅に追加します。垂直スクロールバーが表示されている場合は拡大できますが、とにかく見た目が悪いです。次のように使用します。

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

javax.swing.ScrollPaneLayout のバグの可能性があるため、この回避策が必要なようです。

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

ここで、extentSize はビューポートの優先サイズに設定され、viewSize は viewport.getViewSize() に設定されます。これは正しくないようです。私の知る限り、ビューポート内のビューのサイズは常に推奨サイズと等しくなければなりません。ビューのサイズは、ビューポートの推奨サイズではなく、実際のサイズと比較する必要があるようです。

于 2012-04-26T11:25:54.943 に答える
2

に関する要求を満たすための簡単な回避策

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();
                }
            }
        });
    }
}
于 2012-04-26T13:01:06.977 に答える
0

JPanel のサイズを変更する必要がある場合は、setPreferredSize を呼び出して JPanel のサイズを変更できます。

buttonContainer.setPreferredSize(Dimension d);
于 2012-04-26T11:38:08.933 に答える