2017-02-23 2 views
1

Inspiriert von dieser Frage JLayeredPane with a LayoutManager Ich versuche, die JLayeredPane mit dem GridBagLayout arbeiten zu lassen.JLayeredPane und GridBagConstraints

Hier ist die individuelle LayeredPane-Klasse:

class StackConstraints { 
    public final int layer; 
    public final Object layoutConstraints; 

    public StackConstraints(int layer, Object layoutConstraints) { 
     this.layer = layer; 
     this.layoutConstraints = layoutConstraints; 
    } 
} 

class LXLayeredPane extends JLayeredPane { 

    private static final long serialVersionUID = 1946283565823567689L; 

    @Override 
    protected void addImpl(Component comp, Object constraints, int index) { 
     int layer = 0; 
     int pos = 0; 
     Object constr = null; 
     if (constraints instanceof StackConstraints) { 
      layer = ((StackConstraints) constraints).layer; 
      constr = ((StackConstraints) constraints).layoutConstraints; 
     } else { 
      layer = getLayer(comp); 
      constr = constraints; 
     } 

     pos = insertIndexForLayer(layer, index); 
     super.addImpl(comp, constr, pos); 
     setLayer(comp, layer, pos); 
     comp.validate(); 
     comp.repaint(); 
    } 
} 

Und hier ist eine einfache Demo (ähnlich wie die Standard-JLayeredPane Demo aber für die Nutzung von GridBagConstraints und gestrippt der unnötigen Sachen angepasst).

public class LayeredPaneDemo extends JPanel implements ActionListener { 
    private final Color[] layerColors = { Color.yellow, Color.magenta, Color.cyan, Color.red, Color.green, Color.blue }; 

    private final JLayeredPane layeredPane; 
    private final List<JLabel> labels; 

    private JButton update; 

    public LayeredPaneDemo() { 
     setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 

     labels = new ArrayList<>(); 

     layeredPane = new LXLayeredPane(); 
     layeredPane.setPreferredSize(new Dimension(400, 410)); 
     layeredPane.setBorder(BorderFactory.createTitledBorder("Click to change colors")); 

     // Add several labels to the layered pane. 
     layeredPane.setLayout(new GridBagLayout()); 
     for (int i = 0; i < layerColors.length; i++) { 
      JLabel label = createColoredLabel("Test", layerColors[i]); 
      labels.add(label); 
      layeredPane.add(label, new StackConstraints(i, gbc(i))); 
     } 

     // Add control pane and layered pane to this JPanel. 
     add(Box.createRigidArea(new Dimension(0, 10))); 
     add(createControlPanel()); 
     add(Box.createRigidArea(new Dimension(0, 10))); 
     add(layeredPane); 
    } 

    private GridBagConstraints gbc(int i) { 
     return new GridBagConstraints(i, i, 2, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, 
       new Insets(0, 0, 0, 0), 0, 0); 
    } 

    // Create and set up a colored label. 
    private JLabel createColoredLabel(String text, Color color) { 
     JLabel label = new JLabel(text); 
     label.setVerticalAlignment(JLabel.TOP); 
     label.setHorizontalAlignment(JLabel.CENTER); 
     label.setOpaque(true); 
     label.setBackground(color); 
     label.setForeground(Color.black); 
     label.setBorder(BorderFactory.createLineBorder(Color.black)); 
     label.setPreferredSize(new Dimension(240, 240)); 
     return label; 
    } 

    // Create the control pane for the top of the frame. 
    private JPanel createControlPanel() { 
     update = new JButton("Update"); 
     update.addActionListener(this); 
     update.setActionCommand("UPDATE"); 

     JPanel controls = new JPanel(); 
     controls.add(update); 
     controls.setBorder(BorderFactory.createTitledBorder("Choose Duke's Layer and Position")); 
     return controls; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     Color prev = labels.get(labels.size() - 1).getBackground(); 

     for (int i = labels.size() - 1; i > 0; --i) { 
      labels.get(i).setBackground(labels.get(i - 1).getBackground()); 
      labels.get(i).validate(); 
      labels.get(i).repaint(); 
     } 
     labels.get(0).setBackground(prev); 
     labels.get(0).validate(); 
     labels.get(0).repaint(); 
    } 

    private static void createAndShowGUI() { 
     JFrame frame = new JFrame("LayeredPaneDemo2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JComponent newContentPane = new LayeredPaneDemo(); 
     newContentPane.setOpaque(true); 
     frame.setContentPane(newContentPane); 

     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

} 

Mein Problem ist, dass ich 6 (sechs!) Etiketten hinzufügen, aber nur 5 (fünf!) Angezeigt werden. Der 0. verschwindet einfach irgendwo. Was ist der Grund dafür?

EDIT: Die anfängliche Motivation hinter der Verfolgung ist eine (teilweise transparent) Komponente auf einem anderen, wie in diesem Bildschirm enter image description here Das Etikett hat 17.00.09 transparenten Hintergrund Anzeige zu platzieren und ist auf der Oberseite platziert der Chart-Komponente. GridBagLayout ist erforderlich, um es genau in der oberen Mitte des Diagramms zu platzieren.

+0

'Ich versuche, die JLayeredPane arbeiten mit dem GridBagLayout zu bekommen.'Warum? Das sind zwei verschiedene Konzepte. Ein geschichtetes Fenster dient zum Anzeigen von Komponenten in einer Ebene. Ein GridBagLayout wird zum Anzeigen von Komponenten in einem Panel verwendet. Was ist das genaue Problem, das Sie versuchen zu lösen? Ich sehe nicht, wie das Verhalten, das Sie erreicht haben, anders ist als das der ursprünglichen, überlagerten Fenster-Demo. – camickr

+0

Bearbeitete die Antwort, um die Motivation zu erklären. Ich hätte Platten mit transparentem Hintergrund und dem GridBagLayout für jede andere Ebene verwenden können, aber sie wollten einfach nicht richtig funktionieren. – Mischa

+0

'aber sie wollten einfach nicht richtig funktionieren '- das definiert das Problem nicht. Sie haben zwei mögliche Probleme: 1) mit dem Layered-Panel-Code oder 2) mit den Einschränkungen, die für das GridBagLayout in jedem Panel verwendet werden. Veröffentlichen Sie eine ordnungsgemäße [mcve], die das Problem veranschaulicht. Aus dem Bild kann ich nicht sagen, welche Komponente gestapelt ist oder was das eigentliche Problem ist. – camickr

Antwort

3
  • Wie @camickr bereits gesagt hat, ist JLayeredPane irrelevant.
  • Werfen Sie einen Blick auf GridBagLayout to create a board | Oracle Community. Vielleicht hilft es.

    Darryl.Burke gesagt:
    Eine Spalte (oder Zeile) in einer GridBagLayout nicht gut definiert, wenn nicht mindestens eine Komponente ist, die nur diese Spalte einnimmt (oder Zeile). Alle Ihre Zeilen haben Komponenten, die 2 Spalten umfassen.

screenshot

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 
import java.util.List; 
import javax.swing.*; 
import javax.swing.table.*; 

public class LayeredPaneDemo2 extends JPanel implements ActionListener { 
    private final Color[] layerColors = { 
     Color.yellow, Color.magenta, Color.cyan, 
     Color.red, Color.green, Color.blue }; 

    private final JLayeredPane layeredPane; 
    private final List<JLabel> labels; 

    private JButton update; 

    public LayeredPaneDemo2() { 
    setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); 

    labels = new ArrayList<>(); 
    // JLayeredPane is not much related, it is a problem of how to use GridBagLayout. 
    layeredPane = new LXLayeredPane(); 
    layeredPane.setPreferredSize(new Dimension(400, 410)); 
    layeredPane.setBorder(BorderFactory.createTitledBorder(
     "Click to change colors")); 

    // Add several labels to the layered pane. 
    layeredPane.setLayout(new GridBagLayout()); 

    for (int i = 0; i < layerColors.length; i++) { 
     JLabel label = createColoredLabel("Test" + i, layerColors[i]); 
     labels.add(label); 
     layeredPane.add(label, new StackConstraints(i, gbc(i))); 
    } 
//  //TEST1: Create reference grid 
//  GridBagConstraints c = new GridBagConstraints(
//  0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, 
//  GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0); 
//  for (int i = 0; i < layerColors.length + 1; i++) { 
//  c.gridx = i; 
//  c.gridy = i; 
//  layeredPane.add(Box.createRigidArea(new Dimension(20, 20)), c); 
//  } 
    //TEST2: Create reference grid >>> 
    GridBagConstraints c = new GridBagConstraints(
     6, 6, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, 
     GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0); 
    for (int i = 0; i < layerColors.length; i++) { 
     c.gridx = i; 
     Component box = Box.createRigidArea(new Dimension(20, 20)); 
     ((JComponent) box).setBorder(BorderFactory.createLineBorder(Color.RED)); 
     layeredPane.add(box, c); 
    } 
    c.gridx = 6; 
    for (int i = 0; i < layerColors.length; i++) { 
     c.gridy = i; 
     Component box = Box.createRigidArea(new Dimension(20, 20)); 
     ((JComponent) box).setBorder(BorderFactory.createLineBorder(Color.RED)); 
     layeredPane.add(box, c); 
    } 
    // <<< 
    // Add control pane and layered pane to this JPanel. 
    add(Box.createRigidArea(new Dimension(0, 10))); 
    add(createControlPanel()); 
    add(Box.createRigidArea(new Dimension(0, 10))); 
    add(layeredPane); 
    } 

    private GridBagConstraints gbc(int i) { 
    return new GridBagConstraints(
     i, i, 2, 2, 0.0, 0.0, GridBagConstraints.CENTER, 
     GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0); 
    } 

    // Create and set up a colored label. 
    private JLabel createColoredLabel(String text, Color color) { 
    JLabel label = new JLabel(text) { 
     @Override protected void paintComponent(Graphics g) { 
     g.setColor(new Color(100, 100, 100, 100)); 
     g.fillRect(0, 0, getWidth(), getHeight()); 
     super.paintComponent(g); 
     } 
    }; 
    label.setVerticalAlignment(JLabel.TOP); 
    label.setHorizontalAlignment(JLabel.CENTER); 
    label.setOpaque(true); 
    label.setBackground(color); 
    label.setForeground(Color.black); 
    label.setBorder(BorderFactory.createLineBorder(Color.black)); 
    label.setPreferredSize(new Dimension(240, 240)); 
    return label; 
    } 

    // Create the control pane for the top of the frame. 
    private JPanel createControlPanel() { 
    update = new JButton("Update"); 
    update.addActionListener(this); 
    update.setActionCommand("UPDATE"); 

    JPanel controls = new JPanel(); 
    controls.add(update); 
    controls.setBorder(BorderFactory.createTitledBorder(
     "Choose Duke's Layer and Position")); 
    return controls; 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
    Color prev = labels.get(labels.size() - 1).getBackground(); 

    for (int i = labels.size() - 1; i > 0; --i) { 
     labels.get(i).setBackground(labels.get(i - 1).getBackground()); 
     labels.get(i).validate(); 
     labels.get(i).repaint(); 
    } 
    labels.get(0).setBackground(prev); 
    labels.get(0).validate(); 
    labels.get(0).repaint(); 
    } 

    private static void createAndShowGUI() { 
    JFrame frame = new JFrame("LayeredPaneDemo2"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    JComponent newContentPane = new LayeredPaneDemo2(); 
    newContentPane.setOpaque(true); 
    frame.setContentPane(newContentPane); 

    frame.pack(); 
    frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
    javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     @Override 
     public void run() { 
     createAndShowGUI(); 
     } 
    }); 
    } 

} 

class StackConstraints { 
    public final int layer; 
    public final Object layoutConstraints; 

    public StackConstraints(int layer, Object layoutConstraints) { 
    this.layer = layer; 
    this.layoutConstraints = layoutConstraints; 
    } 
} 

class LXLayeredPane extends JLayeredPane { 
    @Override 
    protected void addImpl(Component comp, Object constraints, int index) { 
    int layer = 0; 
    int pos = 0; 
    Object constr = null; 
    if (constraints instanceof StackConstraints) { 
     layer = ((StackConstraints) constraints).layer; 
     constr = ((StackConstraints) constraints).layoutConstraints; 
    } else { 
     layer = getLayer(comp); 
     constr = constraints; 
    } 

    pos = insertIndexForLayer(layer, index); 
    super.addImpl(comp, constr, pos); 
    setLayer(comp, layer, pos); 
    comp.validate(); 
    comp.repaint(); 
    } 
} 
1

Gibt es einen grundlegenden Grund, warum ich Ebenen und GridBagLayout nicht mischen kann?

Das ist mein Punkt. Ich glaube nicht, dass Sie JLayeredPane anpassen müssen.

Eine geschichtete Scheibe wird zum Schichten von Platten verwendet.

Dann kann jedes einzelne Panel seinen eigenen Layoutmanager haben, egal ob GridBagLayout, FlowLayout oder was auch immer.

Zum Beispiel versuchen, die Schleife zu aktualisieren, die die Beschriftungen in der LayeredPaneDemo erstellt:

JLabel label = null; 

for (int i = 0; i < layerStrings.length; i++) { 
    //JLabel label = createColoredLabel(layerStrings[i], layerColors[i], origin); 
    label = createColoredLabel(layerStrings[i], layerColors[i], origin); 
    layeredPane.add(label, new Integer(i)); 
    origin.x += offset; 
    origin.y += offset; 
} 

label.setLayout(new GridBagLayout()); 
label.add(new JCheckBox("Check Me"), new GridBagConstraints()); 

Der obige Code eine Checkbox die Standardeinschränkungen auf dem Etikett wird nur hinzufügen, über die das Kontrollkästchen bedeutet, dass innerhalb der zentriert werden Etikette.

Mir ist nicht bewusst, dass Sie keinen anderen Layout-Manager für jedes Panel im geschichteten Bereich verwenden können. Wenn das Layout nicht das ist, was Sie erwarten, würde ich vermuten, dass Ihre GridBagConstrainsts nicht korrekt sind.

Verwandte Themen