2012-10-11 8 views
6

Buduję aplikację, która będzie składała się z kilku paneli z zakładkami. Na każdym z nich chciałbym umieścić zestawy komponentów oddzielone od siebie granicami. to będzie wyglądać:Jak otaczać komponenty Java Swing z ramką?

|- Titled Border 1 --- 

[JTextField] [JComboBox] [JTextField] [JComboBox] 

|-------- 

|- Titled Border 2 --- 

[JTextField] [JComboBox] [JTextField] [JComboBox] 

|-------- 

... and so forth. 

Kiedy starałem się po prostu dodać nową ramkę zatytułowaną 2 granic, do centrali, to dodano i obejmowało pierwszy pozostawiając komponenty na górze choć. W niektórych przykładach widziałem wiele JPaneli zdefiniowanych w ramach jednej ramki, a każdy panel miał swoją własną granicę. To może działać w moim przypadku, ale jak dodać te panele do wyświetlania w jednej karcie?

Jeden z tutoriali Oracle pokazuje dokładnie panel z zakładkami z demonstracją wielu rodzajów obramowań. Kiedy próbowałem go edytować i umieścić tam komponent, pojawił się on między dwiema granicami zamiast być otoczony. I była to kolejna opcja, która nie przyniosła mi sukcesu.

Po drugie, nie używam żadnego menedżera układu, pozycje komponentów są stałe i szczerze, zachowałbym to ustawienie. A może w tym konkretnym przypadku zalecamy korzystanie z dowolnego menedżera układu?

Czy masz jakieś wskazówki, jak rozwiązać ten problem?

Edit: wydaje się, że nie jestem jeszcze pozwolono dołączyć zrzut ekranu, ale tutaj jest część kodu dbanie o wyświetlanie granic:

lenMicro = new JPanel(); 
    lenMicro.setLayout(null); 

    bGreyLine = BorderFactory.createLineBorder(Color.GRAY, 1, true); 
    bTitled1 = BorderFactory.createTitledBorder(bGreyLine, "Length (1/2)", TitledBorder.LEFT, TitledBorder.TOP); 
    lenMicro.setBorder(bTitled1); 
    bTitled2 = BorderFactory.createTitledBorder(bGreyLine, "Length (2/2)", TitledBorder.LEFT, TitledBorder.TOP); 
    lenMicro.setBorder(bTitled2); 

Granica zatytułowanych „Długość (2/2)” jest wyświetlany, gdy ostatnie dwa wiersze są odkomentowane.

+3

powiedziałbym - użyj LayoutManager w 99,99% przypadków. Jedynym wyjątkiem może być podanie pewnych losowych obiektów, np. kształty rysunku użytkownika. – StanislavL

+0

Czy możesz dołączyć niektóre zrzuty ekranu zamiast opisywać sytuację? –

+2

Interfejs API mówi o umieszczeniu obramowania na kontenerze, w którym znajduje się składnik. –

Odpowiedz

15

Podczas korzystania z Absolute Positioning należy podać lokalizację dla każdego komponentu, który stanie się częścią widoku. Dlatego nie patrząc dokładnie na to, co robisz, trudno jest przewidzieć, gdzie dokładnie coś idzie źle. Chociaż użycie Layout Managers, usunie ten duży ciężar z twoich ramion w związku z rozmieszczeniem różnych elementów w widoku.

Ponadto należy ustawić granicę dla odpowiedniego komponentu. Nie mogę więc w żadnym wypadku założyć, że dodałeś jeden komponent i pojawił się on między dwiema granicami (chociaż biorąc pod uwagę fakt, że używasz pozycjonowania bezwzględnego, mogłeś podać nieprawidłowe współrzędne dla tego komponentu w widoku). Proszę spojrzeć na ten kod przykład, że może może pomóc trochę w tym kierunku:

import java.awt.*; 
import javax.swing.*; 
import javax.swing.border.*; 

public class BorderExample 
{ 
    private JPanel topPanel; 
    private JPanel centerPanel; 
    private JPanel bottomPanel; 
    private int hgap; 
    private int vgap; 
    private JTextField tfield1, tfield2; 
    private JComboBox cbox1, cbox2; 
    private String[] data = {"One", "Two"}; 

    public BorderExample() 
    { 
     hgap = 5; 
     vgap = 5; 
    } 

    private void displayGUI() 
    { 
     JFrame frame = new JFrame("Border Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel contentPane = new JPanel(); 
     contentPane.setOpaque(true); 
     contentPane.setBackground(Color.WHITE); 
     contentPane.setBorder(
      BorderFactory.createEmptyBorder(hgap, hgap, hgap, hgap)); 
     contentPane.setLayout(new BorderLayout(hgap, vgap)); 

     topPanel = new JPanel(); 
     topPanel.setOpaque(true); 
     topPanel.setBackground(Color.WHITE); 
     topPanel.setBorder(
      BorderFactory.createTitledBorder("Top Panel")); 
     tfield1 = new JTextField(10); 
     tfield1.setBorder(
      BorderFactory.createTitledBorder(
      BorderFactory.createEtchedBorder(
        EtchedBorder.RAISED, Color.GRAY 
        , Color.DARK_GRAY), "JTextField")); 
     JPanel comboPanel = new JPanel();   
     cbox1 = new JComboBox(data); 
     cbox1.setBorder(
      BorderFactory.createTitledBorder("JComboBox")); 
     topPanel.add(tfield1); 
     topPanel.add(cbox1); 

     centerPanel = new JPanel(); 
     centerPanel.setOpaque(true); 
     centerPanel.setBackground(Color.WHITE); 
     centerPanel.setBorder(
      BorderFactory.createTitledBorder("Center Panel")); 
     tfield2 = new JTextField(10); 
     tfield2.setBorder(
      BorderFactory.createLoweredBevelBorder()); 
     cbox2 = new JComboBox(data); 
     cbox2.setBorder(
      BorderFactory.createRaisedBevelBorder()); 
     centerPanel.add(tfield2); 
     centerPanel.add(cbox2); 

     bottomPanel = new JPanel(); 
     bottomPanel.setOpaque(true); 
     bottomPanel.setBackground(Color.WHITE); 
     bottomPanel.setBorder(
      BorderFactory.createTitledBorder("Center Panel")); 

     contentPane.add(topPanel, BorderLayout.PAGE_START); 
     contentPane.add(centerPanel, BorderLayout.CENTER); 
     contentPane.add(bottomPanel, BorderLayout.PAGE_END); 

     frame.setContentPane(contentPane); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String... args) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       new BorderExample().displayGUI(); 
      } 
     }); 
    } 
} 

Oto wyjściowa taka sama:

BORDER_EXAMPLE

+0

Wielkie dzięki! Pomógł mi zrozumieć, jak się sprawy mają w tej sprawie. Zdecydowałem się użyć menedżera układu, GridBagLayout, a teraz mam do czynienia z jego ustawieniami. Kiedy skończę, opublikuję najbardziej odpowiednie części kodu. – AbreQueVoy

+0

Na pewno zadajesz cokolwiek, co może sprawić ci kłopoty, układy są zawsze dobre. Dla reszty jesteś NAJBARDZIEJ WELCOME i KEEP SMILING :-) A [SSCCE] (http://sscce.org/) do pracy, nadal będzie doceniane –

2

OK, więc to rozwiązuje duża część moich obawy dotyczące korzystania z Layout Manager i dodanie obramowania do grup składników:

import javax.swing.*; 
import javax.swing.border.Border; 
import javax.swing.border.TitledBorder; 
import java.awt.*; 

public class TestingGround extends JFrame { 

private JTextField tLenUnit, tLenResult, tAreUnit, tAreResult; 
private JComboBox<String> cLenInUnit, cLenOutUnit, cAreInUnit, cAreOutUnit; 
private JPanel lenMicro, lenMicro1, lenMicro2, lenNormal, lenMacro, area, volume; 
private Border bGreyLine, bTitled1, bTitled2; 

private TestingGround() { 

    setTitle("Testing Ground for an Application"); 
    setVisible(true); 
    setResizable(true); 
    setLocationRelativeTo(null); 

    try { 
     UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } catch (InstantiationException e) { 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedLookAndFeelException e) { 
     e.printStackTrace(); 
    } 

    lenMicro = new JPanel(); 
    lenMicro.setLayout(new GridBagLayout()); 

    lenMicro1 = new JPanel(); 
    lenMicro1.setLayout(new GridBagLayout()); 

    bGreyLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1, true); 
    bTitled1 = BorderFactory.createTitledBorder(bGreyLine, "Length", TitledBorder.LEFT, TitledBorder.TOP); 
    lenMicro1.setBorder(bTitled1); 

    tLenUnit = new JTextField("0.0"); 
    tLenUnit.setColumns(10); 
    lenMicro1.add(tLenUnit, new GBC(0, 0, 2, 1).setAnchor(GBC.WEST).setInsets(5, 5, 5, 5)); 

    cLenInUnit = new JComboBox<String>(); 
    cLenInUnit.addItem(""); 
    cLenInUnit.addItem("First"); 
    cLenInUnit.addItem("Second"); 
    cLenInUnit.setSelectedIndex(0); 
    cLenInUnit.setPreferredSize(new Dimension(120, 25)); 
    lenMicro1.add(cLenInUnit, new GBC(2, 0, 3, 1)); 

    tLenResult = new JTextField(""); 
    tLenResult.setColumns(10); 
    lenMicro1.add(tLenResult, new GBC(5, 0, 2, 1).setInsets(5, 5, 5, 5)); 

    cLenOutUnit = new JComboBox<String>(); 
    cLenOutUnit.addItem("First"); 
    cLenOutUnit.addItem("Second"); 
    cLenOutUnit.setSelectedIndex(1); 
    cLenOutUnit.setPreferredSize(new Dimension(120, 25)); 
    lenMicro1.add(cLenOutUnit, new GBC(7, 0, 1, 1)); 

    // Area part: 

    lenMicro2 = new JPanel(); 
    lenMicro2.setLayout(new GridBagLayout()); 

    bTitled2 = BorderFactory.createTitledBorder(bGreyLine, "Area", TitledBorder.LEFT, TitledBorder.TOP); 
    lenMicro2.setBorder(bTitled2); 

    tAreUnit = new JTextField("0.0"); 
    tAreUnit.setColumns(10); 
    lenMicro2.add(tAreUnit, new GBC(0, 1, 2, 1).setAnchor(GBC.WEST).setInsets(5, 5, 5, 5)); 

    cAreInUnit = new JComboBox<String>(); 
    cAreInUnit.addItem(""); 
    cAreInUnit.addItem("One sqm"); 
    cAreInUnit.addItem("Two sqm"); 
    cAreInUnit.setSelectedIndex(0); 
    cAreInUnit.setPreferredSize(new Dimension(120, 25)); 
    lenMicro2.add(cAreInUnit, new GBC(2, 1, 3, 1)); 

    tAreResult = new JTextField(""); 
    tAreResult.setColumns(10); 
    lenMicro2.add(tAreResult, new GBC(5, 1, 2, 1).setInsets(5, 5, 5, 5)); 

    cAreOutUnit = new JComboBox<String>(); 
    cAreOutUnit.addItem("One sqm"); 
    cAreOutUnit.addItem("Two sqm"); 
    cAreOutUnit.setSelectedIndex(1); 
    cAreOutUnit.setPreferredSize(new Dimension(120, 25)); 
    lenMicro2.add(cAreOutUnit, new GBC(7, 1, 1, 1)); 

    // Joining all lenMicroX panels into one: 

    lenMicro.add(lenMicro1, new GBC(0, 0, 8, 1).setAnchor(GBC.FIRST_LINE_START).setInsets(5, 5, 5, 5).setIpad(10, 10)); 
    lenMicro.add(lenMicro2, new GBC(0, 1, 8, 1).setAnchor(GBC.LINE_START).setInsets(5, 5, 5, 5).setIpad(10, 10)); 

    volume = new JPanel(); 
    volume.setLayout(null); 

    // Panel definition --begin: 

    JTabbedPane tPane = new JTabbedPane(); 

    tPane.addTab("Length & Area", null, lenMicro, "Length & Area units"); 
    tPane.addTab("Volume", null, volume, "Volume units"); 
    add(tPane); 

    // Panel --end. 
} 

public static void main(String[] args) { 

    TestingGround app = new TestingGround(); 
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    app.pack(); 
    app.setVisible(true); 

} 

} 

GridBagConstraints klasa pomocnika jest podejmowane fro m Cay Horstmann's i Gary Cornell's Jawa Core i można znaleźć tutaj: http://www.horstmann.com/articles/GBC.java.

Udało mi się dowiedzieć z przykładu Gagandeepa, że ​​panele można umieścić na wierzchu, nazwijmy to panelem macierzystym. W ten sposób każde dziecko-panele może mieć swoją własną granicę.

Druga sprawa: Postanowiłem użyć GridBagLayout, ponieważ wydaje się być najdokładniejszym do wykorzystania w tym i innych moich projektach.Cóż, wciąż muszę się wiele na ten temat dowiedzieć (na przykład, aby dopasować komponenty do niektórych linii ;-) [edit: just added setPreferredSize() do JComboBoxes; sprawia, że ​​układ wygląda lepiej ;-)]).

Dziękuję wszystkim za pomoc i cenne wskazówki!

The application after correction.

+1

Tylko słowo porady, zawsze używaj połączeń takich jak ** frame.setVisible (true/false) **, po dodaniu wszystkiego do 'JFrame', a nie wcześniej. W ten sposób przedstawia się widokowi, gdy tylko zda sobie sprawę z jego wielkości. Tak jak przez ciebie, może czasami powodować nieprawidłowe wyniki, wywołując właściwość widoczną dużo wcześniej, zanim ramka faktycznie obliczyła jej rozmiar. +1 za wysiłek, jaki włożyłeś w to :-) –

+1

OK, dzięki za radę! (Będę musiał wtedy porozmawiać z moim nauczycielem, ha ha :-)) – AbreQueVoy