Kilka razy byłem krytykowany za to, że zasugerowałem użycie następujących metod:
- setPreferredSize
- setMinimumSize
- setMaximumSize
na Swing
komponentach. Nie widzę żadnej alternatywy dla ich użycia, gdy chcę zdefiniować proporcje między wyświetlanymi komponentami. Powiedziano mi to:
W przypadku układów odpowiedź jest zawsze taka sama: użyj odpowiedniego narzędzia LayoutManager
Trochę przeszukałem Internet, ale nie znalazłem żadnej kompleksowej analizy tego tematu. Mam więc następujące pytania:
- Czy powinienem całkowicie unikać stosowania tych metod?
- Metody zostały zdefiniowane z jakiegoś powodu. Kiedy powinienem ich użyć? W jakim kontekście? Do jakich celów?
- Jakie dokładnie są negatywne konsekwencje stosowania tych metod? (Mogę tylko pomyśleć o dodaniu przenośności między systemami o różnej rozdzielczości ekranu).
- Nie sądzę, aby jakikolwiek LayoutManager mógł dokładnie zaspokoić wszystkie pożądane potrzeby układu. Czy naprawdę muszę wdrożyć nowy menedżer układów dla każdej małej odmiany mojego układu?
- Jeśli odpowiedź na 4 brzmi „tak”, czy nie doprowadzi to do mnożenia klas LayoutManager, które będą trudne do utrzymania?
- Czy w sytuacji, gdy muszę zdefiniować proporcje między elementami potomnymi komponentu (np. Dziecko 1 powinno zajmować 10% miejsca, dziecko 2 40%, dziecko 3 50%), czy można to osiągnąć bez implementacji niestandardowego menedżera układu?
źródło
JEditorPane
z HTML, który sam nie sugeruje szerokości. OTOH Nie jestem pewien, czy coś przeoczyłem. Dokładnie przejrzę odpowiedzi w wątku, ale byłem zainteresowany, jeśli masz jakieś uwagi, szczególnie w tym drugim przypadku.Kilka heurystyk:
Nie używaj,
set[Preferred|Maximum|Minimum]Size()
gdy naprawdę chcesz przesłonićget[Preferred|Maximum|Minimum]Size()
, jak można to zrobić przy tworzeniu własnego komponentu, pokazanego tutaj .Nie używaj,
set[Preferred|Maximum|Minimum]Size()
gdy możesz polegać na starannie przesłoniętym komponenciegetPreferred|Maximum|Minimum]Size
, jak pokazano tutaj i poniżej.Użyj
set[Preferred|Maximum|Minimum]Size()
do uzyskania post-validate()
geometrii, jak pokazano poniżej i tutaj .Jeśli komponent nie ma preferowanego rozmiaru, np.
JDesktopPane
Może być konieczne określenie rozmiaru kontenera, ale każdy taki wybór jest dowolny. Komentarz może pomóc wyjaśnić zamiar.Rozważ alternatywne lub niestandardowe układy, gdy okaże się, że będziesz musiał przejść przez wiele komponentów, aby uzyskać pochodne rozmiary, jak wspomniano w tych komentarzach .
źródło
setPreferredSize()
zawsze zastępuje obliczenia komponentu arbitralnym wyborem.Nie, nie ma formalnych dowodów sugerujących, że wywołanie lub zastąpienie tych metod jest niedozwolone. W rzeczywistości Oracle twierdzi, że te metody są używane do podawania wskazówek dotyczących rozmiaru: http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment .
Można je również przesłonić (co jest najlepszą praktyką dla Swing) podczas rozszerzania komponentu Swing (zamiast wywoływania metody na niestandardowej instancji komponentu)
Co najważniejsze, bez względu na to, jak określisz rozmiar komponentu, upewnij się, że kontener komponentu używa menedżera układu, który przestrzega żądanego rozmiaru komponentu.
Gdy trzeba podać niestandardowe wskazówki dotyczące rozmiaru menedżerowi układu kontenerów, aby komponent był dobrze rozplanowany
Wielu menedżerów układu nie zwraca uwagi na żądany maksymalny rozmiar komponentu. Jednak
BoxLayout
iSpringLayout
tak. PonadtoGroupLayout
zapewnia możliwość jawnego ustawienia minimalnego, preferowanego lub maksymalnego rozmiaru bez dotykania komponentu.Upewnij się, że naprawdę musisz ustawić dokładny rozmiar komponentu. Każdy komponent Swing ma inny preferowany rozmiar, w zależności od używanej czcionki oraz wyglądu i stylu. Zatem posiadanie ustawionego rozmiaru może powodować zróżnicowany wygląd interfejsu użytkownika w różnych systemach
czasami można napotkać problemy z
GridBagLayout
polami tekstowymi i, w których jeśli rozmiar kontenera jest mniejszy niż rozmiar preferowany, wykorzystywany jest rozmiar minimalny, co może powodować znaczne zmniejszenie pól tekstowych.JFrame
nie wymusza nadpisaniagetMinimumSize()
tylko przywoływaniasetMinimumSize(..)
swoich dziełJeśli przez wdrożenie masz na myśli użycie, to tak. Nie
LayoutManger
da się obsłużyć wszystkiego, każdyLayoutManager
ma swoje zalety i wady, dzięki czemu każdy z nich może być użyty razem w celu uzyskania ostatecznego układu.Odniesienie:
źródło
setXxxSize
metody jako czerwoną flagę, że mogę tu skończyć , nawet jeśli sugerują to dokumenty. I prawie zawsze powinien nadpisanegetXxxSize
, gdzie ma dostęp do wymaganej geometrii; a nawet krótkie przykłady są poddawane recyklingowi bardziej, niż chcę myśleć. +1 za wzmiankę o różnicach między menedżerami układu i cytowanie samouczka.Jest tutaj wiele dobrych odpowiedzi, ale chcę dodać trochę więcej o powodach, dla których powinieneś ich unikać (pytanie pojawiło się ponownie w zduplikowanym temacie):
Z kilkoma wyjątkami, jeśli używasz tych metod, prawdopodobnie dopracowujesz GUI, aby dobrze wyglądać w określonym wyglądzie (i przy ustawieniach specyficznych dla systemu, np. Preferowanej czcionki pulpitu itp.). Same metody nie są z natury złe, ale typowe powody ich używania to . Gdy tylko zaczniesz dostrajać pozycje i rozmiary pikseli w układzie, ryzykujesz uszkodzenie swojego GUI (lub przynajmniej źle wyglądającego) na innych platformach.
Jako przykład tego spróbuj zmienić domyślny wygląd aplikacji. Nawet z opcjami dostępnymi na twojej platformie możesz być zaskoczony, jak słabo można renderować wyniki.
Tak więc, w imię utrzymania GUI funkcjonalnego i ładnego na wszystkich platformach (pamiętaj, jedną z głównych zalet Javy jest jego wieloplatformowość), powinieneś polegać na menedżerach układu itp., Aby automatycznie dostosowywać rozmiary komponenty, aby renderowało się poprawnie poza określonym środowiskiem programistycznym.
To powiedziawszy, z pewnością możesz wyobrazić sobie sytuacje, w których metody te są uzasadnione. Ponownie, nie są z natury źli, ale ich użycie jest zwykle dużą czerwoną flagą wskazującą na potencjalne problemy z GUI. Upewnij się tylko, że zdajesz sobie sprawę z wysokiego potencjału powikłań, jeśli / kiedy ich używasz, i zawsze staraj się zastanowić, czy istnieje inne niezależne od wyglądu rozwiązanie swoich problemów - najczęściej okazuje się, że metody nie są konieczne.
Nawiasem mówiąc, jeśli czujesz się sfrustrowany standardowymi menedżerami układu, istnieje wiele dobrych darmowych, otwartych programów zewnętrznych, na przykład JGoodies
FormLayout
lubMigLayout
. Niektóre konstruktory GUI mają nawet wbudowaną obsługę zewnętrznych menedżerów układu - na przykład edytor GUI WindowBuilder firmy Eclipse jest dostarczany z obsługąFormLayout
iMigLayout
.źródło
JTextField.setColumns
ustawić liczbę kolumn, która odpowiednio dostosuje preferowany rozmiar. Jeśli to zrobiszsetPreferredSize
, programujesz na stałe rozmiar, który spowoduje uszkodzenie układów w zależności od rozmiaru czcionki platformy. Oto kilka pól tekstowych w układzie siatki siatki zsetColumns
odpowiednio wywoływanymi . Do przycisków używaj odpowiednich układów / ciężarów siatki, aby kontrolować rozmiary.Jeśli masz problemy z układami w Java Swing, mogę gorąco polecić JGoodies
FormLayout
dostarczone bezpłatnie jako część darmowej biblioteki Forms autorstwa Karstena Lentzscha tutaj .Ten bardzo popularny menedżer układu jest niezwykle elastyczny, dzięki czemu można opracowywać bardzo dopracowane interfejsy Java.
Znajdziesz tutaj dokumentację Karstena , a trochę dobrej dokumentacji z zaćmienia tutaj .
źródło
Metody te są słabo rozumiane przez większość ludzi. Absolutnie nie powinieneś ignorować tych metod. Od menedżera układu zależy, czy zastosują się do tych metod. Ta strona zawiera tabelę, która pokazuje, którzy menedżerowie układu honorują, które z tych metod:
http://thebadprogrammer.com/swing-layout-manager-sizing/
Piszę kod Swing od ponad 8 lat, a menedżerowie układu znajdujący się w JDK zawsze spełniali moje potrzeby. Nigdy nie potrzebowałem zewnętrznego menedżera układu, aby uzyskać moje układy.
Powiem, że nie powinieneś próbować udzielać wskazówek menedżerowi układu tymi metodami, dopóki nie będziesz pewien, że ich potrzebujesz. Wykonaj swój układ bez żadnych wskazówek dotyczących zmiany rozmiaru (tj. Pozwól menedżerowi układu wykonać swoją pracę), a następnie możesz wprowadzić niewielkie poprawki, jeśli zajdzie taka potrzeba.
źródło
Może
GridBagLayout
zaspokoi twoje potrzeby. Poza tym w sieci jest mnóstwo menedżerów układu i założę się, że jest taki, który pasuje do twoich wymagań.źródło
Widzę to inaczej niż zaakceptowana odpowiedź.
1) Czy powinienem całkowicie unikać stosowania tych metod?
Nigdy nie unikaj! Są one po to, aby wyrazić ograniczenia wielkości komponentów dla menedżera układu. Możesz uniknąć ich używania, jeśli nie korzystasz z żadnego menedżera układu i spróbuj samodzielnie zarządzać układem wizualnym.
Niestety, Swing nie ma rozsądnych domyślnych wymiarów. Jednak zamiast ustawiać wymiary komponentu, lepiej OOP schodzić z własnego komponentu z rozsądnymi wartościami domyślnymi. (W takim przypadku wywołujesz setXXX w klasie potomnej.) Alternatywnie możesz zastąpić metody getXXX dla tego samego efektu.
2) Metody zostały zdefiniowane z konkretnego powodu. Kiedy powinienem ich użyć? W jakim kontekście? Do jakich celów?
Zawsze. Podczas tworzenia komponentu ustaw jego realistyczny minimalny / preferowany / maksymalny rozmiar zgodnie z użyciem tego komponentu. Na przykład, jeśli masz JTextField do wprowadzania symboli kraju, takich jak Wielka Brytania, jego preferowany rozmiar powinien być tak szeroki, aby zmieścił się w dwóch znakach (z bieżącą czcionką itp.), Ale prawdopodobnie nie ma sensu pozwolić, aby urósł. W końcu symbole kraju to dwa znaki. Przeciwnie, jeśli masz JTextField do wprowadzania np. Nazwy klienta, może on mieć preferowany rozmiar podobny do rozmiaru piksela dla 20 znaków, ale może wzrosnąć do większego, jeśli zmieni się rozmiar układu, więc ustaw maksymalny rozmiar na więcej. Jednocześnie posiadanie JTextField o szerokości 0 pikseli jest bezcelowe, więc ustaw realistyczny minimalny rozmiar (powiedziałbym, że piksel to 2 znaki).
3) Jakie dokładnie są negatywne konsekwencje stosowania tych metod?
(Mogę tylko pomyśleć o dodaniu przenośności między systemami o różnej rozdzielczości ekranu).
Bez negatywnych konsekwencji. Są to wskazówki dla menedżera układu.
4) Nie sądzę, aby jakikolwiek LayoutManager mógł dokładnie zaspokoić wszystkie pożądane potrzeby układu.
Czy naprawdę muszę wdrożyć nowy menedżer układów dla każdej małej odmiany mojego układu?
Nie definitywnie nie. Zwykle stosuje się kaskadowanie różnych podstawowych menedżerów układu, takich jak układ poziomy i pionowy.
Na przykład poniższy układ:
ma dwie części. Lewa i prawa część mają układ poziomy. Prawa część to JPanel dodany do układu poziomego, a ten JPanel ma układ pionowy, który układa przyciski pionowo.
Oczywiście może to stać się trudne z układem w prawdziwym życiu. Dlatego menedżery układu oparte na siatce, takie jak MigLayout, są znacznie lepsze, jeśli masz zamiar opracować coś poważnego.
5) Jeśli odpowiedź na 4 brzmi „tak”, czy nie doprowadzi to do mnożenia klas LayoutManager, które będą trudne do utrzymania?
Nie, zdecydowanie nie powinieneś tworzyć menedżerów układu, chyba że potrzebujesz czegoś bardzo specjalnego.
6) W sytuacji, gdy muszę zdefiniować proporcje ...
między dziećmi elementu (np. dziecko1 powinno zajmować 10% miejsca, dziecko2 40%, dziecko3 50%), czy można to osiągnąć bez implementacji niestandardowego menedżera LayoutManager?
Zasadniczo po prawidłowym ustawieniu preferowanych rozmiarów możesz nie chcieć nic robić procentowo. Po prostu, ponieważ wartości procentowe są bezcelowe (np. Nie ma sensu mieć JTextField 10% rozmiaru okna - ponieważ można zmniejszyć okno, aby JTextField stał się 0px szeroki, lub można rozwinąć okno, aby JTextField znajdował się na dwóch ekranach na konfiguracja wielu wyświetlaczy).
Ale może się zdarzyć, że użyjesz wartości procentowych do kontrolowania rozmiarów większych elementów konstrukcyjnych twojego GUI (na przykład paneli).
Możesz użyć JSplitPane, gdzie możesz wstępnie ustawić stosunek dwóch stron. Lub możesz użyć MigLayout, który pozwala ustawić takie ograniczenia w procentach, pikselach i innych jednostkach.
źródło
btnBar.setPreferredSize( dimTouchBtn );
jest najlepszym sposobem na to. Prosto, nie ma potrzeby tworzenia niestandardowego menedżera układu. Używam głównieGridBagLayout
z niektórymiBorderLayout
iBoxLayout
zagnieżdżanie, gdy jest to wygodne. Jest to mocna kombinacja i łatwa w użyciu.Czy powinienem całkowicie unikać stosowania tych metod? Nie powiedziałbym „unikaj” ich. Powiedziałbym, że jeśli uważasz, że ich potrzebujesz, prawdopodobnie robisz coś złego. Rozmiary komponentów są określane w kontekście. Na przykład rozmiary komponentów tekstowych są określane przez liczbę określonych wierszy i kolumn w połączeniu z wybraną czcionką. Rozmiar przycisku i etykiety będzie odpowiadał rozmiarowi grafiki, jeśli ją ustawisz, lub przestrzeni potrzebnej do wyświetlenia ustawionego tekstu. Każdy komponent ma naturalny rozmiar, a menedżerowie układu użyją go do rozłożenia wszystkiego bez konieczności określania rozmiarów. Głównym wyjątkiem jest JScrollPane, który ma rozmiar niezależny od wszystkiego, co zawiera. Dla tych czasami dzwonię
setSize()
i pozwalam temu rozmiarowi określić początkowy rozmiar okna, dzwoniącJFrame.pack()
. Zazwyczaj pozwalam rozmiarowi okna określać rozmiar JScrollPane. Użytkownik określi rozmiar okna. Wielu menedżerów układu i tak ignoruje ustawione przez ciebie rozmiary, więc często nie robią nic dobrego.Metody zostały zdefiniowane z jakiegoś powodu. Kiedy powinienem ich użyć? W jakim kontekście? Do jakich celów? Wierzę, że zostały dodane, aby zapewnić wskazówki dla menedżerów układu. Być może zostały napisane z przyczyn historycznych, ponieważ menedżerowie układów byli nowi, a ludzie nie ufali im w pełni. Znam kilku programistów, którzy unikali menedżerów układu i umieszczali wszystko ręcznie, tylko dlatego, że nie chcieli zawracać sobie głowy poznawaniem nowego paradygmatu. To okropny pomysł.
Jakie dokładnie są negatywne konsekwencje stosowania tych metod? (Mogę tylko pomyśleć o dodaniu przenośności między systemami o różnej rozdzielczości ekranu). Są nieskuteczne i wytwarzają złe układy, a obiekty są ściskane lub rozciągane do nienaturalnych rozmiarów. A układy będą kruche. Zmiany rozmiaru okna czasami psują układ i umieszczają rzeczy w niewłaściwych miejscach.
Nie sądzę, aby jakikolwiek LayoutManager mógł dokładnie zaspokoić wszystkie pożądane potrzeby układu. Czy naprawdę muszę wdrożyć nowy menedżer układów dla każdej małej odmiany mojego układu? Nie powinieneś „wdrażać” nowego menedżera układów. Powinieneś utworzyć instancję istniejących. Często używam kilku menedżerów układu w jednym oknie. Każdy JPanel będzie miał własnego menedżera układu. Niektóre osoby boją się układów zagnieżdżonych, ponieważ są trudne do utrzymania. Kiedy ich używam, daję każdemu własną metodę tworzenia, aby łatwiej było zobaczyć, co każdy z nich robi. Ale nigdy nie „wdrażam” menedżera układu. Po prostu je tworzę.
Jeśli odpowiedź na 4 brzmi „tak”, czy nie doprowadzi to do mnożenia klas LayoutManager, które będą trudne do utrzymania? Jeśli wdrażasz nowe klasy menedżera układu dla niewielkich różnic w układzie, używasz ich źle. Jeśli tylko wdrażasz nowe menedżery układu, prawdopodobnie robisz coś złego. Jedyny raz, kiedy rozszerzyłem klasę LayoutManager, było dodanie suwaka powiększenia do JScrollPane.
Czy w sytuacji, gdy muszę zdefiniować proporcje między elementami potomnymi komponentu (np. Dziecko 1 powinno zajmować 10% miejsca, dziecko 2 40%, dziecko 3 50%), czy można to osiągnąć bez implementacji niestandardowego menedżera układu? JSplitPane ma sposób określania procentu, jaki powinien otrzymać każdy składnik. Rozdzielacz jest domyślnie ruchomy, ale możesz go wyłączyć, jeśli chcesz. Nie używam tej funkcji dużo. Zwykle mam niektóre elementy, które zajmują ustalony rozmiar, a resztę miejsca zajmuje okienko przewijania. Rozmiar panelu przewijania będzie dostosowywany do rozmiaru okna. Jeśli masz dwa panele przewijania obok siebie, możesz umieścić je w JSplitPane i określić procent nowego miejsca przydzielonego każdemu, gdy użytkownik rozszerza i kurczy okna.
źródło