4

9つのjbuttonがjpanelに追加され、パネルがjscrollpaneに追加され、jframeに追加されました。

http://www.pic1.iran-forum.ir/images/up9/95426323683658592564.jpg

フレームの向きを変更するとき: applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

パネルが右に移動し、ボタンのサイズが固定されてパネルを埋めることができませんでしたが、下の画像では、スクロールバーがパネルの全幅を埋めていることがわかります

http://www.pic1.iran-forum.ir/images/up9/60975202722295688553.jpg

(ボタンの追加にはgridbaglayoutを使用し、スクロールペインの追加にはborderlayout.centerを使用しました)。

それはJavaのバグですか?

編集:その最も単純なビュー。それは役に立ちますか?

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;

public class MyFrame extends JFrame{
private JButton[] arrayButton = new JButton[9];
private JButton btnLeft = new JButton("<");
private JButton btnRight = new JButton(">");
private JScrollPane scpButtons = new JScrollPane();

public MyFrame() {
    for (int i = 0; i < arrayButton.length; i++) 
        arrayButton[i] = new JButton("btn");

    JPanel pnlButton = initPnlButton();
    scpButtons.setViewportView(pnlButton);
    setLayout(new BorderLayout());
    add(scpButtons, BorderLayout.CENTER);

           // comment it and see the result 
    applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);      
    pack();
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setExtendedState(JFrame.MAXIMIZED_BOTH);
    setVisible(true);
}

private JPanel initPnlButton() {
    JPanel pnlButton = new JPanel(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, 10,
            1, new Insets(0, 0, 0, 0), 0, 0);

    int ind = 0;
    int row = 3;
    int column = 4;
    for (int i = 0; i < row; i++) {
        for (int j = 1; j < column; j++) {
            gbc.gridx = j;
            gbc.gridy = i;
            pnlButton.add(arrayButton[ind++], gbc);
        }
    }
    gbc.weightx = 0;
    gbc.gridheight = 3;
    gbc.gridx = 0;
    gbc.gridy = 0;
    pnlButton.add(btnLeft, gbc);
    gbc.gridx = 4;
    gbc.gridy = 0;
    pnlButton.add(btnRight, gbc);
    pnlButton.setPreferredSize(new Dimension(1000, 700));
    return pnlButton;
}
public static void main(String[] args) {
    new MyFrame();
}
}
4

2 に答える 2

4

編集 4

(できれば最後に :-)

最終的な原因は、scrollPane のメイン ビューポートにあるようです。RToL でビューのサイズを変更すると、優先されるサイズよりも小さくなると混乱します。何がうまくいかないのかを正確に追跡しませんでしたが、実行可能なように見えます (コアのバグを見つけて、それを修正するために snoracle を微調整することはできません ;) 解決策は、ビューに Scrollableable を実装させることです。

  • getPreferredScrollableViewportSize が getPreferredSize を返す
  • getScrollableTracksViewportHeight/Width を実装して、高さ/幅が親の高さ/幅より小さい場合は true を返し、それ以外の場合は false を返します

JXPanel ( SwingX に含まれる)は、デフォルトで最初の処理を実行する Scrollable であり、必要に応じて ScrollableSizeHints を設定することで後者用に構成できます。

private JPanel initPnlButton() {
    JXPanel pnlButton = new JXPanel(new GridBagLayout());
    pnlButton.setScrollableWidthHint(ScrollableSizeHint.PREFERRED_STRETCH);
    pnlButton.setScrollableHeightHint(ScrollableSizeHint.PREFERRED_STRETCH);
    ...
}

すべてのコンポーネントを追加した後、CO を適用するだけです。

applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
pack();
setExtendedState(JFrame.MAXIMIZED_BOTH);
setVisible(true);

編集 2

私たち (@Reza Gh と私) がオプションをいじるほど、その動作をバグと見なす傾向があります。最新の調査結果をまとめると

  • scrollPane が主な原因のようです (Reza)
  • パネルがそのpreferredSize以下にサイズ変更されると、誤動作が始まります(人工物に注意してください-少なくともRezaのプロダクションコードの一部ではないことを願っています-パネルの作成時にsetPreferredを使用します)

編集

もう少し遊んでみると、インスタンス化時の非常に奇妙な動作のように見えます。(インスタンス化の最後に) 使用するスニペット

pack();
// [1]
setSize(getWidth() + 1, getHeight() + 1);
// [2]
setExtendedState(JFrame.MAXIMIZED_BOTH);
setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
    }
});

およびコメント 1、2、またはその両方

  • 両方にコメント: フレームはパックされたサイズで表示され、最大化するとフレームがいっぱいになりませんが、子は右端にドッキングされます
  • コメント 1: フレームが最大化されたサイズで表示され、子が完成したコンテンツを塗りつぶし、次にサイズを変更してパックし、再度最大化します: 子は塗りつぶされません
  • コメント 2: フレームはほぼ (1 ピクセル大きい) 圧縮されたサイズになり、最大化 (および他のすべてのサイズ変更) は画面を正しく埋めます

正確な動作は、おそらくネイティブ コンポーネントの向きにも依存します (私の場合は LToR です)。全体として、これはコンポーネント指向のコア処理のどこかにバグがあると思います (驚くべきことではありませんが、何年も経っても期待するほど安定していません)。

パックの後にサイズを変更し (1 ピクセル程度、最大値だけでは機能しません)、applyCO を呼び出すハックのようです。

オリジナル

これは元の問題 (フレームのインスタンス化に componentOrientation を適用すること) を解決するものではなく、実行時に CO を安全に切り替える方法を示すだけです。

Action createCOToggle(final JFrame frame) {
    Action toggleComponentOrientation = new AbstractAction("toggle orientation") {

        @Override
        public void actionPerformed(ActionEvent e) {
            ComponentOrientation current = frame.getComponentOrientation();
            if (current.isLeftToRight()) {
                frame.applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
            } else {
                frame.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
            }
            frame.getRootPane().revalidate();
            frame.invalidate();
            frame.validate();
            frame.repaint();
        }

    };
    return toggleComponentOrientation;
}

それを使用してアクション認識コンポーネントを構成すると、フレームが期待どおりに動作し、領域全体が塗りつぶされます。多くの re/in/validate は奇妙に見えますが、 SwingX のテスト カバレッジで経験したように (jdk6 で) 必要であることが判明しました

今、私の期待は、フレームのインスタンス化の最後に同じアクションを呼び出すと、それも同様に動作するということです。

.... // configure/fill frame
setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        createCOToggle(MyFrame.this).actionPerformed(null);
    }
});

残念ながら、そうではありません。現在のところ、理由についての手がかりはありません。申し訳ありません。

于 2012-08-26T11:34:22.547 に答える
1

多くのプロパティで遊んで、ステートメントを上下に移動した後、答えを見つけました。あなたが置くなら

scpButtons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);

すべてがうまくいき、その必要はありませんsetSize(getWidth() + 1, getHeight() + 1);

とても面白いので、私から丸一日を過ごしました:) C#または他の言語にはこのようなバグがありますか?

ブロックを実行させSwingUtilitiesた場合、ウィンドウのサイズを変更する前に、すべてがまだLtRです。

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;

public class MyFrame extends JFrame {
private JButton[] arrayButton = new JButton[9];
    private JButton btnLeft = new JButton("<");
    private JButton btnRight = new JButton(">");
    private JScrollPane scpButtons = new JScrollPane();

    public MyFrame() {
        for (int i = 0; i < arrayButton.length; i++)
            arrayButton[i] = new JButton("btn");

        JMenu mnuSettings = new JMenu("MENU");
        JMenuBar menubar = new JMenuBar();
        menubar.add(mnuSettings);
        setJMenuBar(menubar);

        JPanel pnlButton = initPnlButton();
        scpButtons.setViewportView(pnlButton);
        setLayout(new BorderLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        add(scpButtons, BorderLayout.CENTER);

        pack();
        // [1]
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        //setSize(getWidth() + 1, getHeight() + 1);
        // [2]
        setVisible(true);
        // SwingUtilities.invokeLater(new Runnable() {
        // public void run() {
        applyComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
//here
        scpButtons.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        // }
        // });
    }

    private JPanel initPnlButton() {
        JPanel pnlButton = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, 10,
                1, new Insets(0, 0, 0, 0), 0, 0);

        int ind = 0;
        int row = 3;
        int column = 4;
        for (int i = 0; i < row; i++) {
            for (int j = 1; j < column; j++) {
                gbc.gridx = j;
                gbc.gridy = i;
                pnlButton.add(arrayButton[ind++], gbc);
            }
        }
        gbc.weightx = 0;
        gbc.gridheight = 3;
        gbc.gridx = 0;
        gbc.gridy = 0;
        pnlButton.add(btnRight, gbc);
        gbc.gridx = 4;
        gbc.gridy = 0;
        pnlButton.add(btnLeft, gbc);
        pnlButton.setPreferredSize(new Dimension(1000, 700));
        return pnlButton;
    }

    public static void main(String[] args) {
        new MyFrame();
    }

}

于 2012-08-27T02:11:13.433 に答える