2013-08-21 18 views
6
  • come attaccare JLabel in GlassPane a rellative, galleggiante coordinate da JProgressBar senza utilizzare ComponentListener o altro ascoltatore,Layout Manager e Posizionamento

  • C'è built_in notificanti LayoutManagers standard che è possibile notificare suo stato interno, e può essere accessibile per la sostituzione, invece il mio tentativo con ComponentListener e NullLayout

enter image description here

.

enter image description here

SSCCE circa ComponentListener e con NullLayout

import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.GridBagConstraints; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import javax.swing.JButton; 
import javax.swing.JCheckBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JProgressBar; 
import javax.swing.JRadioButton; 
import javax.swing.UIManager; 
//http://stackoverflow.com/questions/14560680/jprogressbar-low-values-will-not-be-displayed 
public class ProgressSample { 

    private JFrame frame = new JFrame("GlassPane instead of JLayer"); 
    private JLabel label; 
    private GridBagConstraints gbc = new GridBagConstraints(); 
    private JProgressBar progressSeven; 

    public ProgressSample() { 
     frame.setLayout(new FlowLayout()); 
     frame.add(new JButton("test")); 
     frame.add(new JCheckBox("test")); 
     frame.add(new JRadioButton("test")); 
     // Nothing is displayed if value is lover that 6 
     JProgressBar progressSix = new JProgressBar(0, 100); 
     progressSix.setValue(2); 
     frame.add(progressSix); 
     // but this works value is higher that 6 
     progressSeven = new JProgressBar(0, 100); 
     progressSeven.addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentMoved(ComponentEvent e) { 
       label.setBounds(
         (int) progressSeven.getBounds().getX(), 
         (int) progressSeven.getBounds().getY(), 
         progressSeven.getPreferredSize().width, 
         label.getPreferredSize().height); 
      } 
     }); 
     progressSeven.setValue(7); 
     frame.add(progressSeven); 
     label = new JLabel(); 
     label.setText("<html>Blablabla, Blablablabla<br>" 
       + "Blablabla, Blablablabla<br>" 
       + "Blablabla, Blablablabla</html>"); 
     label.setPreferredSize(new Dimension(
       progressSeven.getPreferredSize().width, 
       label.getPreferredSize().height)); 
     Container glassPane = (Container) frame.getRootPane().getGlassPane(); 
     glassPane.setVisible(true); 
     glassPane.setLayout(null); 
     glassPane.add(label, gbc); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     ProgressSample dialogTest = new ProgressSample(); 
    } 
} 
+1

+1 per 'SSCCE' ... – Reimeus

+1

' layoutContainer() 'possono essere ignorate per sparare un evento che potrebbe essere ascoltato da un gestore di layout personalizzato per la lastra di vetro. Non sono sicuro se è quello che vuoi. – kiheru

+0

_non utilizzare ComponentListener o un altro listener_ quale strano requisito, compiti a casa? kleopatra

risposta

5

come attaccare JLabel in GlassPane a rellative, coordinate da JProgressBar galleggiante senza utilizzare ComponentListener o altro ascoltatore

La mia idea sarebbe quella di avvolgere il t wo componenti in un contenitore con OverlayLayout e "riproduci" con AlignementX/AlignementY per le relative coordinate. Quindi metti il ​​contenitore di wrapping nella gerarchia originale. (Vedi la mia SSCCE sotto)

c'è built_in notificanti in LayoutManagers standard che può notificare sul suo stato interno, e può essere accessibile per la sostituzione, invece mio tentativo con ComponentListener e NullLayout

Ci non è un simile contratto nell'API LayoutManager, quindi non è possibile fare affidamento in modo sicuro su tali meccanismi. Inoltre, dovrai affrontare problemi con LayoutManager standard perché prenderanno in considerazione il tuo extra JLabel nel layout.

Immagina di utilizzare FlowLayout e di inserire 1 componente, quindi il tuo JLabel aggiuntivo, quindi un altro componente. Quando sposti l'extra JLabel l'ultimo componente rimarrà "lontano" dal primo componente e vedrai uno spazio vuoto tra questi due.

Se quest'ultimo problema non è un problema, si può semplicemente estendere FlowLayout (o qualsiasi altro LayoutManager), ignorare layoutContainer e posizionare l'extra JLabel dove vuoi.

import java.awt.Container; 
import java.awt.FlowLayout; 
import java.awt.GridBagConstraints; 

import javax.swing.JButton; 
import javax.swing.JCheckBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.JRadioButton; 
import javax.swing.OverlayLayout; 
import javax.swing.UIManager; 

//http://stackoverflow.com/questions/14560680/jprogressbar-low-values-will-not-be-displayed 
public class ProgressSample { 

    private JFrame frame = new JFrame("GlassPane instead of JLayer"); 
    private JLabel label; 
    private GridBagConstraints gbc = new GridBagConstraints(); 
    private JProgressBar progressSeven; 

    public ProgressSample() { 
     frame.setLayout(new FlowLayout()); 
     frame.add(new JButton("test")); 
     frame.add(new JCheckBox("test")); 
     frame.add(new JRadioButton("test")); 
     // Nothing is displayed if value is lover that 6 
     JProgressBar progressSix = new JProgressBar(0, 100); 
     progressSix.setValue(2); 
     frame.add(progressSix); 
     JPanel wrappingPanel = new JPanel(); 
     OverlayLayout mgr = new OverlayLayout(wrappingPanel); 
     wrappingPanel.setLayout(mgr); 
     progressSeven = new JProgressBar(0, 100); 
     progressSeven.setAlignmentX(0.0f); 
     progressSeven.setAlignmentY(0.0f); 
     frame.add(wrappingPanel); 
     label = new JLabel(); 
     label.setText("<html>Blablabla, Blablablabla<br>" + "Blablabla, Blablablabla<br>" + "Blablabla, Blablablabla</html>"); 
     label.setAlignmentX(0.0f); 
     label.setAlignmentY(0.0f); 
     wrappingPanel.add(label); 
     wrappingPanel.add(progressSeven); 
     Container glassPane = (Container) frame.getRootPane().getGlassPane(); 
     glassPane.setVisible(true); 
     glassPane.setLayout(new FlowLayout()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     try { 
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     ProgressSample dialogTest = new ProgressSample(); 
    } 
} 
+0

+1 hmmm sono d'accordo, probabilmente rispondendo alla mia domanda ....., quindi meglio, più sicuro potrebbe essere utilizzato [JProgressBar come contenitore (come sempre per me)] (http: // StackOverflow.it/a/18355235/714968), ma questa domanda si basa sulle mie conoscenze mancate sul codice postato lì come risposta, – mKorbel

+0

@mKorbel C'è uno svantaggio di usare 'JProgressBar' come un contenitore: la barra di avanzamento si estenderà sull'intero i limiti forniti così sembra piuttosto strano. I limiti –

+0

sono effetti collaterali, causati dal LayoutManager utilizzato, ad es. GBC ha causato lo stesso problema per JPanel, hai ragione non è standard in Swing, abbastanza requisiti in Htlm5/JavaFX – mKorbel