Почему метод JFrame setSize () неправильно устанавливает размер?

Итак, я программировал на java около семестра, и у меня была эта проблема несколько раз, и я наконец нашел время, чтобы спросить.

Если я сделаю JFrame, а затем установлю размер, например, setSize(400,800). Фрейм на самом деле не 800 pixels длинный. Насколько я могу судить, это на самом деле больше похоже на 770 (or maybe 769) pixels долго. Кроме того, если вы установите очень низкий размер по вертикали (ниже 30), фрейм даже не будет отображаться, только верхняя панель окна из ОС, и фрейм не станет больше, пока вы не перейдете к значению более 30 (так что setSize(400,0) выглядит так же, как setSize(400,20)). Почему это нетрудно исправить, но это странно, и мне любопытно, почему это так?

Если вам нужна дополнительная информация о чем-либо, просто спросите, и я вам ее предоставлю.


person convergedtarkus    schedule 06.07.2011    source источник
comment
Обычно вам не нужно устанавливать размер фрейма. Если да, то это признак неприятностей. Вместо этого укажите предпочтительный размер для компонентов в кадре (если возможно, используя аргументы конструктора, например, new JTextArea(40,10)), или в противном случае, установив предпочтительный размер для компонентов и добавив их в соответствующий макет / ограничения. После этого pack() фрейм станет минимального размера, необходимого для отображения графического интерфейса.   -  person Andrew Thompson    schedule 06.07.2011
comment
вы можете прочитать ответ stackoverflow.com/ questions / 6384702 /   -  person Suhail Gupta    schedule 06.07.2011
comment
@ Андрей: Что затрудняет установку размера кадра?   -  person Logan    schedule 06.07.2011
comment
@Logan: Если единственным компонентом кадра является область рендеринга 400x400, насколько большим должен быть кадр, чтобы его разместить? Пусть JRE разберется с pack(). Если у вас есть дополнительные вопросы, я предлагаю вам (поискать) задать свой вопрос. По теме можно упомянуть гораздо больше, чем можно втиснуть в комментарий.   -  person Andrew Thompson    schedule 06.07.2011


Ответы (6)


Вероятно, это потому, что размер рамки включает размер границы.

Фрейм - это окно верхнего уровня с заголовком и рамкой. Размер рамки включает любую область, отведенную для границы. Размеры области границы можно получить с помощью метода getInsets. Поскольку область границы включена в общий размер кадра, граница эффективно закрывает часть кадра, ограничивая область, доступную для рендеринга и / или отображения подкомпонентов, прямоугольником, который имеет расположение в верхнем левом углу (вставки. слева, вставки.топ) и имеет размер ширины - (вставки.лефт + вставки.права) по высоте - (вставки.топ + вставки.bottom).

Источник: http://download.oracle.com/javase/tutorial/uiswing/components/frame.html

person Kyle    schedule 06.07.2011

JFrame SetSize () содержит область + граница.

Я думаю, вам нужно установить размер ContentPane этого

jFrame.getContentPane().setSize(800,400);

Поэтому я бы посоветовал вам использовать JPanel, встроенный в JFrame, и использовать эту JPanel. Это минимизирует вашу проблему.

JFrame jf = new JFrame();
JPanel jp = new JPanel();
jp.setPreferredSize(new Dimension(400,800));// changed it to preferredSize, Thanks!
jf.getContentPane().add( jp );// adding to content pane will work here. Please read the comment bellow.
jf.pack();

Я читаю это из Javadoc

Класс JFrame немного несовместим с Frame. Как и все другие контейнеры верхнего уровня JFC / Swing, JFrame содержит JRootPane в качестве своего единственного дочернего элемента. Панель содержимого, предоставляемая корневой панелью, как правило, должна содержать все компоненты, не являющиеся меню, отображаемые JFrame. Это отличается от случая AWT Frame. Например, чтобы добавить дочерний элемент во фрейм AWT, вы должны написать:

frame.add(child);

Однако при использовании JFrame вам нужно вместо этого добавить дочерний элемент в панель содержимого JFrame:

frame.getContentPane().add(child);

person Talha Ahmed Khan    schedule 06.07.2011
comment
пожалуйста, измените jp.setSize( 400, 800 ); на jp.setPreferredSize(new Dimension(400, 800));, если вы добавите JPanel к JFrame, тогда jf.getContentPane().add( jp ) бесполезен, потому что вы называете то же JComponents - person mKorbel; 06.07.2011
comment
@mKorbel, я поменял на preferredSize, спасибо. Но что касается второго пункта, я не добавляю JPanel к JFrame, но я добавляю JPanel к дочернему элементу JFrame JRootPane. Пожалуйста, прочтите комментарий, который я добавил в конце. - person Talha Ahmed Khan; 06.07.2011
comment
Опять же, нет необходимости добавлять JComponent в ContentPane в Swing, если вы добавляете JFrame # add (JPanel) то же самое (с BorderLayout.CENTER), что и JFrame.getContentPane (). add (JPanel), в любом случае +1 - person mKorbel; 06.07.2011

Есть много веских причин для установки размера кадра. Один из них - запомнить последний размер, установленный пользователем, и восстановить эти настройки. У меня есть этот код, который, кажется, мне подходит:

package javatools.swing;
import java.util.prefs.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.JFrame;

public class FramePositionMemory {
    public static final String WIDTH_PREF = "-width";

    public static final String HEIGHT_PREF = "-height";

    public static final String XPOS_PREF = "-xpos";

    public static final String YPOS_PREF = "-ypos";
    String prefix;
    Window frame;
    Class<?> cls;

    public FramePositionMemory(String prefix, Window frame, Class<?> cls) {
        this.prefix = prefix;
        this.frame = frame;
        this.cls = cls;
    }

    public void loadPosition() {
        Preferences prefs = (Preferences)Preferences.userNodeForPackage(cls);
    //  Restore the most recent mainframe size and location
        int width = prefs.getInt(prefix + WIDTH_PREF, frame.getWidth());
        int height = prefs.getInt(prefix + HEIGHT_PREF, frame.getHeight());
        System.out.println("WID: " + width + " HEI: " + height);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int xpos = (screenSize.width - width) / 2;
        int ypos = (screenSize.height - height) / 2;
        xpos = prefs.getInt(prefix + XPOS_PREF, xpos);
        ypos = prefs.getInt(prefix + YPOS_PREF, ypos);
        frame.setPreferredSize(new Dimension(width, height));
        frame.setLocation(xpos, ypos);
        frame.pack();
    }

    public void storePosition() {
        Preferences prefs = (Preferences)Preferences.userNodeForPackage(cls);
        prefs.putInt(prefix + WIDTH_PREF, frame.getWidth());
        prefs.putInt(prefix + HEIGHT_PREF, frame.getHeight());
        Point loc = frame.getLocation();
        prefs.putInt(prefix + XPOS_PREF, (int)loc.getX());
        prefs.putInt(prefix + YPOS_PREF, (int)loc.getY());
        System.out.println("STORE: " + frame.getWidth() + " " + frame.getHeight() + " " + loc.getX() + " " + loc.getY());
    }
}
public class Main {
void main(String[] args) {
        JFrame frame = new Frame();
        // SET UP YOUR FRAME HERE.
        final FramePositionMemory fm = new FramePositionMemory("scannacs2", frame, Main.class);
        frame.setSize(400, 400); // default size in the absence of previous setting
        fm.loadPosition();

        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                fm.storePosition();
            }
        });
        frame.setVisible(true);
    }
}

}

person xpusostomos    schedule 29.05.2015

В OS X необходимо учитывать существующие декорации окон. Они добавляют к высоте 22 пикселя. Итак, в JFrame вам нужно сообщить программе следующее:

frame.setSize(width, height + 22);
person ben    schedule 23.05.2016

Я знаю, что этому вопросу около 6+ лет, но ответ @Kyle не работает.

Используя это

setSize(width - (getInsets().left + getInsets().right), height - (getInsets().top + getInsets().bottom));

Но это всегда работает в любом размере:

setSize(width + 14, height + 7);

Если вы не хотите, чтобы граница граничила, а нужна только белая область, вот:

setSize(width + 16, height + 39);

Также это работает только в Windows 10, для пользователей MacOS используйте ответ @Ben.

person Community    schedule 16.02.2018
comment
чтобы сделать рамку достаточно большой на любом дисплее, она должна быть: this.setSize (widthofjPanel + leftInset + rightInset, heightofjPanel + topInset + bottomInset); после того, как вы получите вставки с помощью int topInset = this.getInsets (). top; и т.д., если кадр будет слишком коротким из-за доступного размера экрана, и вы используете jScrollPane, добавьте ширину полосы прокрутки с помощью widthOfVerticalScrollbar = (int) jScrollPane1.getVerticalScrollBar (). getPreferredSize (). getWidth (); - person Phil Longenecker; 09.05.2018
comment
ознакомьтесь с руководством mu по созданию Java Gui в Netbeans по адресу: philofjava.webstarts.com - person Phil Longenecker; 10.07.2018

Верхняя граница кадра имеет размер 30. Вы можете написать код для печати координаты любой точки на кадре с помощью MouseInputAdapter. Вы обнаружите, что, когда курсор находится чуть ниже верхней границы кадра, координата y не равна нулю, его близко к 30. Следовательно, если вы зададите размер кадра 300 * 300, размер, доступный для размещения компонентов в кадре, будет всего 300 * 270. Поэтому, если вам нужен размер 300 * 300, укажите размер кадра 300 * 330 .

person Community    schedule 12.07.2018