2012-05-07 11 views
11

Se si crea un JScrollPane con una finestra più grande del componente JScrollPane, viene visualizzato quel componente in alto a sinistra.Oscillazione: creazione di un JScrollPane che visualizza il componente centrato?

C'è un modo per modificare questo comportamento in modo che venga visualizzato il componente centrato?

programma di esempio di seguito.


chiarimento:

ho un componente che ha (larghezza, altezza) = (cw, ch).

Ho un JScrollPane con una finestra che ha (larghezza, altezza) = (vw, vh).

Il componente potrebbe diventare più grande o più piccolo. Vorrei un modo per utilizzare le barre di scorrimento per posizionare il punto centrale del componente rispetto al punto centrale della finestra, quindi se una o entrambe le dimensioni del componente sono più piccole della finestra, il componente viene visualizzato al centro della finestra.

Il comportamento di scorrimento predefinito posiziona l'angolo in alto a sinistra del componente rispetto all'angolo in alto a sinistra della finestra.

Tutto quello che sto chiedendo è come cambiare il punto di riferimento. Non sono sicuro di quanto sia facile farlo con il JScrollPane predefinito, quindi se non è facile, imparerò cosa posso e penso a un approccio diverso.


package com.example.test.gui; 

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.geom.AffineTransform; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JSpinner; 
import javax.swing.SpinnerNumberModel; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SimpleScroller extends JFrame { 
    static class Thingy extends JPanel 
    { 
     private double size = 20.0; 

     @Override public Dimension getPreferredSize() { 
      int isize = (int) this.size; 
      return new Dimension(isize, isize); 
     } 
     @Override protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      int[] x = {0, 100, 100, 0, 0, 75, 75, 25, 25, 50}; 
      int[] y = {0, 0, 100, 100, 25, 25, 75, 75, 50, 50}; 

      Graphics2D g2d = (Graphics2D) g; 
      AffineTransform at0 = g2d.getTransform(); 
      g2d.scale(size/100, size/100); 
      g.drawPolyline(x, y, x.length); 
      g2d.setTransform(at0); 
     } 
     public void setThingySize(double size) { 
      this.size = size; 
      revalidate(); 
      repaint(); 
     } 
     public double getThingySize() { return this.size; } 
    } 

    public SimpleScroller(String title) { 
     super(title); 
     final Thingy thingy = new Thingy(); 
     setLayout(new BorderLayout());  
     add(new JScrollPane(thingy), BorderLayout.CENTER); 

     final SpinnerNumberModel spmodel = 
      new SpinnerNumberModel(thingy.getThingySize(), 
       10.0, 2000.0, 10.0); 
     spmodel.addChangeListener(new ChangeListener() { 
      @Override public void stateChanged(ChangeEvent e) { 
       thingy.setThingySize((Double) spmodel.getNumber()); 
      }   
     }); 
     add(new JSpinner(spmodel), BorderLayout.NORTH); 
    } 
    public static void main(String[] args) { 
     new SimpleScroller("simple scroller").start(); 
    } 
    private void start() { 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 
} 
+0

Per favore, pubblica il Codice, con il quale stai tirando i capelli :-). Grazie a Dio, per questo "Non sto tirando i miei capelli (ancora)", Esempio sarà buono, qualcosa da provare, sarà molto apprezzato :-) –

+0

Non mi sto ancora strappando i capelli (e ancora) Voglio che inserisca il codice che ho, ma posso fare un esempio. –

+0

vuoi dipingere questo serpente al centro del JScrollPane – mKorbel

risposta

12
  1. mettere un JPanel nel scroll-riquadro
  2. Impostare il layout del pannello per un GridBagLayout.
  3. Inserire un componente nel pannello senza vincoli. Sarà centrato.

Questa è la tecnica utilizzata nello Nested Layout Example, che colloca l'immagine rosso/arancione nel centro del genitore.

+0

Penso che OP voglia dipingere qualcosa su JViewport e magari impostare questo qualcosa sul Punto desiderato – mKorbel

+0

Non voglio dipingere sul JViewport, almeno non direttamente - Il mio codice reale è un componente derivato da JPanel, come nel mio esempio, ma ha anche altri elementi della GUI. –

+0

@Andrew Thompson (@Jason S) è un OP comune con domande troppo ampie :-) – mKorbel

4

ho semplicemente aggiunto un JPanel al JScrollPane a cui ho aggiunto il THINGY JPanel. Spero che questo è quello che si voleva:

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.geom.AffineTransform; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JSpinner; 
import javax.swing.SpinnerNumberModel; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class SimpleScroller extends JFrame { 
    static class Thingy extends JPanel 
    { 
     private double size = 20.0; 

     @Override public Dimension getPreferredSize() { 
      int isize = (int) this.size; 
      return new Dimension(isize, isize); 
     } 
     @Override protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      int[] x = {0, 100, 100, 0, 0, 75, 75, 25, 25, 50}; 
      int[] y = {0, 0, 100, 100, 25, 25, 75, 75, 50, 50}; 

      Graphics2D g2d = (Graphics2D) g; 
      AffineTransform at0 = g2d.getTransform(); 
      g2d.scale(size/100, size/100); 
      g.drawPolyline(x, y, x.length); 
      g2d.setTransform(at0); 
     } 
     public void setThingySize(double size) { 
      this.size = size; 
      revalidate(); 
      repaint(); 
     } 
     public double getThingySize() { return this.size; } 
    } 

    public SimpleScroller(String title) { 
     super(title); 
     final Thingy thingy = new Thingy(); 
     setLayout(new BorderLayout()); 
     JPanel panel = new JPanel(); 
     panel.add(thingy); 
     JScrollPane scroll = new JScrollPane(); 
     scroll.setViewportView(panel); 
     add(scroll, BorderLayout.CENTER); 

     final SpinnerNumberModel spmodel = 
      new SpinnerNumberModel(thingy.getThingySize(), 
       10.0, 2000.0, 10.0); 
     spmodel.addChangeListener(new ChangeListener() { 
      @Override public void stateChanged(ChangeEvent e) { 
       thingy.setThingySize((Double) spmodel.getNumber()); 
      }   
     }); 
     add(new JSpinner(spmodel), BorderLayout.NORTH); 
    } 
    public static void main(String[] args) { 
     new SimpleScroller("simple scroller").start(); 
    } 
    private void start() { 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     pack(); 
     setVisible(true); 
    } 
} 

Ecco l'output:

SIMPLE SCROLLER

+1

+1 ... che funziona esattamente come Voglio che funzioni nella dimensione orizzontale, ma non nella dimensione verticale. –

3

accettare la vostra entrambi i commenti, ma

sì ...anche se mi piacerebbe molto per posizionare arbitrariamente si

ci sono

metodi importanti per evitare lo sfarfallio o saltare sul JViewport

JViewport.setScrollMode (JViewport .BLIT_SCROLL_MODE); JViewport.setScrollMode (JViewport.BACKINGSTORE_SCROLL_MODE); JViewport.setScrollMode (JViewport.SIMPLE_SCROLL_MODE);

  • uso GlassPane (è molto semplice da impostare per possition al punto desiderato e/o Dimmension)

e

Non voglio dipingere al JViewport, a almeno non direttamente - Il mio codice reale è un componente sottoclasse da JPanel, come nel mio esempio, ma ha anche altri elementi della GUI in esso.

  • è possibile utilizzare JXLayer (java6) o parti di metodi da JXLayer attuate per il JLayer (Java7) direttamente

  • potrebbe essere troppo duro, ma in tutti i casi è possibile sovrapporre qualunque con JLabel

Avviso

tutto il mio suggerimento per consumare MouseEvent per impostazione predefinita, J (X) Strato e JLabel con KeyEvents troppo, ma non c'è alcun problema con gli eventi rispedizione da ---> ad un altro JComponent

EDIT

attesa: no, non voglio dipingere la spirale (quello che hai chiamato "serpente") nel centro di JScrollPane; Voglio dipingere il mio componente e visualizzare il mio componente al centro di JScrollPane.

  • tuoi JPanel potrebbe essere più ampio di quello JViewport di default

a) JPanel ritorna Dimension

b) JViewport tornare Dimension

  • quindi senza alcun problema, sfarfallio o freeze

a) è possibile centrare Dimmension da JPanel (Point) al centro di JViewport (Point)

b) se c'è JComponent è possibile spostare il JViewport a qualsiasi getBounds() tha restituito JComponent o Punto da JPanel dentro JScrollPane

3

Con il suggerimento di Andrew, non è possibile avere la vista più piccola della vista (e ancora centrata).

Il modo più pulito è farlo direttamente dal gestore di layout, ignorando ViewportLayout. C'è un'implementazione nella fonte di:

http://www.randelshofer.ch/multishow

Cercare la classe ZoomableViewportLayout, che fa il lavoro perfettamente.

Problemi correlati