2012-02-07 16 views
7

Ho un JPanel (giallo) inserito in JScrollPane.Perché il mio JPanel all'interno di un JScrollPane non scorre?

pic1

Quando entro un certo testo in JTextPane, si ridimensiona, ma la barra di scorrimento verticale non è ancora attivo. yelowPanel.getSize() restituisce lo stesso valore di prima. (Puoi vederlo su redPanel).

pic2

Così come posso aggiornare yellowPanel? Voglio scorrere il pannello verticalmente. Ho cercato di:

panelCreating.revalidate(); 
panelCreating.invalidate(); 
panelCreating.repaint(); 

funziona solo panelCreating.setPreferredSize(new Dimension(333, 777)); ma non so cosa dimensioni per impostare. Dipende dal contenuto.

C'è un piccolo esempio:

package swingtest; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.BorderFactory; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextPane; 

public class SwingTest extends JFrame { 

    public SwingTest() { 
     initComponents(); 
    } 

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

      @Override 
      public void run() { 
       new SwingTest().setVisible(true); 
      } 
     }); 
    } 
    private JPanel panelCenter, panelCreating; 
    private JScrollPane scrollPaneCreating, scrollPaneCenter; 
    private JTextPane textPane1, textPane2; 
    private JButton button1; 

    private void initComponents() { 
     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     setMinimumSize(new Dimension(300, 300)); 

     panelCreating = new JPanel(); 
     panelCreating.setMinimumSize(new Dimension(160, 200)); 
     panelCreating.setPreferredSize(new Dimension(160, 200)); 
     scrollPaneCreating = new JScrollPane(panelCreating, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 

     textPane1 = new JTextPane(); 
     textPane1.setText("a\na"); 
     textPane2 = new JTextPane(); 
     textPane2.setText("b\nb"); 
     button1 = new JButton("+++"); 

     panelCenter = new JPanel(); 
     panelCenter.setBackground(Color.blue); 
     scrollPaneCenter = new JScrollPane(panelCenter); 



     // ----------------- Left Panel Init ----------------------- 

     panelCreating.setLayout(new GridBagLayout()); 
     panelCreating.setBackground(Color.ORANGE); 
     panelCreating.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); 

     GridBagConstraints c = new GridBagConstraints(); 
     c.insets = new Insets(0, 0, 4, 4); 
     c.anchor = GridBagConstraints.FIRST_LINE_START; 
     c.weightx = c.weighty = 0; 

     c.gridx = 0; 
     c.gridy = GridBagConstraints.RELATIVE; 
     c.gridwidth = GridBagConstraints.REMAINDER; 
     c.gridheight = 1; 
     c.fill = GridBagConstraints.BOTH; 
     panelCreating.add(textPane1, c); 

     button1.addActionListener(new ActionListener() { 

      int height = 50; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       textPane1.setText(textPane1.getText() + "\na"); 
       textPane1.setPreferredSize(new Dimension(150, height)); 
       textPane2.setText(textPane2.getText() + "\nb"); 
       textPane2.setPreferredSize(new Dimension(150, height)); 
       height += 30; 

       panelCreating.revalidate(); 
       panelCreating.repaint(); 
       scrollPaneCreating.revalidate(); 
      } 
     }); 
     panelCreating.add(button1, c); 

     panelCreating.add(textPane2, c); 

     // ------------------------------------------------------- 

     getContentPane().setLayout(new GridBagLayout()); 
     c = new GridBagConstraints(); 

     c.ipadx = c.ipady = 0; 
     c.insets = new Insets(0, 0, 0, 0); 
     c.weighty = 0; 
     c.gridheight = 1; 
     c.gridx = 0; 
     c.gridy = 1; 
     c.gridwidth = 1; 
     c.weightx = 0; 
     c.fill = GridBagConstraints.BOTH; 
     getContentPane().add(scrollPaneCreating, c); 


     c.gridx = 1; 
     c.gridy = 1; 
     c.fill = GridBagConstraints.BOTH; 
     c.weightx = 1; 
     c.weighty = 1; 
     getContentPane().add(scrollPaneCenter, c); 

    } 
} 

pannello giallo utilizza anche GridBagLayout. Ci scusiamo per il mio inglese

+2

Perché la barra di scorrimento orizzontale si abilita quando i componenti all'interno crescono solo verticalmente? Per favore includi un [sscce] (http://www.sscce.org) perché non è chiaro cosa stai chiedendo (almeno a me). – mre

+0

scusate, voglio dire scrollbar verticale .. – alaster

+1

@alaster per favore puoi modificare il tuo post con il codice in http://sscce.org/ form, perché questo potrebbe essere una lezione sul perchè JScrollPane non funziona usando AbsoluteLayout, +1 per documentando questo strano numero – mKorbel

risposta

5

Invece di impostare una dimensione preferita su panelCreating, appoggiarla su scrollPaneCreating. E non impostare una dimensione preferita sui componenti del testo, cresceranno man mano che aggiungi nuove righe di testo. L'idea è di fare in modo che il pannello all'interno del riquadro di scorrimento cresca quanto necessario e limitare le dimensioni del riquadro di scorrimento stesso.

// [...] 

    panelCreating = new JPanel(); 
    //panelCreating.setMinimumSize(new Dimension(160, 200)); 
    //panelCreating.setPreferredSize(new Dimension(160, 200)); 
    scrollPaneCreating = new JScrollPane(panelCreating, 
     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
     JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
    scrollPaneCreating.setMinimumSize(new Dimension(160, 200)); 
    scrollPaneCreating.setPreferredSize(new Dimension(160, 200)); 

    // [...] 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      textPane1.setText(textPane1.getText() + "\na"); 
      //textPane1.setPreferredSize(new Dimension(150, height)); 
      textPane2.setText(textPane2.getText() + "\nb"); 
      //textPane2.setPreferredSize(new Dimension(150, height)); 
      //height += 30; 

      // This isn't necessary either 
      //panelCreating.revalidate(); 
      //panelCreating.repaint(); 
      //scrollPaneCreating.revalidate(); 
     } 

A cura di aggiungere: un'altra alternativa è quella di impostare la dimensione del JViewport che è collegato al pannello di scorrimento. Il viewport è dove viene visualizzato il contenuto. È possibile pensare al riquadro di scorrimento come composto dalla vista più le barre di scorrimento. Se il riquadro di scorrimento è impostato su una dimensione fissa, la dimensione del viewport viene determinata sottraendo la dimensione della barra di scorrimento. Ma se il viewport è impostato su una dimensione fissa, la dimensione del riquadro di scorrimento viene determinata aggiungendo la dimensione della barra di scorrimento alla dimensione del viewport. È preferibile impostare una dimensione fissa sul viewport se si desidera controllare con precisione la quantità di contenuto da visualizzare sullo schermo, poiché le dimensioni della barra di scorrimento possono variare a seconda del sistema operativo.

scrollPaneCreating.getViewport().setMinimumSize(new Dimension(160, 200)); 
scrollPaneCreating.getViewport().setPreferredSize(new Dimension(160, 200)); 
+0

Questo è stato un mio errore e non ho nemmeno bisogno di cambiare il layout. Grazie – alaster

4

Il layout predefinito di JPanel è FlowLayout. Prova invece a GridLayout. C'è un esempio correlato here. Ad esempio,

panelCreating = new JPanel(new GridLayout()); 
scrollPaneCreating = new JScrollPane(panelCreating); 

Addendum: considerare anche i layout nidificati. L'esempio seguente utilizza BoxLayout per il pannello di sinistra.

enter image description here

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.GridLayout; 
import javax.swing.BorderFactory; 
import javax.swing.Box; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextPane; 

/** @see https://stackoverflow.com/questions/9184476 */ 
public class SwingTest extends JFrame { 

    private static final int N = 8; 

    public SwingTest() { 
     initComponents(); 
    } 

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

      @Override 
      public void run() { 
       new SwingTest().setVisible(true); 
      } 
     }); 
    } 
    private JPanel panelCenter, panelCreating; 
    private JScrollPane scrollPaneCreating, scrollPaneCenter; 

    private void initComponents() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     panelCreating = new JPanel(); 
     scrollPaneCreating = new JScrollPane(panelCreating, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 

     panelCenter = new JPanel(); 
     panelCenter.setBackground(Color.blue); 
     scrollPaneCenter = new JScrollPane(panelCenter); 

     // ----------------- Left Panel Init ----------------------- 
     panelCreating.setLayout(new BoxLayout(panelCreating, BoxLayout.Y_AXIS)); 
     panelCreating.setBackground(Color.orange); 
     panelCreating.setBorder(BorderFactory.createEmptyBorder(N, N, N, N)); 

     panelCreating.add(createTextPane()); 
     panelCreating.add(Box.createVerticalStrut(N)); 
     panelCreating.add(createTextPane()); 
     panelCreating.add(Box.createVerticalStrut(N)); 
     panelCreating.add(createTextPane()); 

     // ------------------------------------------------------- 
     setLayout(new GridLayout(1, 0)); 
     add(scrollPaneCreating); 
     add(scrollPaneCenter); 
     pack(); 
    } 

    private JTextPane createTextPane() { 
     JTextPane pane = new JTextPane(); 
     pane.setText("" 
      + "Twas brillig and the slithy toves\n" 
      + "Did gyre and gimble in the wabe;\n" 
      + "All mimsy were the borogoves,\n" 
      + "And the mome raths outgrabe."); 

     pane.setBorder(BorderFactory.createEmptyBorder(N, N, N, N)); 
     return pane; 
    } 
} 
+0

Sto usando solo GridBagLayout Pannello interno ed esterno Ma quando uso 'GridLayout' in SSCCE allegato, ho lo stesso problema .. – alaster

+0

Ho mostrato un approccio alternativo sopra. – trashgod

+0

bella alternativa + 1 – mKorbel

0

Ho risolto il problema aggiungendo 1 riga.

panelCreating.setPreferredSize(new Dimension((int) panelCreating.getPreferredSize().getWidth(), 
        (int)(panelCreating.getPreferredSize().getHeight()+30))); 

La riga deve essere inserita dopo le seguenti righe;

@Override 
     public void actionPerformed(ActionEvent e) { 
      textPane1.setText(textPane1.getText() + "\na"); 
      textPane1.setPreferredSize(new Dimension(150, height)); 
      textPane2.setText(textPane2.getText() + "\nb"); 
      textPane2.setPreferredSize(new Dimension(150, height)); 
      height += 30; 

Spiegazione: Il grid bag layout non impostare è riquadro preferito dimensioni quando si imposta la dimensione preferita dei textPanes al suo interno, ma lo ScrollPane solo scorre in base alla dimensione preferita del riquadro in esso. Quindi è necessario impostare la nuova dimensione preferita del riquadro ogni volta che si modifica la dimensione dei componenti al suo interno, quindi scrollPane saprà esattamente cosa deve fare. Questo è quello che ho fatto, aggiungere una linea che ha aumentato la dimensione preferita di creazionePanel, che è quella all'interno di scrollPanel

Problemi correlati