2012-04-29 15 views
7

Java/Eclipse IDE hier.JButtons in JPanels mit einem GridLayout JFrame

Ich habe einen JFrame, der auf ein GridLayout der Größe NxN festgelegt ist. N wird vom Benutzer als Befehlszeile am Anfang des Programms angegeben. JButtons in einem NxN-Muster werden zu dem Fenster in JPanels hinzugefügt, das von GridLayout an Stelle gesetzt wird (glaube ich).

Benötigt jedes JButton ein eigenes JPanel, um GridLayout zu verwenden? Ich habe den Eindruck, dass Sie nur ein JPanel für alle Buttons einrichten und das JPanel auf ein GridLayout für die JButtons einstellen können. Ich möchte ein weiteres JPanel links neben dem Button-Array hinzufügen, um Button-Klicks (JLabel) und einen Reset-Button innerhalb desselben linken JPanels anzuzeigen.

Hier ist (ein wenig) mein Code, wobei N durch den Benutzer gegeben wird, System ist mein Hintergrundklasse verarbeitet und Button ist die Klasse für Action/actionPerformed:

JFrame window = new JFrame(""); 
GridLayout layout = new GridLayout(N,N); 
window.setLayout(layout); 

for (int row = 0; row < N; row++){ 
    for (int col = 0; col < N; col++){ 
     JPanel panel = new JPanel(); 
     JButton b = new JButton ("("+row+","+col+")"); 
     window.add(b).setLocation(row, col); 
     panel.add(b); 
     b.addActionListener(new ButtonEvent(b, system, row, col)); 
     window.add(panel); 
    } 
} 

window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
window.pack(); 
window.setVisible(true); 

Und das ist, was ich habe (N = 4):

http://i.imgur.com/nbQoM.png

Hier ist (ungefähr), was ich suche (N = 4):

http://i.imgur.com/SiVWO.png

Alles, was ich brauche/will, sind zwei (oder mehr) JPanels, die ungefähr wie oben eingerichtet sind, und alle Layoutmanager, die ich ausprobiert habe, spielen mit dem GridLayout Layout JFrame nicht gut.

Alle Empfehlungen zu einer besseren Lösung sind eingeladen.

Danke!

Antwort

11

Hier versuchen, dieses Codebeispiel:

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

public class LayoutExample extends JFrame 
{ 
    private static final String INITIAL_TEXT = "Nothing Pressed"; 
    private static final String ADDED_TEXT = " was Pressed"; 
    private JLabel positionLabel; 
    private JButton resetButton; 
    private static int gridSize = 4; 

    public LayoutExample() 
    { 
     super("Layout Example"); 
    } 

    private void createAndDisplayGUI() 
    {  
     setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     JPanel contentPane = new JPanel(); 
     contentPane.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 20)); 
     contentPane.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2)); 

     JPanel leftPanel = new JPanel(); 
     leftPanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2)); 
     leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));  
     JPanel labelPanel = new JPanel(); 
     positionLabel = new JLabel(INITIAL_TEXT, JLabel.CENTER); 
     JPanel buttonLeftPanel = new JPanel(); 
     resetButton = new JButton("Reset"); 
     resetButton.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      { 
       positionLabel.setText(INITIAL_TEXT); 
      } 
     }); 
     labelPanel.add(positionLabel); 
     buttonLeftPanel.add(resetButton); 
     leftPanel.add(labelPanel); 
     leftPanel.add(buttonLeftPanel); 

     contentPane.add(leftPanel); 

     JPanel buttonPanel = new JPanel(); 
     buttonPanel.setLayout(new GridLayout(gridSize, gridSize, 10, 10)); 
     for (int i = 0; i < gridSize; i++) 
     { 
      for (int j = 0; j < gridSize; j++) 
      { 
       JButton button = new JButton("(" + i + ", " + j + ")"); 
       button.setActionCommand("(" + i + ", " + j + ")"); 
       button.addActionListener(new ActionListener() 
       { 
        public void actionPerformed(ActionEvent ae) 
        { 
         JButton but = (JButton) ae.getSource(); 
         positionLabel.setText(
          but.getActionCommand() + ADDED_TEXT);       
        } 
       }); 
       buttonPanel.add(button); 
      } 
     } 
     contentPane.add(buttonPanel); 

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

    public static void main(String[] args) 
    { 
     if (args.length > 0) 
     { 
      gridSize = Integer.parseInt(args[0]); 
     } 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       new LayoutExample().createAndDisplayGUI(); 
      } 
     }); 
    } 
} 

OUTPUT:

Start After Click

+1

+1 Siehe auch dieses verwandte [Beispiel] (http://stackoverflow.com/a/7706684/230513). – trashgod

+1

@trashgod: Danke, dass du diesen großen Bug entfernt hast, denn jetzt wird er zumindest ohne Argumente laufen :-). Mein Scheck vorher war nutzlos, LOL. –

+0

Schön! Ich mag es, wie dies die Größe ändert (oder tatsächlich nicht die Größe ändert). Der folgende Beitrag von trashgod erklärt genau, warum das so funktioniert. Vielen Dank! – Avertheus

7

Hat jeder JButton braucht ein eigenes JPanel Gridlayout zu benutzen?

Nein Add und setLayout auf JFrame tun nicht, was sie erscheinen. JFrame ist Top-Level-Container und es ist besser, Ihre Inhalte in JPanels zu organisieren.

Sie sollten Ihre Platten in dieser Form organisieren:

----JPanel----------------------------| 
| ---LeftPanel--- ---ButtonsPanel--- | 
| |    | |    | | 
| |    | |    | | 
| |    | | GridLayout(N,N)| | 
| |    | |    | | 
| |    | |    | | 
| --------------- ------------------ | 
--------------------------------------- 

Dann JPanel zum JFrame hinzufügen. setzen auch Paneele in separaten Klassen:

class BPanel extends JPanel { 
    public BPanel() { 
     GridLayout layout = new GridLayout(N,N, hgap, vgap); 
     setLayout(layout); 
     for (int row = 0; row < N; row++){ 
      for (int col = 0; col < N; col++){ 
       JButton b = new JButton ("("+row+","+col+")"); 
       add(b).setLocation(row, col); 
       b.addActionListener(new ButtonEvent(b, system, row, col)); 
      } 
     } 
    } 
} 
class LeftPanel extends JPanel { 
.... 
} 

class MainFrame extends JFrame { 
    public MainFrame() { 
     JPanel p = new JPanel(); 
     p.add(new LeftPanel()); 
     p.add(newButtonsPanel()); 
     add(p); 
    } 
} 
+1

Schöne Antwort. Große ASCII-Kunst! Siehe auch das [Verschachtelte Layout-Beispiel] (http://stackoverflow.com/a/5630271/418556). –

+0

Ja, das scheint für mich funktioniert zu haben. Ich habe jetzt alle meine JPanels in verschiedenen Klassen und ein einziges JPanel für das GridLayout. Danke für die Erklärung! – Avertheus

3

Ein Vorteil jeder Taste geben (oder Gruppe von Schaltflächen) ein eigenes Panel ist, dass das verschachtelte Panel eine haben kann anderes Layout. In dieser example hat jede verschachtelte ButtonPanel die Standardeinstellung FlowLayout, so dass die Größe der Schaltfläche konstant bleibt, da der umschließende Container in der Größe geändert wird.

+0

Das ist interessant, genau das habe ich festgestellt, als ich die erste Antwort zu diesem Thread von @ixos gelesen habe, Zum Spaß setzte ich mich hin, um das zu tun, was OP wollte, und mir wurde klar, dass dieses "Größenaspekt" -Ding Probleme auf der linken Seite verursacht, deshalb trennen diese beiden JPanel's für "JButton" und "JLabel" ', aber was Sie vorgeschlagen haben, dass für jedes' JButton' ein 'JPanel', das hat mir gefallen :-) –

Verwandte Themen