Bagaimana posisi terbaik GUI Swing?

126

Di utas lain saya menyatakan bahwa saya suka memusatkan GUI saya dengan melakukan sesuatu seperti ini:

JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new HexagonGrid());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);

Tetapi Andrew Thompson memiliki pendapat yang berbeda, sebagai gantinya menelepon

frame.pack();
frame.setLocationByPlatform(true);

dan ingin tahu pikiran ingin tahu mengapa?

Hovercraft Penuh Belut
sumber
Gui harus dimulai di tempat yang sama dengan yang terakhir kali berakhir.
NomadMaker

Jawaban:

167

Menurut saya, GUI di tengah layar terlihat begitu .. "splash-screen'ish". Saya terus menunggu mereka menghilang dan GUI yang sebenarnya muncul!

Sejak Java 1.5 kami telah memiliki akses Window.setLocationByPlatform(boolean). yang..

Setel apakah Window ini akan muncul di lokasi default untuk sistem windowing asli atau di lokasi saat ini (dikembalikan oleh getLocation) saat Window berikutnya terlihat. Perilaku ini menyerupai jendela asli yang ditampilkan tanpa secara terprogram mengatur lokasinya. Sebagian besar sistem jendela membuat jendela jika lokasinya tidak diatur secara eksplisit. Lokasi sebenarnya ditentukan setelah jendela ditampilkan di layar.

Lihat efek dari contoh ini yang menempatkan 3 GUI ke posisi default yang dipilih oleh OS - pada Windows 7, Linux dengan Gnome & Mac OS X.

Jendela susun pada Windows 7 masukkan deskripsi gambar di sini Jendela bertumpuk pada Mac OS X

(3 lot) 3 GUI ditumpuk dengan rapi. Ini mewakili 'jalan paling tidak mengejutkan' bagi pengguna akhir, karena itu adalah bagaimana OS dapat memposisikan 3 contoh editor teks biasa (atau apa pun, dalam hal ini). Terima kasih saya kepada trashgod untuk Linux & Mac. gambar-gambar.

Berikut adalah kode sederhana yang digunakan:

import javax.swing.*;

class WhereToPutTheGui {

    public static void initGui() {
        for (int ii=1; ii<4; ii++) {
            JFrame f = new JFrame("Frame " + ii);
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            String s =
                "os.name: " + System.getProperty("os.name") +
                "\nos.version: " + System.getProperty("os.version");
            f.add(new JTextArea(s,3,28));  // suggest a size
            f.pack();
            // Let the OS handle the positioning!
            f.setLocationByPlatform(true);
            f.setVisible(true);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(
                        UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {}
                initGui();
            }
        });
    }
}
Andrew Thompson
sumber
1
@AndrewThompson Mengapa variabel counter Anda iibukan hanya i? Apakah itu mematuhi beberapa konvensi atau itu preferensi pribadi (atau mungkin sesuatu yang sama sekali berbeda)?
MirroredFate
1
@MirroredFate Umm .. Saya pikir saya akan mengunci opsi 3 di sana, "sesuatu yang sama sekali berbeda". Itu hanya apa yang saya terbiasa ketika saya pertama kali diprogram di Basic (ya, lama sekali). Kemalasan merupakan alasan untuk terus digunakan, 'jika tidak rusak, jangan perbaiki'.
Andrew Thompson
1
@MirroredFate Apakah Anda kebetulan pangeran persia Fan? Saya sangat menyesal meletakkannya di sini. Saya tidak tahan
Anarach
11
@MirroredFate Inilah sebabnya saya menggunakan iibukan i. Ketika saya mengambil bagian dalam kompetisi pemrograman, saya sering harus mencari indeks loop ke, katakanlah, +1atau -1darinya untuk memperbaikinya dengan satu kesalahan. Dalam kasus tersebut, mencari iijauh lebih mudah daripada mencari i, terlepas dari editor yang saya gunakan. Demikian pula, saya menggunakan jjdan kkuntuk indeks loop bersarang. :)
musically_ut
5

Saya sepenuhnya setuju bahwa setLocationByPlatform(true)ini adalah cara terbaik untuk menentukan posisi JFrame baru tetapi pada pengaturan dual-monitor Anda bisa mendapatkan masalah. Dalam kasus saya, anak JFrame muncul di monitor 'yang lain'. Contoh: Saya punya GUI utama saya di Layar 2, saya memulai JFrame baru dengan setLocationByPlatform(true)dan itu terbuka di Layar 1. Jadi di sini adalah solusi yang lebih lengkap, saya pikir:

...
// Let the OS try to handle the positioning!
f.setLocationByPlatform(true);
if (!f.getBounds().intersects(MyApp.getMainFrame().getBounds())) {
    // non-cascading, but centered on the Main GUI
    f.setLocationRelativeTo(MyApp.getMainFrame()); 
}
f.setVisible(true);
Axel Podehl
sumber