Haruskah saya menghindari penggunaan metode Size set (Preferred | Maximum | Minimum) di Java Swing?

481

Beberapa kali saya dikritik karena menyarankan penggunaan metode berikut:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

pada Swingkomponen. Saya tidak melihat alternatif untuk penggunaannya ketika saya ingin menentukan proporsi antara komponen yang ditampilkan. Saya telah diberitahu ini:

Dengan tata letak, jawabannya selalu sama: gunakan LayoutManager yang cocok

Saya telah mencari di web sedikit, tetapi saya belum menemukan analisis yang komprehensif dari subjek. Jadi saya punya pertanyaan berikut:

  1. Haruskah saya sepenuhnya menghindari penggunaan metode-metode itu?
  2. Metode telah ditetapkan karena suatu alasan. Jadi kapan saya harus menggunakannya? Dalam konteks apa? Untuk tujuan apa?
  3. Apa sebenarnya konsekuensi negatif dari penggunaan metode tersebut? (Saya hanya bisa berpikir menambahkan portabilitas antara sistem dengan resolusi layar yang berbeda).
  4. Saya tidak berpikir LayoutManager dapat dengan tepat memenuhi semua kebutuhan tata letak yang diinginkan. Apakah saya benar-benar perlu menerapkan LayoutManager baru untuk setiap variasi kecil pada layout saya?
  5. Jika jawaban ke 4 adalah "ya", tidakkah ini akan menyebabkan proliferasi kelas LayoutManager yang akan menjadi sulit dipertahankan?
  6. Dalam situasi di mana saya perlu menentukan proporsi antara anak-anak dari Komponen (misalnya, child1 harus menggunakan 10% ruang, child2 40%, child3 50%), apakah mungkin untuk mencapai itu tanpa menerapkan LayoutManager kustom?
Heisenbug
sumber

Jawaban:

236
  1. Haruskah saya sepenuhnya menghindari penggunaan metode-metode itu?

    Ya untuk kode aplikasi.

  2. Metode telah ditetapkan karena suatu alasan. Jadi kapan saya harus menggunakannya? Dalam konteks apa? Untuk tujuan apa?

    Saya tidak tahu, secara pribadi saya menganggapnya sebagai kecelakaan desain API. Sedikit dipaksakan oleh komponen majemuk yang memiliki gagasan khusus tentang ukuran anak. "Sedikit", karena mereka seharusnya mengimplementasikan kebutuhan mereka dengan Manajer Layout kustom.

  3. Apa sebenarnya konsekuensi negatif dari penggunaan metode tersebut? (Saya hanya bisa berpikir menambahkan portabilitas antara sistem dengan resolusi layar yang berbeda.)

    Beberapa (tidak lengkap, dan sayangnya tautannya terputus karena migrasi SwingLabs ke java.net) alasan teknisnya seperti disebutkan dalam Peraturan (hehe) atau di tautan @bendicott yang ditemukan dalam komentarnya untuk jawaban saya . Secara sosial, berpose banyak pekerjaan ke rekan Anda yang malang yang harus mempertahankan kode dan harus melacak tata letak yang rusak.

  4. Saya tidak berpikir LayoutManager dapat dengan tepat memenuhi semua kebutuhan tata letak yang diinginkan. Apakah saya benar-benar perlu menerapkan LayoutManager baru untuk setiap variasi kecil pada layout saya?

    Ya, ada LayoutManagers yang cukup kuat untuk memenuhi perkiraan yang sangat baik untuk "semua kebutuhan tata letak". Tiga besar adalah JGoodies FormLayout, MigLayout, DesignGridLayout. Jadi tidak, dalam praktiknya, Anda jarang menulis LayoutManagers kecuali untuk lingkungan yang sangat khusus.

  5. Jika jawaban ke 4 adalah "ya", tidakkah ini akan menyebabkan proliferasi kelas LayoutManager yang akan menjadi sulit dipertahankan?

    (Jawaban ke 4 adalah "tidak".)

  6. Dalam situasi di mana saya perlu mendefinisikan proporsi antara anak-anak dari Komponen (misalnya, anak 1 harus menggunakan ruang 10%, anak 2 40%, anak 3 50%), apakah mungkin untuk mencapai itu tanpa menerapkan LayoutManager kustom?

    Salah satu dari Tiga Besar dapat, bahkan tidak bisa GridBag (tidak pernah repot-repot untuk benar-benar menguasai, terlalu banyak kesulitan untuk terlalu sedikit daya).

kleopatra
sumber
4
Saya tidak sepenuhnya yakin saya setuju dengan saran ini setidaknya dalam dua situasi. 1) Kustom komponen yang diberikan 2) Menggunakan JEditorPanedengan HTML yang tidak dengan sendirinya menyarankan lebar. OTOH Saya tidak yakin apakah saya melewatkan sesuatu. Saya akan dengan hati-hati meninjau balasan di utas, tetapi tertarik jika Anda memiliki komentar, terutama pada kasus terakhir.
Andrew Thompson
2
@Andrew Thompson 1) custom comps: itu adalah comp itu sendiri yang bertanggung jawab untuk mengembalikan petunjuk tata letak yang berguna, jika mereka tidak impl adalah buggy 2) bahkan core kompi buggy ;-) 3) Saya tidak keberatan dengan ruang putih (meskipun bukan kali ini disengaja, terima kasih :-)
kleopatra
8
Saya tidak percaya jawaban yang diterima adalah yang mengatakan untuk menghindari menggunakan metode setXXX (). Terkadang Anda hanya membutuhkan mereka untuk memberikan petunjuk kepada manajer tata letak. Jika Anda meletakkan panel maka Anda harus benar-benar merasa bebas untuk menggunakan metode ini saat diperlukan. Mengatakan bahwa saya pikir jika Anda menggunakan manajer tata letak yang sesuai, Anda akan menemukan diri Anda tidak terlalu membutuhkan metode ini, tetapi kadang-kadang Anda hanya membutuhkannya. Coba letakkan JComboBox atau JSpinner di X_AXIS BoxLayout dan tidak menggunakannya, yakin Anda akan menemukan Anda perlu setMaximumSize () di sana.
Michael
5
@Michael tidak, saya sama sekali tidak membutuhkannya - jawabannya adalah selalu menggunakan LayoutManager yang layak dan melakukan tweaker apa pun pada level manajer (vs level komponen)
kleopatra
5
Anda terus mengatakan "gunakan LayoutManager yang layak dan katakan ukuran apa yang Anda inginkan" di seluruh stackoverflow, tetapi Anda tidak pernah memberikan contoh spesifik dari LayoutManager yang "layak". Dan tidak ada manajer standar yang mengizinkan pengontrolan ukuran secara langsung.
Ti Strga
100

Beberapa heuristik:

  • Jangan gunakan set[Preferred|Maximum|Minimum]Size()ketika Anda benar-benar bermaksud menimpa get[Preferred|Maximum|Minimum]Size(), seperti yang mungkin dilakukan dalam membuat komponen Anda sendiri, yang ditunjukkan di sini .

  • Jangan gunakan set[Preferred|Maximum|Minimum]Size()saat Anda bisa mengandalkan komponen yang diganti dengan hati-hati getPreferred|Maximum|Minimum]Size, seperti yang ditunjukkan di sini dan di bawah.

  • Gunakan set[Preferred|Maximum|Minimum]Size()untuk mendapatkan post- validate()geometri, seperti yang ditunjukkan di bawah dan di sini .

  • Jika komponen tidak memiliki ukuran yang disukai, misalnya JDesktopPane, Anda mungkin harus mengukur wadahnya, tetapi pilihan semacam itu sewenang-wenang. Sebuah komentar dapat membantu memperjelas maksudnya.

  • Pertimbangkan tata letak alternatif atau kustom ketika Anda menemukan bahwa Anda harus mengulang-ulang banyak komponen untuk mendapatkan ukuran turunan, seperti yang disebutkan dalam komentar ini .

masukkan deskripsi gambar di sini

import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

/**
 * @see /programming/7229226
 * @see /programming/7228843
 */
public class DesignTest {

    private List<JTextField> list = new ArrayList<JTextField>();
    private JPanel panel = new JPanel();
    private JScrollPane sp = new JScrollPane(panel);

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

            @Override
            public void run() {
                DesignTest id = new DesignTest();
                id.create("My Project");
            }
        });
    }

    private void addField(String name) {
        JTextField jtf = new JTextField(16);
        panel.add(new JLabel(name, JLabel.LEFT));
        panel.add(jtf);
        list.add(jtf);
    }

    private void create(String strProjectName) {
        panel.setLayout(new GridLayout(0, 1));
        addField("First Name:");
        addField("Last Name:");
        addField("Address:");
        addField("City:");
        addField("Zip Code:");
        addField("Phone:");
        addField("Email Id:");
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
            .addPropertyChangeListener("permanentFocusOwner",
            new FocusDrivenScroller(panel));
        // Show half the fields
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        sp.validate();
        Dimension d = sp.getPreferredSize();
        d.setSize(d.width, d.height / 2);
        sp.setPreferredSize(d);

        JInternalFrame internaFrame = new JInternalFrame();
        internaFrame.add(sp);
        internaFrame.pack();
        internaFrame.setVisible(true);

        JDesktopPane desktopPane = new JDesktopPane();
        desktopPane.add(internaFrame);

        JFrame frmtest = new JFrame();
        frmtest.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmtest.add(desktopPane);
        frmtest.pack();
        // User's preference should be read from java.util.prefs.Preferences
        frmtest.setSize(400, 300);
        frmtest.setLocationRelativeTo(null);
        frmtest.setVisible(true);
        list.get(0).requestFocusInWindow();
    }

    private static class FocusDrivenScroller implements PropertyChangeListener {

        private JComponent parent;

        public FocusDrivenScroller(JComponent parent) {
            this.parent = parent;
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            Component focused = (Component) evt.getNewValue();
            if (focused != null
                && SwingUtilities.isDescendingFrom(focused, parent)) {
                parent.scrollRectToVisible(focused.getBounds());
            }
        }
    }
}
trashgod
sumber
2
tidak setuju (seperti yang Anda duga :-) dengan alasan oleh "faktor eksternal": properti XXSize dimaksudkan untuk mengekspresikan kebutuhan internal saja . Tweak orang-orang dari luar adalah penyalahgunaan, alias peretasan. Jika Anda menginginkan bingkai (Internal- atau J-) dengan ukuran tertentu relatif lebih disukai ... ukuran bingkai, bukan konten
kleopatra
2
@kleopatra: hanya untuk menjadi sedikit ngotot: jika metode setXXSize tidak boleh digunakan dari luar, mengapa belum dinyatakan pribadi atau dilindungi? Bukankah ini kekurangan desain? Bukankah pengubah publik secara implisit memberi tahu pengguna yang dapat menggunakan metode itu?
Heisenbug
2
Saya harus setuju dengan @kleopatra: setPreferredSize()selalu mengganti perhitungan komponen dengan pilihan sewenang-wenang.
trashgod
1
@trashgod +100 untuk Anda, saya pikir tidak ada masalah dengan mengganti metode ini, bahkan memanggil mereka (tapi tentu saja ini berarti Anda memiliki komponen khusus sehingga menimpa akan lebih baik)
David Kroukamp
5
@DavidKroukamp: Terima kasih. Saya tunduk pada pengalaman kleopatra yang lebih besar, tetapi saya melihat nilai dalam memeriksa pandangan sebaliknya secara kritis.
trashgod
47

Haruskah saya sepenuhnya menghindari penggunaan metode-metode itu?

Tidak, tidak ada bukti formal untuk menyarankan memanggil atau mengganti metode ini tidak diperbolehkan. Bahkan, Oracle mengatakan metode ini digunakan untuk memberikan petunjuk ukuran: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .

Mereka juga dapat diganti (yang merupakan praktik terbaik untuk Swing) ketika memperluas komponen Swing (daripada memanggil metode pada instance komponen kustom)

Yang paling penting tidak peduli bagaimana Anda menentukan ukuran komponen Anda, pastikan bahwa wadah komponen Anda menggunakan manajer tata letak yang menghormati ukuran komponen yang diminta.

Metode telah ditetapkan karena suatu alasan. Jadi kapan saya harus menggunakannya? Dalam konteks apa? Untuk tujuan apa?

Saat Anda perlu memberikan petunjuk ukuran khusus kepada pengelola Tata Letak wadah sehingga komponen akan ditata dengan baik

Apa sebenarnya konsekuensi negatif dari penggunaan metode tersebut? (Saya hanya bisa berpikir untuk menambah portabilitas antara sistem dengan resolusi layar yang berbeda).

  • Banyak manajer tata letak tidak memperhatikan ukuran maksimum komponen yang diminta. Namun, BoxLayoutdan SpringLayoutlakukan. Selain itu, GroupLayoutmemberikan kemampuan untuk mengatur ukuran minimum, disukai atau maksimum secara eksplisit, tanpa menyentuh komponen.

  • Pastikan Anda benar-benar perlu mengatur ukuran persis komponen. Setiap komponen Swing memiliki ukuran pilihan yang berbeda, tergantung pada font yang digunakan dan tampilan serta rasa. Dengan demikian memiliki ukuran yang diatur dapat menghasilkan tampilan yang bervariasi dari UI pada Sistem yang berbeda

  • kadang-kadang masalah dapat ditemui GridBagLayoutdan bidang teks, di mana jika ukuran wadah lebih kecil dari ukuran yang disukai, ukuran minimum digunakan, yang dapat menyebabkan bidang teks menyusut cukup banyak.

  • JFrametidak memaksakan overriden getMinimumSize()hanya memanggil setMinimumSize(..)pekerjaannya

Saya tidak berpikir LayoutManager dapat dengan tepat memenuhi semua kebutuhan tata letak yang diinginkan. Apakah saya benar-benar perlu menerapkan LayoutManager baru untuk setiap variasi kecil pada layout saya?

Jika dengan menerapkan maksud Anda menggunakan maka ya. Tidak ada yang LayoutMangerbisa menangani semuanya, masing LayoutManager- masing memiliki pro dan kontra sehingga masing-masing dapat digunakan bersama untuk menghasilkan tata letak akhir.

Referensi:

David Kroukamp
sumber
3
memberikan petunjuk ukuran khusus yang merupakan kontradiksi: memberikan petunjuk ukuran (dalam px!) adalah tugas eksklusif komponen. Ini menghitung mereka berdasarkan perincian keadaan internal yang tidak diketahui oleh pihak lain kecuali dirinya sendiri (juga tidak dapat melacak). Dari perspektif klien, cara penyesuaian dapat berupa LayoutManager yang cocok dan / atau mengkhususkan api pada komponen yang memungkinkan mengonfigurasi persyaratan ukuran dalam hal properti semantik "ukuran yang relevan", jumlah baris / kolom dalam komponen teks
kleopatra
3
@kleopatra Saya masih ingin tahu mengapa Oracle kemudian memberi tahu kami cara menggunakan metode ini dan cara yang benar untuk menggunakannya. Kita mungkin memiliki preferensi kita sendiri tetapi kita tidak bisa mengatakan para perancang itu untuk tidak digunakan ketika tidak ada bukti untuk menyarankan ini. Tapi itu sebabnya saya memasang karunia melihat mungkin jika itu akan menarik orang lain yang dapat memberikan informasi dari sumber yang kredibel di mana oracle menyatakan untuk tidak menggunakan metode ini sama sekali (sehingga menjadikannya praktik yang buruk jika Anda melakukannya, misalnya setMinimumSize harus memanggil hal-hal seperti JSplitPane dll ini dapat dilihat dalam tutorial Oracle panel split
David Kroukamp
4
@ David: Saya datang untuk melihat setXxxSizemetode sebagai bendera merah yang saya mungkin berakhir di sini , bahkan ketika dokumen menyarankannya. Saya hampir selalu harus ditimpa getXxxSize, di mana seseorang memiliki akses ke geometri yang diperlukan; dan bahkan contoh singkat dapat didaur ulang lebih dari yang ingin saya pikirkan. +1 untuk menyebutkan variasi di antara pengelola tata letak dan mengutip tutorial.
trashgod
1
Doh, dalam komentar saya di atas, saya bermaksud mengutip jawabannya di sini .
trashgod
13
+1 "Tidak, tidak ada bukti formal untuk menyarankan menelepon atau mengganti metode ini tidak diizinkan." Spot on. Posting yang ditandai sebagai jawabannya adalah BS polos.
TT.
25

Ada banyak jawaban bagus di sini, tetapi saya ingin menambahkan sedikit tentang alasan mengapa Anda biasanya harus menghindari ini (pertanyaan baru saja muncul lagi dalam topik rangkap):

Dengan beberapa pengecualian, jika Anda menggunakan metode ini, Anda mungkin sedang menyesuaikan GUI agar terlihat bagus pada tampilan-dan-nuansa tertentu (dan dengan pengaturan khusus sistem Anda, mis. Font desktop pilihan Anda, dll.). Metode itu sendiri pada dasarnya tidak jahat, tetapi alasan khas untuk menggunakannya adalah . Segera setelah Anda mulai menyetel posisi dan ukuran piksel dalam tata letak, Anda berisiko melanggar GUI Anda (atau paling tidak, terlihat buruk), pada platform lain.

Sebagai contohnya, cobalah mengubah tampilan dan nuansa aplikasi Anda. Bahkan hanya dengan opsi yang tersedia di platform Anda, Anda mungkin akan terkejut melihat betapa buruknya hasil yang dapat diberikan.

Jadi, atas nama menjaga GUI Anda fungsional dan terlihat bagus di semua platform (ingat, salah satu manfaat utama Java adalah cross-platformness), Anda harus mengandalkan manajer tata letak, dll., Untuk secara otomatis menyesuaikan ukuran komponen Anda sehingga ditampilkan dengan benar di luar lingkungan pengembangan spesifik Anda.

Semua yang dikatakan, Anda tentu bisa membayangkan situasi di mana metode ini dibenarkan. Sekali lagi, mereka secara inheren tidak jahat, tetapi penggunaannya biasanya merupakan bendera merah besar yang menunjukkan potensi masalah GUI. Pastikan Anda sadar akan potensi komplikasi yang tinggi jika / ketika Anda menggunakannya, dan selalu coba dan pikirkan jika ada solusi lain yang terlihat dan terasa independen untuk masalah Anda - lebih sering Anda akan menemukan bahwa ini metode tidak perlu.

Omong-omong, jika Anda merasa frustrasi dengan manajer tata letak standar, ada banyak yang bagus, sumber pihak ketiga sumber terbuka, misalnya JGoodiesFormLayout , atau MigLayout. Beberapa pembangun GUI bahkan memiliki dukungan bawaan untuk pengelola tata letak pihak ketiga - editor GUI WindowBuilder Eclipse, misalnya, dikirimkan dengan dukungan untuk FormLayoutdan MigLayout.

Jason C
sumber
2
Memberi +1 jawaban penuh perhatian - hanya tidak setuju dengan mereka tidak secara inheren jahat hanya karena :-) Biasanya, klien luar tidak memiliki peluang apa pun untuk menebak - dan hanya asumsi yang sedekat yang bisa didapat oleh orang luar - petunjuk tata letak setengah jalan yang benar: hanya komponen itu sendiri memiliki semua info setiap saat untuk mengembalikan sesuatu yang bermanfaat. Dan karena saat itu orang luar mengganggu tanggung jawab mereka untuk menjaga agar petunjuk itu tetap mutakhir dan tidak bisa dilakukan.
kleopatra
1
Nah, Anda tahu, saya memiliki pandangan yang lebih "senjata tidak membunuh orang, orang membunuh orang" tentang hal-hal semacam ini. :) Jika seseorang menggunakan metode ini, mereka perlu mengetahui hal-hal seperti poin bagus yang Anda ajukan tentang penggunaan petunjuk tata letak yang tidak dapat diprediksi (itulah sebabnya situasi di mana metode ini tepat jarang terjadi).
Jason C
Saya pikir pengaturan ukuran yang disukai bukan bendera merah besar sama sekali. Bukan pengaturan itu adalah bendera merah besar sebagai gantinya. Biarkan saya uraikan. Manajer tata letak - tidak peduli seberapa pintar itu - tidak memiliki ide tentang fungsi logis dari widget gui. Misalnya, manajer tata letak tidak dapat membedakan antara JTextField untuk memasukkan kode ZIP, dan JTextField untuk memasukkan nama. Demikian pula itu tidak dapat membedakan antara tombol alat di sebelah JTextField atau tombol OK besar di bagian bawah formulir. Oleh karena itu baik set widget yang lebih baik, atau beberapa petunjuk ukuran diperlukan, bukan?
Wah Bee
@ GeeBee Tidak, itu contoh utama dari bendera merah, sebenarnya. Apa yang harus Anda lakukan adalah menggunakan JTextField.setColumnsuntuk mengatur jumlah kolom, yang menyesuaikan ukuran yang diinginkan sesuai. Jika Anda melakukannya, setPreferredSizemaka Anda sedang mengkodekan ukuran, yang akan memecah tata letak Anda tergantung pada ukuran font platform. Berikut adalah beberapa bidang teks dalam tata letak tas kisi dengan setColumnsdisebut tepat . Untuk tombol Anda, gunakan tata letak / bobot grid yang tepat untuk mengontrol ukuran.
Jason C
@ GeeBee Dan sekarang, dengan itu dilakukan dengan benar, perhatikan bagaimana lebar bidang teks berkurang ketika saya mengurangi ukuran font: i.snag.gy/ZULulh.jpg . Bahkan mengubah ukuran font dengan cepat sekarang bekerja secara otomatis, daripada Anda, katakanlah, harus menghitung ulang semua lebar bidang teks dan secara eksplisit memanggil setPreferredSize lagi untuk masing-masing, yang harus Anda lakukan adalah membatalkan tata letak dan ukurannya akan menyesuaikan.
Jason C
20

Jika Anda mengalami masalah dengan tata letak di Java Swing, maka saya bisa sangat merekomendasikan JGoodies yang FormLayoutdisediakan secara bebas sebagai bagian dari perpustakaan freeware Formulir oleh Karsten Lentzsch di sini .

Manajer tata letak yang sangat populer ini sangat fleksibel, memungkinkan untuk dikembangkan UI Java yang sangat halus.

Anda akan menemukan dokumentasi Karsten di sini , dan beberapa dokumentasi yang agak bagus dari gerhana di sini .

Tom
sumber
16

Metode-metode ini kurang dipahami oleh kebanyakan orang. Anda harus benar-benar tidak mengabaikan metode ini. Terserah manajer tata letak jika mereka menghormati metode ini. Halaman ini memiliki tabel yang menunjukkan manajer tata letak mana yang menghargai metode mana yang:

http://thebadprogrammer.com/swing-layout-manager-sizing/

Saya telah menulis kode Swing selama 8+ tahun dan manajer tata letak yang termasuk dalam JDK selalu memenuhi kebutuhan saya. Saya tidak pernah membutuhkan manajer tata letak pihak ke-3 untuk mencapai tata letak saya.

Saya akan mengatakan bahwa Anda tidak harus mencoba memberikan petunjuk tata letak manajer dengan metode ini sampai Anda yakin Anda membutuhkannya. Lakukan tata letak Anda tanpa memberikan petunjuk ukuran (mis. Biarkan pengelola tata letak melakukan tugasnya) dan kemudian Anda dapat membuat koreksi kecil jika perlu.

Michael
sumber
1
entah ada sedikit kesalahpahaman (di pihak Anda) atau kesalahpahaman (di pihak saya), pilihlah :-) Anda terus mengulangi (di sini, di blog Anda, di jawaban Anda yang terkait dengan BoxLayout) set XXSize sebagai yang penting - sebenarnya LayoutManager tertarik (atau tidak) dengan XXSize, yaitu ukuran petunjuk independen tentang bagaimana hal itu terjadi (perhitungan internal oleh komponen atau dipaksakan secara manual oleh kode aplikasi)
kleopatra
1
Saya tidak yakin saya mengerti apa yang Anda dapatkan di sini. Saya sebutkan di atas bahwa metode XXSize () hanyalah petunjuk. Saya benar-benar melihat tidak ada yang salah dengan memberikan sedikit layout manager, jika diperlukan. Dalam kode ayunan saya, Anda akan menemukan metode setXXSize () sesekali. Tidak banyak, tetapi kadang-kadang saya merasa dibutuhkan. JComboBox dan JSpinner sering membutuhkan petunjuk. Terutama JComboBox yang dihuni setelah direalisasikan. Anda tampaknya menentang setiap dan semua penggunaan metode ini dan saya tidak tahu mengapa. (mungkin saya yang ketinggalan perahu ini saya kira).
Michael
5
bukan metode adalah petunjuknya, propertinya adalah: komponen harus melaporkan sesuatu yang masuk akal untuk semua petunjuk, beberapa (seperti fi JComboBox) tidak - dalam mengembalikan maxInteger atau lebih. Itu bug dan harus diperbaiki oleh kombo. Mengenai kebiasaan Anda: pastikan untuk berada jauh ketika kolega pengelola harus membersihkannya :) Petunjuk yang sulit dikodekan cenderung merusak tata letak dengan perubahan sekecil apa pun dan sulit dideteksi sebagai alasan tata letak yang rusak.
kleopatra
15

Dalam situasi di mana saya perlu menentukan proporsi antara anak-anak dari Komponen (anak 1 harus menggunakan 10% ruang, child2 40%, child3 50%), apakah mungkin untuk mencapai itu tanpa menerapkan manajer tata letak khusus?

Mungkin GridBagLayoutakan memuaskan kebutuhan Anda. Selain itu, ada banyak manajer tata letak di web, dan saya yakin ada satu yang sesuai dengan kebutuhan Anda.

Thomas
sumber
Terima kasih atas jawabannya. Saya harus berasumsi bahwa yang Anda maksudkan juga: "jangan gunakan setPreferredSize sama sekali", kan?
Heisenbug
1
GridBagLayout menggunakan batasan, di mana Anda dapat menentukan "bobot" baik dalam X dan Y untuk komponen tertentu, sehingga LayoutManager dapat memutuskan apa yang harus dilakukan dengan ruang ekstra pada ukuran. TETAPI Anda masih perlu / dapat menggunakan setPreferredSize untuk menentukan ukuran pilihan masing-masing komponen, perhatikan bahwa "preferen" tidak berarti itu akan selalu dihargai. Untuk kasus khusus, Anda mungkin juga memerlukan setMinimumSize dan setMaximumSize. Mereka tidak jahat , jangan membeli itu. docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
マ ル ち ゃ ん ん だ よ
5

Saya melihatnya berbeda dari jawaban yang diterima.

1) Haruskah saya sepenuhnya menghindari penggunaan metode-metode itu?

Jangan pernah menghindar! Mereka ada di sana untuk mengekspresikan batasan ukuran komponen Anda ke manajer tata letak. Anda dapat menghindari menggunakannya jika Anda tidak menggunakan pengelola tata letak apa pun dan mencoba mengelola tata letak visual sendiri.

Sayangnya, Swing tidak hadir dengan dimensi standar yang wajar. Namun, alih-alih mengatur dimensi komponen, lebih baik OOP untuk menurunkan komponen Anda sendiri dengan standar yang wajar. (Dalam hal ini Anda memanggil setXXX di kelas turunan Anda.) Atau, Anda dapat mengganti metode getXXX untuk efek yang sama.

2) Metode telah ditetapkan karena suatu alasan. Jadi kapan saya harus menggunakannya? Dalam konteks apa? Untuk tujuan apa?

Selalu. Saat Anda membuat komponen, atur ukuran min / prefer / max yang realistis sesuai dengan penggunaan komponen itu. Misalnya, jika Anda memiliki JTextField untuk memasukkan simbol negara seperti Inggris, ukuran pilihannya akan selebar dua karakter (dengan font saat ini, dll.) Tetapi mungkin tidak ada artinya membiarkannya tumbuh lebih besar. Bagaimanapun, simbol negara adalah dua karakter. Sebaliknya, jika Anda memiliki JTextField untuk memasukkan misalnya nama pelanggan, itu bisa memiliki ukuran yang disukai untuk seperti ukuran piksel untuk 20 karakter, tetapi dapat tumbuh menjadi lebih besar jika tata letak diubah ukurannya, jadi atur ukuran maksimum menjadi lebih banyak. Pada saat yang sama, memiliki lebar JTextField 0px tidak ada gunanya, jadi atur ukuran minimum yang realistis (saya akan mengatakan ukuran piksel 2 karakter).

3) Apa sebenarnya konsekuensi negatif dari penggunaan metode tersebut?

(Saya hanya bisa berpikir menambahkan portabilitas antara sistem dengan resolusi layar yang berbeda).

Tidak ada konsekuensi negatif. Ini adalah petunjuk untuk pengelola tata letak.

4) Saya tidak berpikir LayoutManager dapat dengan tepat memenuhi semua kebutuhan tata letak yang diinginkan.

Apakah saya benar-benar perlu menerapkan LayoutManager baru untuk setiap variasi kecil pada layout saya?

Tidak, tentu saja tidak. Pendekatan yang biasa dilakukan adalah dengan memanipulasi tata letak dasar yang berbeda seperti tata letak horizontal dan vertikal.

Misalnya, tata letak di bawah ini:

<pre>
+--------------+--------+
| ###JTABLE### | [Add]  | 
| ...data...   |[Remove]|
| ...data...   |        |
| ...data...   |        |
+--------------+--------+
</pre>

memiliki dua bagian. Bagian kiri dan kanan adalah tata letak horizontal. Bagian kanan adalah JPanel yang ditambahkan ke tata letak horizontal, dan JPanel ini memiliki tata letak vertikal yang menjabarkan tombol-tombol secara vertikal.

Tentu saja, ini bisa menjadi rumit dengan tata letak kehidupan nyata. Oleh karena itu manajer tata letak berbasis kisi seperti MigLayout jauh lebih baik jika Anda ingin mengembangkan sesuatu yang serius.

5) Jika jawaban ke 4 adalah "ya", tidakkah ini akan menyebabkan proliferasi kelas LayoutManager yang akan menjadi sulit dipertahankan?

Tidak, Anda pasti tidak akan mengembangkan manajer tata letak, kecuali jika Anda memerlukan sesuatu yang sangat istimewa.

6) Dalam situasi di mana saya perlu mendefinisikan proporsi ...

antara anak-anak dari Komponen (misalnya, child1 harus menggunakan ruang 10%, child2 40%, child3 50%), apakah mungkin untuk mencapai itu tanpa menerapkan LayoutManager kustom?

Pada dasarnya, setelah ukuran yang diinginkan diatur dengan benar, Anda mungkin tidak ingin melakukan apa pun dalam persentase. Sederhananya, karena persentase tidak ada gunanya (misalnya tidak ada gunanya memiliki JTextField 10% dari ukuran jendela - karena seseorang dapat mengecilkan jendela sehingga JTextField menjadi lebar 0px, atau dapat memperluas jendela sehingga JTextField berada di dua tampilan pada sebuah layar pengaturan multi-display).

Tapi, mungkin kali Anda dapat menggunakan persentase untuk mengontrol ukuran blok bangunan yang lebih besar dari gui Anda (panel, misalnya).

Anda dapat menggunakan JSplitPane di mana Anda dapat mengatur sebelumnya rasio kedua sisi. Atau, Anda dapat menggunakan MigLayout yang memungkinkan Anda mengatur batasan seperti itu dalam persentase, piksel, dan unit lainnya.

Wah Bee
sumber
Betulkah? Ini jam 0? Ini lebih baik daripada jawaban yang diterima yang memiliki 100+ lebih. Itu pada dasarnya mengatakan "Kamu tidak akan menggunakan setPreferredSize!" yang MENGERIKAN. Dalam pekerjaan saya, ada BANYAK persyaratan ukuran tertentu, seperti "Tombol pada layar sentuh harus [X] oleh [Y] dengan [M] x [N] jarak antara" persyaratan keselamatan. btnBar.setPreferredSize( dimTouchBtn );adalah cara terbaik untuk melakukan itu. Mudah, tidak perlu manajer tata letak khusus. Saya menggunakan sebagian besar GridBagLayoutdengan beberapa BorderLayoutdan BoxLayout, bersarang saat nyaman. Ini adalah kombinasi yang kuat dan mudah digunakan.
Loduwijk
Saya tergesa-gesa dalam komentar saya di atas. Ini adalah jawaban pertama yang saya lihat setelah jawaban yang diterima. Mengapa SO tidak lagi urutkan berdasarkan penghitungan suara? Saya pikir itu adalah salah satu alasan utama penghitungan suara pada awalnya. Saya tetap mendukung komentar asli; ini adalah salah satu jawaban yang lebih baik. Kecuali untuk poin # 6 - yang tidak terlalu bagus. Ada banyak (minoritas masih bisa sejumlah besar) alasan untuk mengubah ukuran, dan GridBagLayout mendukung dengan baik dalam kebanyakan kasus yang saya alami.
Loduwijk
Saya pikir mengubah ukuran vs tidak mengubah ukuran tidak akan dianggap sebagai keputusan agama. Ada kasus penggunaan ketika tidak ada yang ingin mengubah ukuran apa pun, misalnya jika Anda mengembangkan GUI untuk kios, dengan resolusi tetap yang telah ditetapkan sebelumnya. Jika Anda memiliki target yang berbeda, seperti tampilan HMI industri dan wadah "tombol", maka ya, Anda harus memiliki setidaknya 1 cm kali 1 cm untuk sebuah tombol di layar sentuh. Dalam hal ini, DPI layar menentukan bagaimana Anda mengubah ukuran. Input lain seperti bidang teks mungkin sama sekali tidak diubah ukurannya secara vertikal, dan terkadang (seperti kode pos) pengubahan ukuran horizontal juga tidak ada gunanya.
Wah Wah
0

Haruskah saya sepenuhnya menghindari penggunaan metode-metode itu? Saya tidak akan mengatakan "hindari" mereka. Saya akan mengatakan bahwa jika Anda berpikir Anda membutuhkannya, Anda mungkin melakukan sesuatu yang salah. Ukuran komponen ditentukan dalam konteks. Misalnya, ukuran komponen teks ditentukan oleh jumlah baris dan kolom yang Anda tentukan, dikombinasikan dengan font yang Anda pilih. Tombol dan ukuran label Anda akan menjadi ukuran grafik, jika Anda mengaturnya, atau ruang yang diperlukan untuk menampilkan teks yang Anda atur. Setiap komponen memiliki ukuran alami, dan manajer tata letak akan menggunakannya untuk meletakkan semuanya tanpa Anda perlu menentukan ukuran. Pengecualian utama adalah JScrollPane, yang memiliki ukuran independen dari apa pun yang dikandungnya. Bagi mereka, saya kadang-kadang akan menelepon setSize(), dan membiarkan ukuran itu menentukan ukuran jendela awal, dengan meneleponJFrame.pack(). Biasanya, saya akan membiarkan ukuran jendela menentukan ukuran JScrollPane. Pengguna akan menentukan ukuran jendela. Banyak manajer tata letak mengabaikan ukuran yang Anda tetapkan, jadi mereka sering tidak berbuat banyak.

Metode telah ditetapkan karena suatu alasan. Jadi kapan saya harus menggunakannya? Dalam konteks apa? Untuk tujuan apa? Saya percaya mereka ditambahkan untuk memberikan petunjuk kepada manajer tata letak. Mereka mungkin telah ditulis karena alasan historis, karena manajer tata letak adalah baru, dan orang-orang tidak sepenuhnya mempercayai mereka. Saya tahu beberapa pengembang yang menghindari manajer tata letak dan meletakkan semuanya secara manual, hanya karena mereka tidak mau repot-repot mempelajari paradigma baru. Itu ide yang buruk.

Apa sebenarnya konsekuensi negatif dari penggunaan metode tersebut? (Saya hanya bisa berpikir menambahkan portabilitas antara sistem dengan resolusi layar yang berbeda). Mereka tidak efektif, dan mereka menghasilkan tata letak yang buruk, dengan benda yang diperas atau ditarik ke ukuran non-alami. Dan tata letak akan rapuh. Perubahan ukuran jendela kadang-kadang akan merusak tata letak dan meletakkan segala sesuatu di tempat yang salah.

Saya tidak berpikir LayoutManager dapat dengan tepat memenuhi semua kebutuhan tata letak yang diinginkan. Apakah saya benar-benar perlu menerapkan LayoutManager baru untuk setiap variasi kecil pada layout saya? Anda seharusnya tidak "menerapkan" Manajer Layout baru. Anda harus instantiate yang sudah ada. Saya sering menggunakan beberapa manajer tata letak dalam satu jendela. Setiap JPanel akan memiliki manajer tata letak sendiri. Beberapa orang menolak keras pada tata letak bersarang, karena sulit dipertahankan. Ketika saya menggunakannya, saya memberikan masing-masing metode kreasi sendiri untuk membuatnya lebih mudah untuk melihat apa yang dilakukan masing-masing. Tapi saya tidak pernah "menerapkan" manajer tata letak. Saya hanya instantiate mereka.

Jika jawaban ke 4 adalah "ya", tidakkah ini akan menyebabkan proliferasi kelas LayoutManager yang akan menjadi sulit dipertahankan? Jika Anda menerapkan kelas manajer tata letak baru untuk sedikit variasi dalam tata letak, Anda salah menggunakannya. Jika Anda hanya menerapkan manajer tata letak baru, Anda mungkin melakukan sesuatu yang salah. Satu-satunya saat saya memperpanjang kelas LayoutManager, itu adalah menambahkan slider zoom ke JScrollPane.

Dalam situasi di mana saya perlu menentukan proporsi antara anak-anak dari Komponen (misalnya, child1 harus menggunakan 10% ruang, child2 40%, child3 50%), apakah mungkin untuk mencapai itu tanpa menerapkan LayoutManager kustom? JSplitPane memiliki cara untuk menentukan persentase yang harus didapatkan setiap komponen. Pembagi dapat dipindah secara default, tetapi Anda dapat mematikannya jika mau. Saya tidak banyak menggunakan fitur itu. Saya biasanya memiliki beberapa komponen yang mengambil ukuran yang ditetapkan, dan sisa ruang diambil oleh panel gulir. Ukuran panel gulir akan menyesuaikan dengan ukuran jendela. Jika Anda memiliki dua panel gulir berdampingan, Anda bisa meletakkannya di JSplitPane dan menentukan persentase ruang baru yang diberikan kepada masing-masing sebagai pengguna memperluas dan mengontrak windows.

MiguelMunoz
sumber