2

スクロールバーのある表を真似したいのですが、幅に問題があります。これは非常に単純化されたコードです (ただし、これは完全なアプリケーションであるため、簡単にコンパイルしてすべてを直接見ることができます)。

package view;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

import net.miginfocom.layout.AC;
import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;
import net.miginfocom.swing.MigLayout;

public class AppView
{
    private final JFrame main_frame;

    public AppView()
    {
        main_frame = new JFrame();
        main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        main_frame.setTitle("Example");

        JPanel main_panel = new JPanel() {
            private static final long serialVersionUID = 1L;

            public Dimension getPreferredSize()
            {
                return new Dimension(300,  200);
            }
        };
        main_panel.setLayout(new MigLayout("fill"));

        JPanel table_panel = new JPanel();
        table_panel.setLayout(new MigLayout(new LC(), new AC().gap("0"), new AC().gap("0")));

        JScrollPane scroll_pane = new JScrollPane(table_panel);
        scroll_pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        int[] width_arr = {20, 20, 20, 20, 20};
        for (int i = 0; i < 60; i++) {
            for (int j = 0; j < width_arr.length; j++) {
                if (j == width_arr.length - 1)
                    table_panel.add(new JLabel(i + 1 + ", " + (j + 1)), new CC().width(width_arr[j] + "%").wrap());

                else
                    table_panel.add(new JLabel(i + 1 + ", " + (j + 1)),  new CC().width(width_arr[j] + "%"));
            }
        }

        main_frame.getContentPane().add(main_panel, BorderLayout.CENTER);
        main_panel.add(scroll_pane, new CC().grow());
        main_frame.pack();
        main_frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run() 
            {
                new AppView();
            }
        });
    }
}

ご覧のとおり、 を作成してtable_panelでラップしscroll_paneます。次に、各行に 5 つの JLabel を含む 60 行を追加します。問題は、行の合計幅が 100% になるように各列の幅を指定すると、スクロール要素の幅が急速に増加し始めることです。以下に 2 つのスクリーンショットを示します。1 つは水平スクロールが無効になっている場合、もう 1 つは水平スクロールが有効になっている場合です。 ここに画像の説明を入力ここに画像の説明を入力

このような動作についての私の提案は、JScrollPane要素の幅が非常に大きいということですが、この提案は正しくないようです。各列の幅を合計幅が 98% になるように定義すると、すべてが正常に機能するためです。

ここに画像の説明を入力

これらの奇妙なことを理解するのを手伝ってください。前もって感謝します。

[アップデート]

必要なものを達成するために、別のアプローチを使用することにしました。このアプローチは、グリッド機能に基づいています。小さな条件があります - すべての幅の値は 5 の倍数である必要があります。5% を超える精度が必要な状況を想像するのは難しいため、この条件は限定的ではないと思います。まず、20 個の非表示要素を追加します (span()メソッドをさらに呼び出すため)。

Box empty;
for (int i = 0; i < 20; i++) {
    empty = new Box(BoxLayout.X_AXIS);
    empty.setVisible(false);
    if (i == 19) 
        table_panel.add(empty, "wrap");
    else
        table_panel.add(empty);
}

これらの要素がなければ、span()メソッドは効果がありません。完全なコード サンプルは次のとおりです。

package view;

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

import net.miginfocom.layout.AC;
import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;
import net.miginfocom.swing.MigLayout;

public class AppView
{
    private final JFrame main_frame;

    public AppView()
    {
        main_frame = new JFrame();
        main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        main_frame.setTitle("Example");

        JPanel main_panel = new JPanel() {
            private static final long serialVersionUID = 1L;

            public Dimension getPreferredSize()
            {
                return new Dimension(300,  200);
            }
        };
        main_panel.setLayout(new MigLayout("fill"));

        JPanel table_panel = new JPanel();
        table_panel.setLayout(new MigLayout(new LC().fill().debug(1).hideMode(2), new AC().gap("0"), new AC().gap("0")));

        JScrollPane scroll_pane = new JScrollPane(table_panel);
        scroll_pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        Box empty;
        for (int i = 0; i < 20; i++) {
            empty = new Box(BoxLayout.X_AXIS);
            empty.setVisible(false);
            if (i == 19) 
                table_panel.add(empty, "wrap");
            else
                table_panel.add(empty);
        }

        int[] width_arr = {20, 20, 20, 20, 20};
        for (int i = 0; i < 60; i++) 
            for (int j = 0; j < width_arr.length; j++) {
                if (j == width_arr.length - 1)
                    table_panel.add(new JLabel(i + 1 + ", " + (j + 1)), new CC().span(width_arr[j] / 5).wrap());

                else
                    table_panel.add(new JLabel(i + 1 + ", " + (j + 1)),  new CC().span(width_arr[j] / 5));
            }

        main_frame.getContentPane().add(main_panel, BorderLayout.CENTER);
        main_panel.add(scroll_pane, new CC().grow());
        main_frame.pack();
        main_frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run() 
            {
                new AppView();
            }
        });
    }
}

これは実際には問題なく動作し、水平スクロールはもう必要ありませんが、非表示のボックスの幅に問題があります - それらの幅は一定ではなく、すべてのボックスで同じではなく、JLabels の幅に依存します。したがって、比率は正しくありません。そして、ここにいくつかのスクリーンショットがあり、それを示しています:

1) 最も単純なケース: 5 つの列、それぞれ 20% の幅で問題なく動作します。 ここに画像の説明を入力

2) より複雑な例: 3 つの列 - 10%、40%、50%。2 列目の幅が 1 列目の 4 倍ではないため、比率が無効です。

ここに画像の説明を入力 ここに画像の説明を入力

さて、次に何をすべきかわかりません。そして、インターネットで何かを見つけようとする試みはすべて無駄でした。

4

0 に答える 0