2012-05-07 22 views
11

Si crea un JScrollPane que tiene una ventana gráfica más grande que el componente de JScrollPane, muestra ese componente en la esquina superior izquierda.Swing: ¿creando un JScrollPane que muestra su componente centrado?

¿Hay alguna manera de cambiar este comportamiento para que se muestre el componente centrado?

ejemplo de programa a continuación.


aclaración:

I tiene un componente que tiene (anchura, altura) = (cw, ch).

Tengo un JScrollPane con una ventana que tiene (ancho, alto) = (vw, vh).

El componente puede agrandarse o reducirse. Me gustaría una forma de usar las barras de desplazamiento para ubicar el punto central del componente relativo al punto central de la ventana gráfica, por lo que si una o ambas dimensiones del componente son más pequeñas que la ventana gráfica, el componente aparece en el centro de la ventana gráfica.

El comportamiento del deslizamiento predeterminado posiciona la esquina superior izquierda del componente en relación con la esquina superior izquierda de la ventana gráfica.

Todo lo que estoy preguntando es cómo cambiar el punto de referencia. No estoy seguro de lo fácil que es esto con el JScrollPane predeterminado, así que si no es fácil, entonces aprenderé lo que puedo y pensaré en un enfoque diferente.


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

Por favor, publique el Código, con el cual está tirando de su cabello :-). Gracias a Dios, por eso "No me estoy tirando del pelo (todavía)", el ejemplo será bueno, algo para probar, será muy apreciado :-) –

+0

No me estoy tirando del pelo (todavía) y tú no " Quiero que publique el código que tengo, pero puedo dar un ejemplo. –

+0

¿quieres pintar esta serpiente en el centro del JScrollPane? – mKorbel

Respuesta

12
  1. Ponga una JPanel en el desplazamiento de una ventana
  2. Definir la presentación del panel a un GridBagLayout.
  3. Coloque un componente en el panel sin restricciones. Estará centrado.

Esta es la técnica utilizada en el Nested Layout Example, que coloca la imagen roja/naranja en el centro del elemento principal.

+0

Creo que OP quiere pintar algo para el JViewport y tal vez para configurar esto para el punto deseado – mKorbel

+0

No quiero pintar en el JViewport, al menos no directamente - Mi código real es un componente subclasificado de JPanel, como en mi ejemplo, pero también tiene otros elementos de la GUI. –

+0

@Andrew Thompson (@Jason S) es OP común con preguntas demasiado amplias :-) – mKorbel

4

simplemente he añadido un JPanel a la JScrollPane a la que añade el THINGY JPanel. Espero que esto es lo que quería:

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); 
    } 
} 

Aquí está la salida:

SIMPLE SCROLLER

+1

+1 ... que funciona exactamente cómo Quiero que funcione en la dimensión horizontal, pero no en la dimensión vertical. –

3

La aceptación de sus dos comentarios, pero

sí ...aunque me gusta mucho para posicionar de forma arbitraria que

hay

métodos importantes para evitar el parpadeo o saltar en el JViewport

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

  • uso GlassPane (es muy fácil de configurar para possition al punto deseado y/o Dimmension)

y

no quiero pintar a la JViewport, por lo al menos no directamente: mi código real es un componente subclasificado de JPanel, como en mi ejemplo, pero también tiene otros elementos de la GUI.

  • puede utilizar JXLayer (java6) o partes de métodos de JXLayer implementarse para la JLayer (Java7) directamente

  • podría ser demasiado duro, pero en todos los casos se puede superponer cualquier cosa con JLabel

Aviso

toda mi sugerencia para consumir MouseEvent por defecto, J Capa (X) y JLabel con KeyEvents también, pero hay ningún problema con los eventos de reexpedición ---> a otro JComponent

EDITAR

espera: no, no quiero pintar la espiral (lo que llamas "serpiente") en el centro del JScrollPane; Quiero pintar mi componente y hacer que mi componente se muestre en el centro de JScrollPane.

  • sus JPanel podrían ser más ancha que JViewport por defecto

a) JPanel vuelve Dimensión

b) la devolución JViewport Dimensión

  • continuación, sin ningún problema, parpadea o congelar

a) se puede centrar Dimmension de JPanel (punto) al centro de JViewport (punto)

b) si es que hay JComponent puede mover el JViewport a cualquier getBounds() tha volvió JComponent o Punto de JPanel en el interior JScrollPane

3

Con la sugerencia de Andrew, no puede tener la vista más pequeña que la ventana gráfica (y aún centrada).

La manera más limpia es hacerlo directamente desde el administrador de diseño, anulando ViewportLayout. Hay una aplicación en la fuente de:

http://www.randelshofer.ch/multishow

Look para la clase ZoomableViewportLayout, lo que hace el trabajo perfectamente.

Cuestiones relacionadas