2011-11-26 14 views
5

Ho un JFrame contenente un set di JPanels in un CardLayout. Ogni JPanel ha una dimensione diversa e voglio che lo JFrame si adatti alle dimensioni del JPanel attualmente visualizzato (non lo JPanel per adattarsi alle dimensioni dello JFrame).Come impostare una dimensione JFrame per adattarsi allo JPanel visualizzato su CardLayout?

Come posso ottenere questo risultato?

+2

* "Voglio che JFrame si adatti alle dimensioni del JPanel attualmente visualizzato" * Sarebbe strano per l'utente avere una dimensione di modifica del frame solo perché il contenuto visualizzato cambia. –

+0

Avere una dimensione fissa JFrame è piuttosto brutto quando il pannello interno non corrisponde. L'ho provato. – JVerstry

+0

Non sono sicuro che funzionerà, ma puoi provare questo: 'frame.setSize (pannello.getPreferredSize()); ' –

risposta

11

Il generale è: se avete un problema di layout, sempre risolverlo con una LayoutManager appropriata. Mai modificare il suggerimento di ridimensionamento di un componente per raggiungere l'obiettivo.

In questo caso, è particolarmente semplice regolare il CardLayout. Per impostazione predefinita, calcola il suo prefSize al massimo di prefSize di tutte le carte. Semplicemente sottoclasse e implementare per restituire la prefSize (più inserti) della scheda attualmente visibile:

public static class MyCardLayout extends CardLayout { 

    @Override 
    public Dimension preferredLayoutSize(Container parent) { 

     Component current = findCurrentComponent(parent); 
     if (current != null) { 
      Insets insets = parent.getInsets(); 
      Dimension pref = current.getPreferredSize(); 
      pref.width += insets.left + insets.right; 
      pref.height += insets.top + insets.bottom; 
      return pref; 
     } 
     return super.preferredLayoutSize(parent); 
    } 

    public Component findCurrentComponent(Container parent) { 
     for (Component comp : parent.getComponents()) { 
      if (comp.isVisible()) { 
       return comp; 
      } 
     } 
     return null; 
    } 

} 

Utilizzando che (indebitamento @ l'esempio di mKorbel), il metodo principale si restringe in modo pulito giù:

private static void createAndShowUI() { 
    final CardLayout cardLayout = new MyCardLayout(); 
    final JPanel cardHolder = new JPanel(cardLayout); 
    final JFrame frame = new JFrame("MultiSizedPanels"); 
    JLabel[] labels = { 
     new JLabel("Small Label", SwingConstants.CENTER), 
     new JLabel("Medium Label", SwingConstants.CENTER), 
     new JLabel("Large Label", SwingConstants.CENTER)}; 

    for (int i = 0; i < labels.length; i++) { 
     int padding = 50 * (i + 1); 
     Border lineBorder = BorderFactory.createCompoundBorder(
      BorderFactory.createLineBorder(Color.blue), 
      BorderFactory.createEmptyBorder(padding, padding, padding, padding)); 
     labels[i].setBorder(lineBorder); 
     JPanel containerPanel = new JPanel(); 
     containerPanel.add(labels[i]); 
     cardHolder.add(containerPanel, String.valueOf(i)); 
    } 
    JButton nextButton = new JButton("Next"); 
    nextButton.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      cardLayout.next(cardHolder); 
      frame.pack(); 
     } 
    }); 
    JPanel btnHolder = new JPanel(); 
    btnHolder.add(nextButton); 

    frame.add(cardHolder, BorderLayout.CENTER); 
    frame.add(btnHolder, BorderLayout.SOUTH); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setLocation(150, 150); 
    frame.setVisible(true); 
} 
+0

Grazie. È più pulito ed esattamente ciò che volevo. – JVerstry

+0

ora è il mondo più chiaro e bello +1 – mKorbel

+0

Così pulito che non posso crederci. Grazie! –

2

Penso che potresti avere il gestore di layout sbagliato per quello che vuoi fare (lasciando da parte, per il momento, che non sono sicuro di voler fare quello che dici di voler fare).

Non ho ancora trovato documentazione su ciò che sospetto, ovvero che CardLayout ridimensiona tutti i suoi figli alla dimensione del suo contenitore. Ho trovato il seguente commento per il suo metodo "layoutContainer":

  * Each component in the <code>parent</code> container is reshaped 
     * to be the size of the container, minus space for surrounding 
     * insets, horizontal gaps, and vertical gaps. 

Credo che questo sia un comportamento ragionevole, in quanto sarebbe molto fastidioso per un utente di avere il salto dimensione del pannello in giro come i pannelli sono attraversati.

Se questo è davvero il comportamento che si desidera, quindi penso che si desidera un gestore di layout diverso. E poiché si tratta di un comportamento insolito per un'interfaccia utente in generale, potresti non trovarne uno standard per eseguire questa particolare 'funzione', quindi potresti dover scrivere il tuo.

4

Ecco lo SSCCE.

1) Per aumentare/ridurre le dimensioni in modo continuo, è necessario cercare alcune API di animazione.

o

2) Se non v'è alcuna attività in background con uscita per l'interfaccia grafica, è possibile mettere in pausa, mentre il dimensionamento JFrame. In tal caso, si ritarderebbe l'aumento/la diminuzione utilizzando Thread#sleep(int) nel thread Runnable.

3) L'avviso (non per OP) utilizzando Thread#sleep(int) direttamente durante l'EDT si bloccherebbe GUI fino al termine del ritardo.

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.border.Border; 
//based on HFOE http://stackoverflow.com/questions/5414177/change-size-of-jpanel-using-cardlayout/5414770#5414770 
public class MultiSizedPanels { 

    private static void createAndShowUI() { 
     final CardLayout cardLayout = new CardLayout(); 
     final JPanel cardHolder = new JPanel(cardLayout); 
     final JFrame frame = new JFrame("MultiSizedPanels"); 
     JLabel[] labels = { 
      new JLabel("Small Label", SwingConstants.CENTER), 
      new JLabel("Medium Label", SwingConstants.CENTER), 
      new JLabel("Large Label", SwingConstants.CENTER)}; 

     for (int i = 0; i < labels.length; i++) { 
      int padding = 50; 
      Dimension size = labels[i].getPreferredSize(); 
      size = new Dimension(size.width + 2 * (i + 1) * padding, size.height + 2 * (i + 1) * padding); 
      labels[i].setPreferredSize(size); 
      Border lineBorder = BorderFactory.createLineBorder(Color.blue); 
      labels[i].setBorder(lineBorder); 
      JPanel containerPanel = new JPanel(); 
      if (i == 1) { 
       containerPanel.setPreferredSize(new Dimension(300, 200)); 
       containerPanel.add(labels[i], BorderLayout.CENTER); 
       cardHolder.add(containerPanel, String.valueOf(i)); 
      } else if (i == 2) { 
       containerPanel.setPreferredSize(new Dimension(600, 400)); 
       containerPanel.add(labels[i], BorderLayout.CENTER); 
       cardHolder.add(containerPanel, String.valueOf(i)); 
      } else { 
       containerPanel.setPreferredSize(new Dimension(800, 600)); 
       containerPanel.add(labels[i], BorderLayout.CENTER); 
       cardHolder.add(containerPanel, String.valueOf(i)); 
      } 
     } 
     JButton nextButton = new JButton("Next"); 
     nextButton.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       cardLayout.next(cardHolder); 
       Dimension dim = new Dimension(); 
       for (Component comp : cardHolder.getComponents()) { 
        if (comp.isVisible() == true) { 
         dim = comp.getPreferredSize(); 
        } 
       } 
       frame.setPreferredSize(dim); 
       java.awt.EventQueue.invokeLater(new Runnable() { 

        public void run() { 
         frame.pack(); 
        } 
       }); 
      } 
     }); 
     JPanel btnHolder = new JPanel(); 
     btnHolder.add(nextButton); 

     frame.add(cardHolder, BorderLayout.CENTER); 
     frame.add(btnHolder, BorderLayout.SOUTH); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocation(150, 150); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 
} 
+0

-1 per l'uso eccessivo di setPrefSize: la regola generale è (come ben sai :-) risolvere i problemi di dimensionamento usando un appropriato LayoutManager. Se non trovi quello che fa ciò che vuoi, scrivi/regola un LayoutManager che ... – kleopatra

0
Try this code this may help you. 




protected void paintComponent(Graphics g) { 
if (getModel().isArmed()) { 
     g.setColor(Color.lightGray); 
} else { 
    g.setColor(getBackground()); 
} 
g.fillOval(0, 0, getSize().width-1, getSize().height-1); 
System.out.println("width is "+getSize().width+"height is "+getSize().height); 
super.paintComponent(g); 
} 
protected void paintBorder(Graphics g) { 
g.setColor(getForeground()); 
g.drawOval(0, 0, getSize().width-1, getSize().height-1); 
} 
Shape shape; 
public boolean contains(int x, int y) { 
if (shape == null || !shape.getBounds().equals(getBounds())) { 
    shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight()); 
} 
return shape.contains(x, y); 
}} 
Problemi correlati