Java Swing'de set (Tercih Edilen | Maksimum | Minimum) Boyut yöntemlerini kullanmaktan kaçınmalı mıyım?


481

Birkaç kez aşağıdaki yöntemlerin kullanılmasını önerdiğim için eleştirildim:

  1. setPreferredSize
  2. setMinimumSize
  3. setMaximumSize

üzerinde Swingbileşenler. Görüntülenen bileşenler arasındaki oranları tanımlamak istediğimde kullanımlarına alternatif göremiyorum. Bana söylendi:

Düzenlerle cevap her zaman aynıdır: uygun bir LayoutManager kullanın

Web'i biraz aradım, ancak konuyla ilgili kapsamlı bir analiz bulamadım. Bu yüzden aşağıdaki sorularım var:

  1. Bu yöntemlerin kullanımından tamamen kaçınmalı mıyım?
  2. Yöntemler bir nedenle tanımlanmıştır. Peki onları ne zaman kullanmalıyım? Hangi bağlamda? Hangi amaçlar için?
  3. Bu yöntemleri kullanmanın olumsuz sonuçları tam olarak nedir? (Yalnızca farklı ekran çözünürlüğüne sahip sistemler arasında taşınabilirlik eklemeyi düşünebilirim).
  4. Herhangi bir LayoutManager'ın istenen tüm yerleşim ihtiyaçlarını tam olarak karşılayabileceğini düşünmüyorum. Düzenimdeki her küçük değişiklik için gerçekten yeni bir LayoutManager uygulamam gerekiyor mu?
  5. 4'ün yanıtı "evet" ise, bu, bakımı zorlaşan LayoutManager sınıflarının çoğalmasına neden olmaz mı?
  6. Bir Bileşenin çocukları arasında oranlar tanımlamam gereken bir durumda (örneğin, child1% 10 alan, child2% 40, child3% 50 kullanmalıdır), özel bir LayoutManager uygulamadan bunu başarmak mümkün müdür?

Yanıtlar:


236
  1. Bu yöntemlerin kullanımından tamamen kaçınmalı mıyım?

    Uygulama kodu için evet.

  2. Yöntemler bir nedenle tanımlanmıştır. Peki onları ne zaman kullanmalıyım? Hangi bağlamda? Hangi amaçlar için?

    Bilmiyorum, kişisel olarak bunu bir API tasarım kazası olarak düşünüyorum. Çocuk boyutları hakkında özel fikirleri olan bileşik bileşenler tarafından biraz zorlandı. "Biraz", çünkü ihtiyaçlarını özel bir LayoutManager ile uygulamış olmalılardı.

  3. Bu yöntemleri kullanmanın olumsuz sonuçları tam olarak nedir? (Yalnızca farklı ekran çözünürlüğüne sahip sistemler arasında taşınabilirlik eklemeyi düşünebilirim.)

    Bazı teknik nedenler belirtilen örneğin edilir (eksik ve ne yazık ki bağlantılar nedeniyle java.net için SwingLabs göçü için kırık) Kuralları (hehe) veya bağlantı @bendicott için onun / onu yorumunda bulundu Cevabıma . Sosyal olarak, kodu korumak zorunda olan ve bozuk bir düzeni izlemek zorunda olan talihsiz arkadaşınıza tonlarca çalışma yapmak.

  4. Herhangi bir LayoutManager'ın istenen tüm yerleşim ihtiyaçlarını tam olarak karşılayabileceğini düşünmüyorum. Düzenimdeki her küçük değişiklik için gerçekten yeni bir LayoutManager uygulamam gerekiyor mu?

    Evet, "tüm düzen ihtiyaçları" na çok iyi bir yaklaşımı karşılayacak kadar güçlü LayoutManager'lar vardır. Büyük üçü JGoodies FormLayout, MigLayout, DesignGridLayout. Yani hayır, pratikte, basitçe özelleşmiş ortamlar dışında nadiren LayoutManager'lar yazarsınız.

  5. 4'ün yanıtı "evet" ise, bu, bakımı zorlaşan LayoutManager sınıflarının çoğalmasına neden olmaz mı?

    (4'ün cevabı "hayır" dır.)

  6. Bir Bileşenin çocukları arasındaki oranları tanımlamam gereken bir durumda (örneğin, çocuk 1 alan% 10, çocuk 2% 40, çocuk 3% 50 kullanmalıdır), özel bir LayoutManager uygulamadan bunu başarmak mümkün müdür?

    Big-Three'den herhangi biri GridBag'i bile yapamaz (gerçekten ustalaşmak için asla uğraşmadı, çok az güç için çok fazla sorun).


4
En az iki durumda bu tavsiyeye katıldığımdan tam olarak emin değilim. 1) Özel olarak oluşturulmuş bileşenler 2) JEditorPaneKendisi için bir genişlik önermeyen HTML'li bir. OTOH Bir şeyleri özlediğimden emin değilim. Konudaki cevapları dikkatlice inceleyeceğim, ancak özellikle ikinci durumda herhangi bir yorumunuz varsa ilgilendi.
Andrew Thompson

2
@Andrew Thompson 1) özel kompozisyonlar: eğer impl buggy 2 yoksa yararlı düzen ipuçları döndürmekten sorumlu olan comp kendisi 2) bile çekirdek comps buggy ;-) 3) beyaz boşluk umurumda değil kasıtlı bu kez, teşekkürler :-)
kleopatra

8
Kabul edilen yanıtın setXXX () yöntemlerini kullanmaktan kaçındığını söyleyen kişi olduğuna inanamıyorum. Bazen mizanpaj yöneticisine bir ipucu vermeniz gerekir. Bir panel döşiyorsanız, gerektiğinde bu yöntemleri kullanmaktan çekinmeyin. Uygun düzen yöneticisini kullanırsanız, bu yöntemlere çok sık ihtiyacınız olmadığını, ancak bazen onlara ihtiyacınız olduğunu düşünüyorum. Bir X_AXIS BoxLayout'a JComboBox veya JSpinner koymayı deneyin ve bunları kullanmayın, orada setMaximumSize () 'e ihtiyacınız olduğunu bulacağınıza inanıyoruz.
Michael

5
@Michael hayır, kesinlikle ihtiyacım yok - cevap her zaman iyi bir LayoutManager kullanmak ve yönetici düzeyinde herhangi bir ince ayar yapmak (bileşen seviyesine karşı)
kleopatra

5
Her zaman stackoverflow üzerinde "iyi bir LayoutManager kullanın ve ne istediğiniz boyutları söyle" diyorsun, ama asla "iyi" bir LayoutManager belirli bir örnek vermeyin. Ve standart yöneticilerin hiçbiri boyutları doğrudan kontrol etmeye izin vermez.
Ti Strga

100

Birkaç buluşsal yöntem:

  • Burada gösterilen kendi bileşeninizi oluştururken yapılabileceği gibi, set[Preferred|Maximum|Minimum]Size()gerçekten geçersiz kılmak istediğinizde kullanmayın .get[Preferred|Maximum|Minimum]Size()

  • Burada ve aşağıda gösterildiği gibi set[Preferred|Maximum|Minimum]Size()bir bileşenin dikkatlice geçersiz kılındığı durumlarda kullanmayın .getPreferred|Maximum|Minimum]Size

  • Aşağıda ve burada gösterildiği gibi set[Preferred|Maximum|Minimum]Size()post- validate()geometri türetmek için kullanın .

  • Bir bileşenin tercih edilen bir boyutu yoksa, örneğin JDesktopPanekabı boyutlandırmanız gerekebilir, ancak bu tür herhangi bir seçenek isteğe bağlıdır. Bir yorum, amacı açıklığa kavuşturmaya yardımcı olabilir.

  • Bu yorumlarda belirtildiği gibi, türetilmiş boyutlar elde etmek için birçok bileşen arasında geçiş yapmanız gerektiğini fark ettiğinizde alternatif veya özel düzenleri düşünün .

resim açıklamasını buraya girin

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());
            }
        }
    }
}

2
katılmıyorum (tahmin edebileceğiniz gibi :-) "dış faktörler" tarafından akıl yürütme ile: XXSize özellikleri sadece dahili ihtiyaçları ifade etmek içindir . Bunları dışarıdan ayarlamak yanlış kullanım, yani hackleme. Aa'ya göre belirli bir boyuta sahip bir (Dahili veya J-) çerçeve istiyorsanız, tercih edilen ... çerçeveyi boyutlandırın, içeriği değil
kleopatra

2
@kleopatra: sadece biraz ısrarcı olmak için: setXXSize yöntemleri hiçbir zaman dışarıdan kullanılmamalıysa, neden özel veya korumalı olarak ilan edilmemiş? Bu bir tasarım eksikliği değil mi? Genel değiştirici kullanıcıya dolaylı olarak bu yöntemleri kullanabileceğini söylemiyor mu?
Heisenbug

2
@Kleopatra ile hemfikirim: setPreferredSize()her zaman bileşenin hesaplamasını keyfi bir seçimle değiştirir.
trashgod

1
@trashgod +100 size, bu yöntemleri geçersiz kılma, hatta onları çağırmayla ilgili bir sorun olmadığını düşünüyorum (ancak elbette bu, özel bir bileşene sahip olduğunuz anlamına gelir, bu nedenle geçersiz kılma daha iyi olurdu)
David Kroukamp

5
@DavidKroukamp: Teşekkür ederim. Kleopatra'nın daha büyük deneyimine erteliyorum, ama karşıt görüşü eleştirel olarak incelemenin değerini görüyorum.
trashgod

47

Bu yöntemlerin kullanımından tamamen kaçınmalı mıyım?

Hayır, bu yöntemlerin çağrılmasına veya geçersiz kılınmasına izin verilmesine ilişkin resmi bir kanıt yoktur. Aslında Oracle, bu yöntemlerin boyut ipuçları vermek için kullanıldığını söylüyor: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .

Ayrıca, bir Swing bileşeni genişletilirken (yöntemi özel bileşen örneğinde çağırmak yerine ) geçersiz kılınabilir (Swing için en iyi uygulamadır )

En önemlisi, bileşeninizin boyutunu nasıl belirtirseniz belirtin, bileşeninizin kapsayıcısının, bileşenin istenen boyutuna uyan bir düzen yöneticisi kullandığından emin olun.

Yöntemler bir nedenle tanımlanmıştır. Peki onları ne zaman kullanmalıyım? Hangi bağlamda? Hangi amaçlar için?

Kapsayıcıya özelleştirilmiş boyut ipuçları sağlamanız gerektiğinde, bileşenin iyi düzenlenmesi için Düzen yöneticisi

Bu yöntemleri kullanmanın olumsuz sonuçları tam olarak nedir? (Yalnızca farklı ekran çözünürlüğüne sahip sistemler arasında taşınabilirlik eklemeyi düşünebilirim).

  • Birçok düzen yöneticisi, bir bileşenin istenen maksimum boyutuna dikkat etmez. Ancak BoxLayoutve yapın SpringLayout. Ayrıca, GroupLayoutbileşene dokunmadan minimum, tercih edilen veya maksimum boyutu açıkça ayarlama yeteneği sağlar.

  • Bileşenin kesin boyutunu gerçekten ayarlamanız gerektiğinden emin olun. Her Swing bileşeninin kullandığı yazı tipine ve görünümüne ve hissine bağlı olarak farklı bir tercih edilen boyutu vardır. Böylece, belirli bir boyuta sahip olmak , farklı Sistemlerde kullanıcı arayüzünün çeşitli görünümlerini üretebilir

  • bazen GridBagLayoutkabın boyutu tercih edilen boyuttan küçükse, metin alanlarının önemli ölçüde küçülmesine neden olabilecek minimum boyut kullanılır.

  • JFramegetMinimumSize()sadece setMinimumSize(..)eserleri çağırmayı geçersiz kılmayı zorunlu kılmaz

Herhangi bir LayoutManager'ın istenen tüm yerleşim ihtiyaçlarını tam olarak karşılayabileceğini düşünmüyorum. Düzenimdeki her küçük değişiklik için gerçekten yeni bir LayoutManager uygulamam gerekiyor mu?

Uygulayarak kullanmak demek evet ise. Kimse LayoutMangerher şeyi idare edemez, her LayoutManagerbirinin artıları ve eksileri vardır, böylece her biri nihai düzeni üretmek için birlikte kullanılabilir.

Referans:


3
kendi içinde bir çelişki olan özelleştirilmiş boyut ipuçları sağlayın : boyutlandırma ipuçları (px!) sağlamak, bileşenin özel görevidir. Bunları, kendisinden başka hiçbir partinin bilemeyeceği (veya takip edemeyeceği) iç durum detaylarına dayanarak hesaplar. İstemci perspektifinden, özelleştirme araçları uygun bir LayoutManager olabilir ve / veya bileşen üzerinde "semantik" boyutla ilgili özellikler, bir metin bileşenindeki sıra / sütun fi sayısı bakımından boyut gereksinimlerinin yapılandırılmasına izin veren API'de uzmanlaşabilir
Kleopatra

3
@kleopatra Oracle'ın neden bu yöntemleri nasıl kullanacağımızı ve bunları doğru şekilde nasıl kullanacağımızı bize anlatmayı çok isterim. Kendi tercihlerimiz olabilir, ancak tasarımcıların bunu önerecek kanıt olmadığında kullanılmadığını söyleyemeyiz. Ama bu yüzden lütuf koyuyorum, belki de oracle devletlerinin bu yöntemleri hiç kullanmamaları için güvenilir bir kaynaktan bilgi verebilecek başkalarını çekip çekmediğini görüyorum (böylece yaparsanız kötü uygulama yapmak, örneğin setMinimumSize olması gerekir JSplitPane gibi şeyleri çağırdı bu bölünmüş bölmelerin Oracle öğretici görülebilir
David Kroukamp

4
@David: setXxxSizeMetodları , dokümanlar önerdiğinde bile, burada sarılabileceğim bir kırmızı bayrak olarak görmeye geldim . Ben hemen hemen her zaman geçersiz olması gerekirdi getXxxSizebirinin gereken geometri erişimi olan yerlerde; ve hatta kısa örnekler bile düşündüğümden daha fazla geri dönüştürülüyor. Düzen yöneticileri arasındaki varyasyonu belirtmek ve öğreticiye atıf yapmak için +1.
trashgod

1
D'oh, yukarıdaki yorumumda, cevabı burada belirtmek istedim .
trashgod

13
+1 "Hayır, bu yöntemlerin çağrılmasına veya geçersiz kılınmasına izin verilmesine ilişkin resmi bir kanıt yok." Açık. Yanıt olarak etiketlenen gönderi düz BS'dir.
TT.

25

Orada burada iyi cevaplar bir yeri vardır ama ben nedenleri hakkında biraz daha eklemek istiyorum neden normalde bu kaçınmalısınız (soru sadece yinelenen konu tekrar gündeme geldi):

Birkaç istisna dışında, bu yöntemleri kullanıyorsanız, muhtemelen GUI'nizi belirli bir görünüm ve his üzerinde (ve sisteme özgü ayarlarınız, örneğin tercih ettiğiniz masaüstü yazı tipi vb.) İyi görünecek şekilde ince ayar yapıyorsunuzdur. Yöntemlerin kendileri doğası gereği kötü değildir, ancak bunları kullanmanın tipik nedenleri vardır . Bir düzende piksel konumlarını ve boyutlarını ayarlamaya başlar başlamaz, diğer platformlarda GUI'nizin kırılması (veya en azından kötü görünüyor) riskini yaşarsınız.

Bunun bir örneği olarak, uygulamanızın varsayılan görünüm ve izlenimini değiştirmeyi deneyin. Sadece platformunuzdaki seçeneklerle bile, sonuçların ne kadar kötü sonuçlanabileceğine şaşırabilirsiniz.

Bu nedenle, GUI'nizi tüm platformlarda işlevsel ve güzel görünümlü tutmak için (unutmayın, Java'nın en büyük avantajlarından biri platformlar arası platformudur), boyutlarını otomatik olarak ayarlamak için düzen yöneticilerine, vb. bileşenlerinizi özel geliştirme ortamınızın dışında doğru şekilde görünecek şekilde ayarlayın.

Bütün bunlar, bu yöntemlerin haklı olduğu durumları kesinlikle düşünebilirsiniz. Yine, doğası gereği kötülük yapmazlar, ancak kullanımları normalde potansiyel GUI sorunlarını gösteren büyük bir kırmızı bayraktır. Sadece bunları kullanırken / kullandığınızda komplikasyonların yüksek potansiyelinin farkında olduğunuzdan emin olun ve sorunlarınıza her zaman farklı bir görünüm ve hissetmeden bağımsız bir çözüm olup olmadığını düşünün ve düşünün. yöntem gerekli değildir.

Bu arada, kendinizi standart düzen yöneticileri ile hayal kırıklığına uğratırsanız, birçok iyi ücretsiz, açık kaynaklı üçüncü taraf var, örneğin JGoodies 'FormLayout veya MigLayout. Bazı GUI oluşturucuları, üçüncü taraf mizanpaj yöneticileri için yerleşik desteğe bile sahiptir - Eclipse'nin WindowBuilder GUI editörü, örneğin, FormLayoutve için destekle birlikte gönderilir MigLayout.


2
+ 1 düşünceli bir cevabı + sadece kendiliğinden kötü olmadıklarına katılmıyorum :-) Çünkü tipik olarak, dışarıdan müşteriler tahmin etmek için hiçbir şansa sahip değildir - ve varsayımlar dışarıdan gelenlerin alabileceği kadar yakındır - sadece doğru düzen ipuçları: sadece bileşenleri kendileri yararlı bir şey dönmek için her zaman tüm bilgilere sahip. Ve dışarıdan gelenler müdahale ettiği andan bu ipuçlarını yapamayacakları kadar güncel tutmak onların sorumluluğudur.
Kleopatra

1
Bilirsiniz, bu tür şeyler hakkında daha fazla "silahım insanları öldürmez, insanlar insanları öldürür". :) Eğer birileri bu yöntemleri kullanır, bunlar gerek (bu yöntemler uygun durumlar gerçekten nadirdir neden olan) Eğer düzen ipuçlarını öngörülemeyen kullanımı hakkında yükseltmek iyi noktaları gibi şeylerin farkında olmak.
Jason C

Bence tercih edilen boyutu ayarlamak hiç de büyük bir kırmızı bayrak değil. O ayarlanmaması olduğunu yerine büyük bir kırmızı bayrak. Açıklayayım. Düzen yöneticisi - ne kadar akıllı olursa olsun) bir gui widget'inin mantıksal işlevi hakkında hiçbir fikri yoktur. Örneğin, mizanpaj yöneticisi ZIP kodu girmek için bir JTextField ve bir isim girmek için bir JTextField arasında ayrım yapamaz. Benzer şekilde, JTextField öğesinin yanındaki araç düğmesi veya formun altındaki büyük bir OK düğmesi arasında ayrım yapamaz. Bu nedenle ya daha iyi bir widget seti ya da bazı boyutlandırma ipuçları gerekir, değil mi?
Gee Bee

@GeeBee Hayır, bu aslında kırmızı bayrağın en iyi örneği. Yapmanız gerekenJTextField.setColumns , tercih edilen boyutu buna göre ayarlayan sütun sayısını ayarlamak için kullanmaktır . Bunu yaparsanız setPreferredSize, platform yazı tipi boyutuna bağlı olarak düzenlerinizi kıracak bir boyutu zor kodlarsınız. Uygun şekilde setColumnsçağrılmış bir ızgara çantası düzenindeki bazı metin alanları . Düğmeleriniz için boyutları kontrol etmek üzere uygun düzenleri / ızgara ağırlıklarını kullanın.
Jason C

@GeeBee Ve şimdi, doğru bir şekilde yapıldığında, yazı tipi boyutunu küçülttüğümde metin alanı genişliklerinin nasıl azaldığına dikkat edin: i.snag.gy/ZULulh.jpg . Hatta tüm metin alanı genişliklerini yeniden hesaplamak ve her biri için setPreferredSize'ı tekrar çağırmak zorunda kalmadan, yazı tipi boyutunu anında değiştirmek bile otomatik olarak çalışır, yapmanız gereken tek şey düzeni geçersiz kılmaktır ve boyutları ayarlanır.
Jason C

20

Java Swing düzenleri ile sorun yaşıyorsanız, o zaman son derece JGoodies tavsiye FormLayoutKarsten Lentzsch tarafından Formlar ücretsiz kütüphane parçası olarak serbestçe temin burada .

Bu çok popüler mizanpaj yöneticisi son derece esnektir ve çok parlak Java kullanıcı arayüzlerinin geliştirilmesine olanak tanır.

Burada Karsten belgelerini ve burada tutulma ile ilgili oldukça iyi belgeleri bulabilirsiniz .


16

Bu yöntemler çoğu insan tarafından yeterince anlaşılmamıştır. Bu yöntemleri kesinlikle görmezden gelmemelisiniz. Bu yöntemleri onurlandırmak düzen yöneticisine bağlıdır. Bu sayfada, hangi düzen yöneticilerinin aşağıdaki yöntemlerden hangisini onurlandırdığını gösteren bir tablo vardır:

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

8+ yıldır Swing kodu yazıyorum ve JDK'da bulunan mizanpaj yöneticileri her zaman ihtiyaçlarımı karşıladı. Düzenlerimi gerçekleştirmek için hiçbir zaman 3. taraf düzen yöneticisine ihtiyaç duymadım.

İhtiyacınız olduğundan emin olana kadar düzen yöneticisi ipuçlarını bu yöntemlerle vermeye çalışmamanız gerektiğini söyleyeceğim. Düzeninizi boyutlandırma ipuçları vermeden yapın (yani düzen yöneticisinin işini yapmasına izin verin) ve sonra gerekirse küçük düzeltmeler yapabilirsiniz.


1
hafif bir yanlış anlama (sizin tarafınızdan) veya yanlış anlama (benim tarafımdan), seçiminizi alın :-) Tekrar tekrar (burada, blogunuzda, BoxLayout ile ilgili cevabınızda) set XXSize önemli olarak - aslında LayoutManager, XXSize ile ilgileniyor (veya ilgilenmiyor), bu, nasıl gerçekleştiğinden bağımsız olarak boyutlandırma ipucu (bileşen tarafından dahili hesaplama veya uygulama kodu tarafından manuel olarak zorla)
kleopatra

1
Burada ne elde ettiğinizi anladığımdan emin değilim. Yukarıda XXSize () yöntemlerinin sadece ipuçları olduğunu belirtmiştim. Gerekirse, mizanpaj yöneticisine küçük bir ipucu vermede gerçekten yanlış bir şey göremiyorum. Salıncak kodumda, ara sıra bir setXXSize () yöntemi bulacaksınız. Çok değil, ama arada bir ihtiyaç duyulduğunu görüyorum. JComboBox ve JSpinner sık ​​sık ipuçlarına ihtiyaç duyar. Özellikle gerçekleştikten sonra doldurulan bir JComboBox. Bu yöntemlerin her türlü kullanımına karşısınız ve nedenini bilmiyorum. (belki de sanırım bu gemide tekneyi özlüyorum).
Michael

5
değil yöntemler ipuçlarıdır, özellikleri şunlardır: bileşenler tüm ipuçları için makul bir şey bildirmelidir, bazı (fi JComboBox gibi) yok - bu yüzden maxInteger veya dönen. Bu bir hata ve açılan tarafından düzeltilmelidir. Alışkanlığınıza gelince: bakımcı koleji bunu temizlemek zorunda kaldığında çok uzak olduğunuzdan emin olun :) Sabit kodlu ipuçları, düzeni en ufak bir değişiklikle yıkma eğilimindedir ve kırık bir düzenin nedeni olarak tespit edilmesi zordur.
kleopatra

15

Bir Bileşenin çocukları arasında oranlar tanımlamam gereken bir durumda (çocuk 1, alanın% 10'unu, çocuk2% 40'ı, çocuk3% 50'yi kullanmalıdır), özel bir düzen yöneticisi uygulamadan bunu başarmak mümkün müdür?

Belki GridBagLayoutihtiyaçlarınızı karşılardı. Bunun yanı sıra, web üzerinde bir ton düzen yöneticisi var ve eminim gereksinimlerinize uyan bir tane var.


Cevap için teşekkürler. Ben de demek istediğimi varsayıyorum: "hiç setPreferredSize kullanmayın", değil mi?
Heisenbug

1
GridBagLayout, belirli bir bileşen için hem X hem de Y'de "ağırlık" belirtebileceğiniz kısıtlamalar kullanır, böylece LayoutManager yeniden boyutlandırmadaki fazladan boşlukla ne yapılacağına karar verebilir. AMA hala her bir bileşenin tercih edilen boyutunu belirlemek için setPreferredSize gerekir / kullanabilirsiniz , "tercih edilen" her zaman onurlandırılacağı anlamına gelmez. Özel durumlar için yine de setMinimumSize ve setMaximumSize öğelerine ihtiyacınız olabilir. Onlar kötü değil, buna alışma . docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
よ ル ち ゃ ん だ

5

Bunu kabul edilen cevaptan farklı görüyorum.

1) Bu yöntemlerin kullanımından tamamen kaçınmalı mıyım?

Asla kaçının! Bileşenlerinizin boyut sınırlamalarını mizanpaj yöneticisine ifade etmek için oradalar. Herhangi bir düzen yöneticisi kullanmıyorsanız bunları kullanmaktan kaçınabilirsiniz ve görsel düzeni kendi başınıza yönetmeye çalışabilirsiniz.

Ne yazık ki, Swing makul varsayılan boyutlarla gelmiyor. Bununla birlikte, bir bileşenin boyutlarını ayarlamak yerine, kendi bileşeninizi makul varsayılanlarla alçaltmak daha iyidir. (Bu durumda, alt sınıfınızda setXXX'i çağırırsınız.) Alternatif olarak, aynı etki için getXXX yöntemlerini geçersiz kılabilirsiniz.

2) Yöntemler bir nedenle tanımlanmıştır. Peki onları ne zaman kullanmalıyım? Hangi bağlamda? Hangi amaçlar için?

Her zaman. Bir bileşen oluşturduğunuzda, o bileşenin kullanımına göre gerçekçi min / tercih edilen / maks boyutunu ayarlayın. Örneğin, İngiltere gibi ülke sembollerini girmek için bir JTextField öğeniz varsa, tercih edilen boyutu iki karaktere (geçerli yazı tipiyle vb.) Sığacak kadar geniş olacaktır, ancak muhtemelen daha büyük büyümesine izin vermek anlamsızdır. Sonuçta, ülke sembolleri iki karakterdir. Tersi olarak, örneğin bir müşteri adı girmek için bir JTextField öğeniz varsa, 20 karakter için piksel boyutu gibi tercih edilen bir boyuta sahip olabilir, ancak düzen yeniden boyutlandırılırsa daha büyük büyüyebilir, bu nedenle maksimum boyutu daha fazla olarak ayarlayın. Aynı zamanda, 0px genişliğinde bir JTextField sahip olmak anlamsız, bu yüzden gerçekçi bir minimum boyutu ayarlayın (2 karakter piksel boyutunu söyleyebilirim).

3) Bu yöntemleri kullanmanın olumsuz sonuçları tam olarak nelerdir?

(Yalnızca farklı ekran çözünürlüğüne sahip sistemler arasında taşınabilirlik eklemeyi düşünebilirim).

Olumsuz sonuçları yok. Bunlar mizanpaj yöneticisi için ipuçları.

4) Herhangi bir LayoutManager'ın istenen tüm yerleşim ihtiyaçlarını tam olarak karşılayabileceğini düşünmüyorum.

Düzenimdeki her küçük değişiklik için gerçekten yeni bir LayoutManager uygulamam gerekiyor mu?

Hayır kesinlikle olmaz. Genel yaklaşım yatay ve dikey mizanpaj gibi farklı temel mizanpaj yöneticilerini kademelendirmektir.

Örneğin, aşağıdaki düzen:

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

iki bölümden oluşuyor. Sol ve sağ kısımlar yatay bir yerleşim düzenidir. Sağ kısım yatay düzene eklenen bir JPanel'dir ve bu JPanel, düğmeleri dikey olarak düzenleyen dikey bir düzene sahiptir.

Tabii ki, bu gerçek bir yaşam düzeniyle zorlaşabilir. Bu nedenle, ciddi bir şey geliştirmek üzereyseniz MigLayout gibi ızgara tabanlı düzen yöneticileri çok daha iyidir.

5) Eğer 4'e verilen cevap "evet" ise, bu, bakımı zorlaşan LayoutManager sınıflarının çoğalmasına neden olmaz mı?

Hayır, çok özel bir şeye ihtiyacınız olmadıkça kesinlikle düzen yöneticileri geliştirmeyeceksiniz.

6) Oranları tanımlamam gereken bir durumda ...

bir Bileşenin çocukları arasında (örneğin, child1% 10 alan, child2% 40, child3% 50 kullanmalıdır), özel bir LayoutManager uygulamadan bunu başarmak mümkün müdür?

Temel olarak, tercih edilen boyutlar doğru ayarlandıktan sonra, yüzde olarak hiçbir şey yapmak istemeyebilirsiniz. Basitçe, yüzdeler anlamsız olduğu için (örneğin, pencere boyutunun% 10'unda bir JTextField olması anlamsızdır), çünkü biri pencereyi küçültebilir, böylece JTextField 0 piksel genişliğinde olur veya pencereyi genişletebilir, böylece JTextField bir çoklu ekran kurulumu).

Ancak, yüzdelerinizi gui'nizin daha büyük yapı taşlarının boyutlarını kontrol etmek için kullanabilirsiniz (örneğin paneller).

İki tarafın oranını önceden ayarlayabileceğiniz JSplitPane kullanabilirsiniz. Veya yüzde, piksel ve diğer birimlerde bu tür kısıtlamaları ayarlamanıza izin veren MigLayout'u kullanabilirsiniz.


Gerçekten mi? Bu 0'da mıydı? Bu 100+ up olan kabul edilen cevaptan daha iyidir. Temelde "SetPreferredSize Kullanacaksınız!" KORKUNÇ. Çalışma alanımda, "Dokunmatik ekranlardaki düğmeler [Y] ile [Y] ve [M] x [N] arasında boşluk olmalı” güvenlik gereksinimi gibi bir çok özel boyut gereksinimi vardır. btnBar.setPreferredSize( dimTouchBtn );bunu yapmanın en iyi yoludur. Basit, özel düzen yöneticisine gerek yok. Çoğunlukla kullanmak GridBagLayoutbazılarıyla BorderLayoutve BoxLayoutne zaman uygun iç içe. Bu güçlü bir kombinasyon ve kullanımı kolaydır.
Loduwijk

Yukarıdaki yorumda aceleci oldu. Bu, kabul edilen cevaptan sonra gördüğüm ilk cevaptı. Neden SO artık oy sayımına göre sıralanmıyor? Bunun aslında oy sayımının temel nedenlerinden biri olduğunu düşündüm. Yine de orijinal yorum yanındayım; bu daha iyi cevaplardan biri. # 6 noktası dışında - o kadar da büyük değil. Yeniden boyutlandırma nedenleri bol (azınlık hala çok sayıda olabilir) ve GridBagLayout çoğu durumda yaşadım iyi destekler.
Loduwijk

Bence yeniden boyutlandırma ve yeniden boyutlandırma dini bir karar olarak ele alınmayacak. Hiç kimsenin herhangi bir şeyi yeniden boyutlandırmak istemediği kullanım durumları vardır, örneğin önceden belirlenmiş bir sabit çözünürlükle bir kiosk için GUI geliştirirseniz. Endüstriyel HMI ekranlar ve "düğmeler" durumu gibi farklı hedefleriniz varsa, evet, bir dokunmatik ekranda bir düğme için en az 1 cm x 1 cm olması gerekir. Bu durumda, ekranın DPI'si nasıl yeniden boyutlandıracağınızı belirler. Metin alanları gibi diğer girdiler dikey olarak yeniden boyutlandırılamayabilir ve bazen (posta kodu gibi) yatay yeniden boyutlandırma da anlamsızdır.
Gee Bee

0

Bu yöntemlerin kullanımından tamamen kaçınmalı mıyım? Onlardan "kaçının" demezdim. Onlara ihtiyacınız olduğunu düşünüyorsanız muhtemelen yanlış bir şey yaptığınızı söyleyebilirim. Bileşen boyutları bağlam içinde belirlenir. Örneğin, Metin bileşeni boyutları, seçtiğiniz yazı tipiyle birlikte belirttiğiniz satır ve sütun sayısına göre belirlenir. Düğme ve etiket boyutunuz, ayarladıysanız grafiğin boyutu veya ayarladığınız metni görüntülemek için gereken alan olacaktır. Her bileşenin doğal bir boyutu vardır ve düzen yöneticileri, boyutları belirtmenize gerek kalmadan her şeyi düzenlemek için bunları kullanır. Ana istisna, içerdiği her şeyden bağımsız bir boyuta sahip olan JScrollPane'dir. Bunlar için bazen arayacağım setSize()ve bu boyutun arayarak ilk pencere boyutunu belirlemesine izin vereceğimJFrame.pack(). Genellikle, pencere boyutu JScrollPane boyutunu belirlemek izin verir. Kullanıcı pencerenin boyutunu belirleyecektir. Birçok düzen yöneticisi zaten ayarladığınız boyutları görmezden gelir, bu nedenle çoğu zaman pek iyi değildir.

Yöntemler bir nedenle tanımlanmıştır. Peki onları ne zaman kullanmalıyım? Hangi bağlamda? Hangi amaçlar için? Düzen yöneticilerine ipuçları vermek için eklendiğine inanıyorum. Tarihsel nedenlerle yazılmış olabilirler, çünkü düzen yöneticileri yeniydi ve insanlar onlara tam olarak güvenmediler. Yeni bir paradigma öğrenmekle uğraşmak istemedikleri için mizanpaj yöneticilerinden kaçınan ve her şeyi manuel olarak yerleştiren birkaç geliştirici biliyorum. Bu korkunç bir fikir.

Bu yöntemleri kullanmanın olumsuz sonuçları tam olarak nedir? (Yalnızca farklı ekran çözünürlüğüne sahip sistemler arasında taşınabilirlik eklemeyi düşünebilirim). Etkisizdirler ve nesneler doğal olmayan boyutlara sıkışan veya gerilen kötü düzenler oluştururlar. Ve düzenler kırılgan olacak. Pencere boyutundaki değişiklikler bazen düzeni bozar ve işleri yanlış yerlere koyar.

Herhangi bir LayoutManager'ın istenen tüm yerleşim ihtiyaçlarını tam olarak karşılayabileceğini düşünmüyorum. Düzenimdeki her küçük değişiklik için gerçekten yeni bir LayoutManager uygulamam gerekiyor mu? Yeni bir LayoutManager'ı "uygulamamalısınız". Mevcut olanları somutlaştırmalısınız. Genellikle tek bir pencerede birkaç düzen yöneticisi kullanıyorum. Her JPanel'in kendi mizanpaj yöneticisi olacaktır. Bazı insanlar iç içe yerleşimlerde kalırlar, çünkü bakımı zordur. Onları kullandığımda, her birinin ne yaptığını görmeyi kolaylaştırmak için her birine kendi yaratma yöntemini veriyorum. Ama bir mizanpaj yöneticisini asla "uygulamam". Ben sadece onları canlandırıyorum.

Eğer 4'e verilen cevap "evet" ise, bu, bakımı zorlaşan LayoutManager sınıflarının çoğalmasına neden olmaz mı? Düzendeki küçük değişiklikler için yeni düzen yöneticisi sınıfları uyguluyorsanız, bunları yanlış kullanıyorsunuzdur. Sadece yeni düzen yöneticileri uyguluyorsanız, muhtemelen yanlış bir şey yapıyorsunuzdur. Bir LayoutManager sınıfını genişlettiğim tek zaman, bir JScrollPane'e bir yakınlaştırma kaydırıcısı eklemekti.

Bir Bileşenin çocukları arasında oranlar tanımlamam gereken bir durumda (örneğin, child1 alanın% 10'unu, child2% 40, child3% 50'yi kullanmalıdır), özel bir LayoutManager uygulamadan bunu başarmak mümkün müdür? JSplitPane, her bileşenin alması gereken yüzdeyi belirtmenin bir yoluna sahiptir. Bölücü varsayılan olarak hareketlidir, ancak isterseniz bunu kapatabilirsiniz. Bu özelliği fazla kullanmıyorum. Genellikle belirli bir boyuta sahip bazı bileşenlerim var ve alanın geri kalanı bir kaydırma bölmesi tarafından kullanılıyor. Kaydırma bölmesi boyutu pencere boyutuna göre ayarlanır. Yan yana iki kaydırma bölmeniz varsa, bunları bir JSplitPane içine yerleştirebilir ve kullanıcı pencereleri genişletip daraltırken her birine verilen yeni alan yüzdesini belirtebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.