неизменяемая граница окна и позиционирование

Если я создаю JFrames без изменения размера, а Windows Aero включена, setLocation кажется, что граница окна не учитывается правильно.

В следующем коде я ожидаю, что второй кадр будет расположен справа от первого кадра, вместо этого границы перекрываются. Если Aero отключен или если я удаляю вызовы setResizable, это делается, как и ожидалось.

import java.awt.Rectangle;
import javax.swing.JFrame;
public class FrameBorders {
public static void main(String[] args) {
    JFrame frame1 = new JFrame("frame 1");
    JFrame frame2 = new JFrame("frame 2");

    frame1.setResizable(false);
    frame2.setResizable(false);

    frame1.setVisible(true);        
    Rectangle bounds = frame1.getBounds();      
    frame2.setLocation(bounds.x+bounds.width, bounds.y);
    frame2.setVisible(true);

}
}

Я что-то не так делаю или это баг? Как я могу отобразить 2 диалоговых окна неизменяемого размера рядом без перекрывающихся границ?

Изменить: добавлены скриншоты (также изменен frame2 на JDialog вместо JFrame)

Aero включено: Aero включено

Aero выключено: Aero выключено

Aero включено, но с изменяемым размером: Aero включено, но с изменяемым размером


person msam    schedule 21.09.2012    source источник
comment
Почему вы хотите отображать 2 неизменяемых диалоговых окна рядом без перекрывающихся границ?   -  person Roman C    schedule 21.09.2012
comment
Я хочу отобразить 2 окна, которые изначально расположены рядом   -  person msam    schedule 21.09.2012
comment
Пожалуйста, не устанавливайте произвольные ограничения на неизменяемый размер контейнера. См. Использование нескольких JFrames, хорошая/плохая практика?   -  person trashgod    schedule 21.09.2012
comment
что происходит, когда вы устанавливаете JFrame#getRootPane().setBorder(someBorder);, потому что у Areo есть тени внизу и слева   -  person mKorbel    schedule 21.09.2012
comment
@mKorbel, устанавливающий границу, устанавливает внутреннюю границу, но не влияет на границу окна.   -  person msam    schedule 21.09.2012
comment
1) установка границы устанавливает внутреннюю границу ---› извините, может плохо, я забыл, что для Un_decorated JFrame, 2) тогда вам нужно вычислить Points как пиксели из теней, может быть по-разному для каждой из тем,   -  person mKorbel    schedule 21.09.2012
comment
@trashgod Они также могут быть JFrame и JDialog, как предложено в этом посте, или 2 JDialogs, проблема все еще существует. Какие проблемы с ограничениями настроек для неизменяемых контейнеров?   -  person msam    schedule 21.09.2012
comment
@mKorbel Не уверен, что понял, но могу ли я получить эту информацию (размер дополнительной рамки)?   -  person msam    schedule 21.09.2012
comment
извините, сейчас я использую WinXp, не смогу использовать Win7 позже, нужно подождать, но для лучшего понимания другим читателям выложите здесь два скриншота с включенным и выключенным Areo.   -  person mKorbel    schedule 21.09.2012


Ответы (2)


Какие проблемы с ограничениями настроек для неизменяемых контейнеров?

Предположим, вы настроили границы, чтобы они хорошо смотрелись на вашей платформе. Предположим, что на платформе пользователя есть шрифт с другим, скажем, более крупным, FontMetrics. Этот пример несколько надуман, но вы поняли идею. Если вы изменяете границы неизменяемого размера контейнера, убедитесь, что любой текст виден независимо от шрифта по умолчанию на хост-платформе.

изображение

import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * @see http://stackoverflow.com/a/12532237/230513
 */
public class Evil extends JPanel {

    private static final String s =
        "Tomorrow's winning lottery numbers: 42, ";
    private JLabel label = new JLabel(s + "3, 1, 4, 1, 5, 9", JLabel.LEFT);

    public Evil() {
        this.add(label);
    }

    private void display() {
        JFrame f = new JFrame("Evil");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this, BorderLayout.WEST);
        f.pack();
        int w = SwingUtilities.computeStringWidth(
            label.getFontMetrics(label.getFont()), s);
        int h = f.getHeight();
        f.setSize(w, h);
        f.setResizable(false);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

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

            @Override
            public void run() {
                new Evil().display();
            }
        });
    }
}
person trashgod    schedule 21.09.2012
comment
Это хороший момент в том, что касается изменения размера (и был бы хорошим ответом на вопрос, который я задал в комментариях, если бы он был взят сам по себе), однако моя первоначальная проблема связана с позиционированием. Предположим, что использование pack() / без текста / размера не будет меняться или даже пустые диалоги/фреймы, как в моем собственном надуманном примере. - person msam; 24.09.2012
comment
Попробуйте pack(), что приведет к тому, что размер этого Window будет соответствовать предпочтительному размеру и компоновке его подкомпонентов. Извините, я не использую aero; sscce, демонстрирующий описанную вами проблему, может оказаться полезным. - person trashgod; 24.09.2012
comment
pack() в этом случае не имеет значения, так как окна пусты (поэтому я не включил его в свой пример). Изменил код, чтобы он компилировался (добавлены только импорт и основной класс...). Если вы не используете Aero, у вас не будет проблем с этим кодом, так как эта проблема присутствует только с aero (см. скриншоты) - person msam; 24.09.2012

Похоже, что это не проблема с Java, а скорее проблема с аэро-приложением, как описано здесь.

Одно из решений, которое я вижу в Java, состоит в том, чтобы разрешить изменять размер окон, а затем обойти ошибку setMaximumSize.

person msam    schedule 24.09.2012
comment
Хорошая ссылка; платформа владеет оформлением кадра, так что результат не полностью возмутителен; aqua имеет свою долю подобных аномалий. - person trashgod; 24.09.2012