2015-05-12 14 views
12

Creazione di una nuova interfaccia grafica in Java (1.8) Altalena, Cerco un modo per ignorare ridimensionare il comportamento di tutti i miei componenti.Come controllare dinamicamente componenti auto-ridimensionamento in Java Swing

Mi spiego a voi con alcune foto modificate:

1. Full Screen GUI

Questa è la mia GUI a schermo intero, con 3 pannelli e un JToolBar. Quella verde deve avere una dimensione fissa, gli altri sarebbero ridimensionabile.

Attualmente, ho solo 2 piccoli GridLayout per organizzarli (uno verticale e uno orizzontale per i pannelli verdi e cyan).

FullScreen GUI

2. Piccolo ridimensionamento orizzontale

Se io, per esempio, ridurre le dimensioni della cornice dal lato destro, voglio che il mio pannello blu e ciano ad essere ridimensionate secondo il nuovo telaio dimensione. Ma il pannello verde deve essere corretto. (Non è la parte più difficile credo.)

Resized once GUI

3. Dimensione minima orizzontale

Questa è la parte più difficile per me. Non appena il ciano (o blu) portata pannello è formato minimo, voglio che "spinta" il pannello verde a sinistra, anche se scompare dal telaio.

Naturalmente, tirando il fotogramma a destra farà il pannello verde appaiono nuovamente.

Minimum size of the GUI

Come potrei farlo?

Ho pensato di utilizzare JSplitPane o un listener specifico per decidere manualmente il comportamento di ridimensionamento ma ho bisogno di qualche consiglio.

Scusate se un post esistente può rispondere a questa, non ho trovato alcuna risposta che spiega il problema per me.

Grazie in anticipo!


Se volete maggiori esempi, guardano il software "Evernote", che si comporta allo stesso modo

+1

Ottima spiegazione del comportamento che stai cercando. Potresti hackerare qualcosa insieme a 'ComponentListener' ma probabilmente non è un buon modo per farlo. Spero che qualcuno con più esperienza di me veda questo e conosca un modo migliore. – Radiodef

risposta

7

L'impostazione della dimensione massima/minima/preferita del pannello Green può mantenere quel pannello delle stesse dimensioni alla prima condizione. Per verificare il ridimensionamento, è possibile utilizzare uno ComponentListener su uno degli altri JPanel - se la dimensione scende sotto una larghezza particolare, quindi modificare la dimensione massima/minima/preferita del pannello Green.

Ecco un esempio messo insieme di fare questo - ridimensiona il pannello Green quando il Blue è < 600, e il ridimensionamento è un ridimensionamento ponderata (30% della larghezza totale). Per ottenere il vero L & F e che desideri, potresti dover giocare con il layout/le dimensioni.

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.Rectangle; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import java.awt.event.ComponentListener; 

import javax.swing.Box; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JToolBar; 
import javax.swing.SwingUtilities; 


public class GridTest extends JPanel{ 

    private boolean changeAllowed = false; 
    //keep reference to cyan for the height dimension 
    final JPanel cyan = new JPanel(); 

    public GridTest(){ 
     cyan.setPreferredSize(new Dimension(600, 300));//provide sizing hint 
    } 

    private Dimension getCustomDimensions(){ 
     if (changeAllowed){ 
      return new Dimension((int)(super.getParent().getBounds().width * 0.3), cyan.getBounds().height); 
     }else{ 
      return new Dimension(200, cyan.getBounds().height); 
     } 
    } 
    @Override 
    public Dimension getMaximumSize(){ 
     return getCustomDimensions(); 
    } 
    @Override 
    public Dimension getMinimumSize(){ 
     return getCustomDimensions(); 
    } 
    @Override 
    public Dimension getPreferredSize(){ 
     return getCustomDimensions(); 
    } 

    public static void main(String[] args) throws Exception{ 
     SwingUtilities.invokeAndWait(new Runnable(){ 

      @Override 
      public void run() { 
       final int MINIMUM = 600; 
       JFrame frame = new JFrame(); 
       frame.add(new JToolBar(), BorderLayout.NORTH); 
       final JPanel blue = new JPanel(); 

       final GridTest green = new GridTest(); 
       green.setBackground(Color.green); 
       green.setOpaque(true); 

       green.cyan.setBackground(Color.cyan); 
       green.cyan.setOpaque(true); 
       blue.setOpaque(true); 
       blue.setBackground(Color.blue); 
       blue.setPreferredSize(new Dimension(900, 300));//hint at size 
       blue.setMinimumSize(new Dimension(100, 200));//hint at size 
       //Nest Box Layouts 
       Box top = Box.createHorizontalBox(); 
       top.add(blue); 
       Box bottom = Box.createHorizontalBox(); 
       bottom.add(green); 
       bottom.add(green.cyan); 
       Box vert = Box.createVerticalBox(); 
       vert.add(top); 
       vert.add(bottom); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(vert); 
       //listen for resizes 
       blue.addComponentListener(new ComponentAdapter(){ 

        @Override 
        public void componentResized(ComponentEvent e) { 
         if (blue.getBounds().width < MINIMUM){//set flag 
          green.changeAllowed = true; 
         }else{ 
          green.changeAllowed = false; 
         } 
        } 
       }); 

       frame.pack(); 
       frame.setSize(800, 600); 
       frame.setVisible(true); 

      } 

     }); 
    } 
} 
+0

Grazie mille per questo, anche se trovo molto strano mettere il pannello ciano nel pannello di classe verde, lo userò per fare esattamente quello che voglio! – Kapcash

2

Questo è come lo faccio e io non sono sicuro che questo è il modo corretto:

Prima imposta il layout su null.

successivo creare un evento ridimensionata componenti per il telaio:

addComponentListener(new ComponentAdapter(){ 
      public void componentResized(ComponentEvent e){ 
      } 
     }); 

All'interno qui è possibile modificare manualmente i componenti come viene ridimensionata.Ho fatto questo per alcuni dei miei programmi per mantenere un riquadro di scorrimento a sinistra e a destra del fotogramma sempre della stessa larghezza e avere tutto il resto della dimensione su e giù come ridimensionato.

+0

'Non sono sicuro che questo sia il modo corretto:' - non utilizzare layout nulli. Swing è stato progettato per essere utilizzato con i gestori di layout. – camickr

3

questo dovrebbe essere facile con un GridBagLayout, a condizione di impostare le dimensioni minime appropriata per i componenti verdi e ciano:

setLayout(new GridBagLayout()); 
green.setMnimumSize(new Dimension(0, 0)); 
cyan.setMinimumSize(new Dimension(100, 100)); // whatever fits 
add(blue, new GridBagConstraints(0, 0, 2, 1, 
     1.0, 0.0, 
     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, 
     new Insets(0, 0, 0, 0), 0, 0); 
add(green, new GridBagConstraints(0, 1, 1, 1, 
     0.0, 0.0, 
     GridBagConstraints.WEST, GridBagConstraints.NONE, 
     new Insets(0, 0, 0, 0), 0, 0); 
add(cyan, new GridBagConstraints(1, 1, 1, 1, 
     1.0, 0.0, 
     GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, 
     new Insets(0, 0, 0, 0), 0, 0); 

Specificando un x peso per ciano e componente blu così come l'impostazione di ridimensionamento = ORIZZONTALE hanno ridimensionare con il contenitore.

2

È possibile utilizzare un BoxLayout per contenere il pannello verde e quello ciano. A BoxLayout rispetta le dimensioni minima e massima di un componente. Così per il pannello verde si imposta allora la dimensione massima pari alla dimensione preferita e per il pannello ciano si imposta la dimensione minima pari alla dimensione preferita:

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

public class SSCCE extends JPanel 
{ 
    public SSCCE() 
    { 
     JPanel blue = new JPanel(); 
     blue.setBackground(Color.BLUE); 
     blue.setPreferredSize(new Dimension(500, 100)); 

     Box box = Box.createHorizontalBox(); 

     JPanel green = new JPanel(); 
     green.setBackground(Color.GREEN); 
     green.setPreferredSize(new Dimension(200, 100)); 
     green.setMaximumSize(green.getPreferredSize()); 
     box.add(green); 

     JPanel cyan = new JPanel(); 
     cyan.setBackground(Color.CYAN); 
     cyan.setPreferredSize(new Dimension(300, 100)); 
     cyan.setMinimumSize(cyan.getPreferredSize()); 
     box.add(cyan); 

     setLayout(new BorderLayout()); 
     add(blue, BorderLayout.NORTH); 
     add(box, BorderLayout.CENTER); 
    } 

    private static void createAndShowGUI() 
    { 
     JFrame frame = new JFrame("SSCCE"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new SSCCE()); 
     frame.setLocationByPlatform(true); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) 
    { 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 

Naturalmente la soluzione corretta è quella di ignorare il getMaximumSize() e getMinimumSize() metodi rispettivamente di ciascun pannello per restituire semplicemente la dimensione preferita del pannello.

+0

Grazie mille per questo, anche questo è utile! – Kapcash

+0

@Kapcash, non sono sicuro del motivo per cui non ti piace questo approccio. Si tratta di un approccio di layout puro in modo da non scrivere alcun codice di layout personalizzato. La soluzione accettata in pratica reinventa la ruota cercando di richiamare il codice di layout personalizzato utilizzando ComponentListener. Non solo è necessario creare e gestire oggetti booleani, il codice di layout è incorporato nell'intera classe. – camickr

+0

L'altro modo mi consente di definire tutto ciò di cui ho bisogno da solo, non solo per il problema reale che ho avuto. Assicurati che userò anche la tua soluzione, ma stavo aspettando qualcosa come il componente Listener che può fare molte più cose di un BoxLayout che conosco già. Non essere deluso, ti ringrazio tanto quanto "Copeg". – Kapcash

0

La sequenza importante è questo:

   frame.revalidate(); 
       frame.pack(); 
       frame.repaint(); 
  1. revalidate(): invalida i componenti fino alla radice vicina successivamente il componente gerarchia viene convalidato partire dalla radice validate vicina.
  2. pacchetto(): consente di dimensionare la finestra per adattarla alle dimensioni e ai layout preferiti dei relativi sottocomponenti. La larghezza e l'altezza risultanti della finestra vengono automaticamente ingrandite.
  3. ripetizioni(): dopo tutti questi ricalcoli, il riverniciare mostra i componenti.

Utilizzare questa sequenza dopo ogni serie di modifiche, è stato fatto nel codice e si desidera vedere i risultati visualizzati sullo schermo.

Mi piace il java.awt.GridBagLayout in combinazione con i java.awt.GridBagConstraints e usare questa disposizione su tutti i contenitori a partire dal pannello di contenuto.

Se si aggiunge un contenitore in un altro contenitore, utilizzare un layout su ciascuno di essi, altrimenti il ​​calcolo non riesce a causa di un layout mancante nella gerarchia.

+0

Grazie, ma le mie domande sono state risolte mesi fa. E non riguardava la sequenza rinfrescante di un componente, ma solo la controlabillity. – Kapcash

Problemi correlati