JFrame слишком маленький и pack () не работает - PullRequest
0 голосов
/ 30 сентября 2018

По какой-то причине JFrame слишком мал при запуске, и использование pack();, похоже, не решает проблему.Есть идеи?

   public class Window {

    public Window(String title, Game game) {

        // Creates new JFrame
        JFrame frame = new JFrame(title);

        // Adds Game to window
        frame.add(game);
        frame.pack();   

        // Settings of Window
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }

}

Screenshot of the program.

Предполагается, что голубой фон - это граница 64 x 64 в нижней и правой сторонах.Рисованные прямоугольники правильные, что я проверил, изменив размер окна.Однако окно слишком маленькое и не соответствует холсту.

Игровой класс:

public class Game extends Canvas implements Runnable {

private Handler handler;

public Game() {

    // Create new window
    Window window = new Window("Horses Aren't Real", this);

    handler = new Handler();
    this.addKeyListener(new KeyInput(handler));

    handler.addObject(new Daanish(100, 100, ID.Player, handler));

}

public static void main (String args[]) {

    // Creates new game
    new Game();

}

public void draw() {

    // Creates a new BufferStrategy
    BufferStrategy bs = this.getBufferStrategy();

    if (bs == null) {

        // This allows the game to preload 3 frames in order to prevent choppy framrate
        this.createBufferStrategy(3);

        return;

    }

    // Create Graphics
    Graphics g = bs.getDrawGraphics();

    g.setColor(Color.cyan);
    g.fillRect(0, 0, 1024, 640);

    g.setColor(Color.black);
    g.fillRect(0, 0, 960, 576);

    handler.draw(g);

    // Remove frame from queue
    g.dispose();
    bs.show();

}

@Override
public Dimension getPreferredSize() {

    return new Dimension(1024, 640);

}

}

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

Итак, вы столкнулись с рядом проблем.Во-первых, размер окна также должен учитывать декорации рамок, это означает, что доступное пространство для содержимого - это размер окна, МИНУС - размер декораций рамок.

Установка размераокно не рекомендуется.

pack запрашивает содержимое фрейма для его предпочтительного размера и использует это, чтобы обернуть окно вокруг него.Таким образом, вместо window size - decorations = content size, у вас есть content size + decorations = window size

Из JavaDocs

Причины того, что это окно имеет размер, соответствующий желаемому размеру и макетамего подкомпонентов.Результирующая ширина и высота окна автоматически увеличиваются, если любое из измерений меньше минимального размера, указанного в предыдущем вызове метода setMinimumSize.

Так что вместо этого переопределите preferredSize изGame класс и возвращаемое количество места, которое вы хотите, может быть что-то вроде ...

public class Game extends JPanel {
    //...
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(800, 600);
    }
    //...
}

Ваша следующая проблема, Window расширяется от JFrame, но в конструкторе вывы создаете ДРУГОЙ Frame ... так, кто на самом деле что делает?

Устраните путаницу.Избегайте расширения из контейнеров верхнего уровня, таких как JFrame, вы не добавляете в него никаких новых функций

public class Window {

    public Window(String title, Game game) {

        // Creates new JFrame
        JFrame frame = new JFrame(title);

        // Adds Game to window
        frame.add(game);
        frame.pack();

        // Settings of Window
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }

}

Обновлено ...

Итак, я взял ваш "обновленный" код,изменил его, чтобы он работал, работал и не было никаких проблем ...

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                Game game = new Game();
                Window window = new Window("Help", game);

                game.start();
            }
        });
    }

    public class Window {

        public Window(String title, Game game) {

            // Creates new JFrame
            JFrame frame = new JFrame(title);

            // Adds Game to window
            frame.add(game);
            frame.setResizable(false);
            frame.pack();

            // Settings of Window
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

        }

    }

    public class Game extends Canvas { //implements Runnable {

//      private Handler handler;

        public Game() {
//
//          handler = new Handler();
//          this.addKeyListener(new KeyInput(handler));
//
//          handler.addObject(new Daanish(100, 100, ID.Player, handler));

        }

        public void start() {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        draw();
                        try {
                            Thread.sleep(40);
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            });
            thread.start();
        }

        public void draw() {

            // Creates a new BufferStrategy
            BufferStrategy bs = this.getBufferStrategy();

            if (bs == null) {
                // This allows the game to preload 3 frames in order to prevent choppy framrate
                this.createBufferStrategy(3);
                return;
            }

            // Create Graphics
            Graphics g = bs.getDrawGraphics();

            g.setColor(Color.cyan);
            g.fillRect(0, 0, 1024, 640);

            g.setColor(Color.black);
            g.fillRect(0, 0, 960, 576);

//          handler.draw(g);

            // Remove frame from queue
            g.dispose();
            bs.show();

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(1024, 640);
        }

    }

}

Однако я работаю на MacOS.Существует небольшая известная проблема с setResizable, с которой я столкнулся в Windows, где декорации окна изменяют размер при вызове setResizable.

«Основное» решение - это вызвать setResziable ПЕРЕД вызовомpack, так что декорации рамок изменяются до того, как API принимает решения о том, как обновить размер окна.

Я думал, что это исправлено в более поздних (8+) версиях Java, нотак как я не запускаю Windows, я не могу проверить

См. Мой JFrame всегда становится на несколько пикселей больше. для получения дополнительной информации.

0 голосов
/ 30 сентября 2018
public class Window extends JFrame {

public Window(final int width, final int height, String title, Game game) {
    super(title);
    // Set dimensions
    Dimension d = new Dimension(width, height);
    game.setPreferredSize(d);

    // Adds Game to window
    add(game);
    // Settings of Window
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    pack();
    setVisible(true);

}

}

При использовании пакета размер кадра обычно изменяется до размера контента

...