5

これは私のコードです:

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class Test{


public static void main(String[] args){

    SwingUtilities.invokeLater(new Runnable(){

        @Override
        public void run() {

            JFrame.setDefaultLookAndFeelDecorated(true);

            JFrame frame = new JFrame();
            JPanel jp = new JPanel();

            jp.setMinimumSize(new Dimension(200, 200));
            jp.setPreferredSize(new Dimension(200, 200));

            //frame.getContentPane().setMinimumSize(new Dimension(200, 200));
            //frame.getContentPane().setPreferredSize(new Dimension(200, 200));

            frame.getContentPane().add(jp);

            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        }
    });
}
}

それはまさに私が望むように動作します。ユーザーはサイズを変更できJFrameますが、常に 200px x 200px を保持するのに十分な大きさになりますJPanel。しかし、私が削除すると:

JFrame.setDefaultLookAndFeelDecorated(true);

ユーザーはJFrame任意のサイズにサイズ変更できます。

デフォルトのルック アンド フィールの装飾がサイズ変更に影響するのはなぜですか? なしで動作させるにはどうすればよいsetDefaultLookAndFeelDecorated(true)ですか?フレームの最小サイズを手動で設定できることは知っています ( JFrame#setMinimumSize(new Dimension dim))。よりスマートなソリューションがない場合はそうします。

Windows 7でjdk 1.7を使用しています。

4

2 に答える 2

4

これは以前はバグでした。このページでは、次のような回避策について説明しています。

  • オーバーライドsetSize()して、新しいサイズが目的のサイズよりも小さいかどうかを確認します
  • 高さと幅paint(Graphics g)JFrameチェックし、フレームを新しい最小サイズに「再作成」します

ただし、バグ提案のために発行された元の例では への呼び出しが省略されているため、修正されたと主張する人がいsetMinimumSize(...)ます。JFrame は最小サイズを強制しないため、これが必要です。

その人のコードを示すスニペットは次のとおりです。

import java.awt.Dimension;
import javax.swing.*;

public class JavaApplication118 {

    private final Dimension m_dim = new Dimension(200, 150);

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

            @Override
            public void run() {
                new JavaApplication118().createAndShowUI();
            }
        });
    }

    private void createAndShowUI() {

        // JFrame.setDefaultLookAndFeelDecorated(true);

        final JFrame frame = new JFrame("Test") {

            @Override
            public Dimension getMinimumSize() {
                return m_dim;
            }

        };

        frame.setMinimumSize(m_dim);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initComponents(frame);

        // frame.setResizable(false);
        frame.pack();
        frame.setVisible(true);
    }

    private void initComponents(JFrame frame) {
        JPanel jp = new JPanel();

        jp.setMinimumSize(new Dimension(200, 200));
        jp.setPreferredSize(new Dimension(400, 400));//for testing

        frame.getContentPane().add(jp);
    }
}

編集

getMinimumSize()を呼び出した後、これは冗長に見えますが、スニペットは上書きされました。これがsetMinimumSize(..)スニペットを見つけた方法であるため、含めたままにしました(スニペットに含まれていた のオーバーライドさ れたgetPreferredSize()メソッドを削除しましたJFrame)。

于 2012-09-30T20:02:03.380 に答える
2

デフォルトのルック アンド フィールの装飾がサイズ変更に影響するのはなぜですか?

ドラッグ中のウィンドウのサイズ変更は、LAF の完全な制御下にあるためです。(fi) MetalRootPaneUI によってインストールされた mouseHandler は、LayoutManager によって返された最小値を下回るウィンドウのサイズを変更しません。フレームの最小サイズを設定しなくても、プログラムでサイズを小さくすることができます。

(残念ながら) ウィンドウの最小サイズを常に強制する唯一の方法は、手動で設定することです。残念ながら、それはその最小値の動的な変化を追跡し、必要に応じて更新することを意味するためです。

再生するスニペット (defaultDecoration とフレーム最小設定を un/comment します)

JFrame.setDefaultLookAndFeelDecorated(true);
JPanel panel = new JPanel() {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        Dimension m = getMinimumSize();
        // visualize the min
        g.drawRect(0, 0, m.width - 1, m.height -1);
    }

};
// BEWARE: for demonstration only, NEVER do in production code 
panel.setMinimumSize(new Dimension(400, 400));
panel.setPreferredSize(panel.getMinimumSize());
final JXFrame frame = new JXFrame("", true);
Action action = new AbstractAction("resize") {

    @Override
    public void actionPerformed(ActionEvent e) {
        frame.setSize(300, 300);
        LOG.info("succeeded? " + frame.getSize());
    }
};
panel.add(new JButton(action));
frame.add(panel);
frame.pack();
// set minimum is required to enforce the minimum
frame.setMinimumSize(frame.getMinimumSize());

アップデート

Window ソースを見ると、 isMinimumSizeSet をオーバーライドして無条件に true を返すことで、最小サイズを自動的に動的に尊重できることがわかります。

final JXFrame frame = new JXFrame("", true) {
    @Override
    public boolean isMinimumSizeSet() {
        return true;
    }
};
...
// no longer needed
// frame.setMinimumSize(frame.getMinimumSize());

ただし、副作用についてはテストされていません

于 2012-10-01T09:14:37.463 に答える