Java,当面板改变大小时改变框架的大小,家庭作业

Java,当面板改变大小时改变框架的大小,家庭作业,java,swing,Java,Swing,新手,请容忍我。我正在用Java编写一个Sokoban游戏,我启动了这个游戏,但我在使用pack()时遇到了问题。我想我的框架调整自己的大小取决于水平的大小,不同的水平有不同的大小。对于不同的尺寸,面板的绘制是正确的,因此如果我只是最大化框架,那么一切都很好,但是如何调用pack()来自动调整框架的大小呢?我试图将pack()放在我的Main方法中,但我怀疑解决方案不是那么简单(可能我构建程序的方式也没有帮助)。将pack()放在Main方法中会生成附加的图像,这是一个非常小的矩形,基本上只有m

新手,请容忍我。我正在用Java编写一个Sokoban游戏,我启动了这个游戏,但我在使用pack()时遇到了问题。我想我的框架调整自己的大小取决于水平的大小,不同的水平有不同的大小。对于不同的尺寸,面板的绘制是正确的,因此如果我只是最大化框架,那么一切都很好,但是如何调用pack()来自动调整框架的大小呢?我试图将pack()放在我的Main方法中,但我怀疑解决方案不是那么简单(可能我构建程序的方式也没有帮助)。将pack()放在Main方法中会生成附加的图像,这是一个非常小的矩形,基本上只有min、max和close按钮

我想实施的建议解决方案如下:

编写Sokoban构造函数,使其将周围的JFrame作为引用参数,然后对象在字段中记住该参数。然后,在更改Sokoban组件的首选大小后,调用此存储框架的方法包

我已经附上了我的构造函数和Main方法的代码

public class Sokoban extends JPanel {

LevelReader lReader = new LevelReader();      
private static final int SQUARESIZE = 50;  // square size in pixels
int currentLevel = 0;
int height = 0;
int width = 0;
int x = 0;
int y = 0;
Contents [][] mapArray;

public Sokoban(String fileName) {
    lReader.readLevels(fileName);
    initLevel(currentLevel);
    KeyListener listener = new MyKeyListener();
    addKeyListener(listener);
    this.setPreferredSize(new Dimension(500,500));
    setFocusable(true);

}

public static void main(String[] args) {
    JFrame frame = new JFrame("Sokoban");
    Sokoban sokoban = new Sokoban("m1.txt");
    frame.add(sokoban);
    frame.setVisible(true);
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
编写Sokoban构造函数,使其将周围的JFrame作为引用参数,然后对象在字段中记住该参数。然后,在更改Sokoban组件的首选大小后,调用此存储框架的方法包

答案已更新为@mKorbel建议的用法(感谢您的提示,代码现在看起来更干净了) 您的fried试图告诉您的是创建这样的东西(我删除了您在本例中不需要的代码)

在构造函数
publicsokoban(字符串文件名,JFrame-tframe)
中,您需要传递对包含Sokoban面板的框架的引用。您需要将该引用中的对象存储在类中的某个位置,比如类字段
private JFrame


现在,由于该引用,无论何时更改面板的大小,您都可以通过调用
frame.pack()
来使用它来更改包含该面板的框架的大小,并使其适应新的大小。

这可能不会解决您的问题,但使用
frame.setVisible(true)是一种很好的做法将所有内容添加到框架后,请尝试在
setDefaultCloseOperation
@Pshemo之后移动它,注意,谢谢!另外,您应该使用
jframe.getContentPane().add()
?与只添加相比,
add
@Patrick,谢谢,jframe.getContentPane().add()的优点是什么?没有什么好处,
add
只是在后台调用
getContentPane
,但它让其他人更清楚地看到,您实际上是在向contentpane添加控件,而不是根窗格。您可以在jframe的文档中阅读,谢谢,我无法完全按照您的建议实施解决方案,但我能够使用您的想法来解决我的问题。我无法使用setPreferredSize使其工作,但我使用setSize使其工作。我认为setPreferredSize比setSize更受欢迎?还有,为什么要使用布尔值调整大小?为什么不直接调用frame.pack而不先设置needResize,然后检查是否设置了needResize?@user1894469我不知道为什么,但有时当frame不需要调整大小,我调用
pack
时,它会阻止下一次调整大小。这就是为什么我使用flag来检查是否需要调整大小。
setPreferredSize
是否优于
setSize
?我不知道。我无法使用setSize+pack调整大小,因此我使用setPreferredSize。无论如何,我回答的主要目的是展示在Sokoban构造函数中传递对框架的引用的想法,其余的并没有那个么重要。
class Sokoban extends JPanel {

    private JFrame frame;

    private class MyAction extends AbstractAction {
        private Dimension dimension;

        public MyAction(Dimension dimension) {
            this.dimension = dimension;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            //we will pack only when dimensions will need to change
            if (!getPreferredSize().equals(dimension)) {
                setPreferredSize(dimension);
                frame.pack();
            }
        }
    }

    public Sokoban(String fileName, JFrame tframe) {
        this.frame = tframe;
        setFocusable(true);
        setPreferredSize(new Dimension(100, 100));
        setBackground(Color.red);
        add(new JLabel("press A, S, D"));

        getInputMap().put(KeyStroke.getKeyStroke('a'), "typed a");
        getInputMap().put(KeyStroke.getKeyStroke('s'), "typed s");
        getInputMap().put(KeyStroke.getKeyStroke('d'), "typed d");

        getActionMap().put("typed a", new MyAction(new Dimension(100, 100)));
        getActionMap().put("typed s", new MyAction(new Dimension(200, 100)));
        getActionMap().put("typed d", new MyAction(new Dimension(100, 200)));
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Sokoban");
        Sokoban sokoban = new Sokoban("m1.txt", frame);

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