2010-02-16 7 views
6

Estoy tratando de renderizar un componente Swing personalizado donde amplié la clase JComponent.¿Cuándo getGraphics() devolverá una instancia de gráficos válida?

Con el propósito de simplificar los requisitos de los componentes, permite resumir que mi componente necesita renderizar algunas cadenas, cada una con sus propias fuentes.

Necesito que mi componente se ajuste exactamente al ancho y alto sumados de mis cadenas representadas.

Para determinar este tamaño, uso FontMetrics para calcular las dimensiones de cada cadena. Con esta información, puedo averiguar qué tamaño tendrá mi componente y cambiar su tamaño de manera apropiada.

El problema es que cuando accedo a getGraphics() siempre es nulo, por lo que no puedo obtener la instancia de FontMetrics. Si espero para calcular el tamaño de mi componente del método paintComponent() modificado, es demasiado tarde (el componente ya tiene un tamaño, ¿verdad?).

La documentación dice que "Este método devolverá nulo si este componente no se puede visualizar actualmente". Entonces, ¿cuándo sé cuándo el componente está listo para mostrarse y tengo un objeto Graphics para que cambie el tamaño de mi componente?

¿Cuál es el orden de invocación de Swing para representar el componente una vez que se ha llamado al marco setVisible (verdadero)?

Gracias


Actualizar: Martes, 06 de Febrero de 2010 a las 23:34

Como se ha mencionado abajo en los comentarios, el GridLayout no respeta ninguna setXxxSize() en absoluto. Para cualquier persona interesada, he publicado resultados del uso de GridLayout, BoxLayout y FlowLayout usando un marco simple que recibe 5 componentes de tamaño fijo de 200 de ancho por 50 de alto (estableciendo min, max y preferred).

Resultados de la prueba:

El GridLayout siempre se cambian de tamaño a lo largo de la anchura y altura (como se menciona en comentarios)

El FlowLayout siempre respetado los componentes de tamaño independientemente.

En cuanto a la la BoxLayout ...

El PAGE_AXIS y Y_AXIS se redujo la anchura de los componentes a aproximadamente la mitad de su tamaño (104), pero no se encogió la altura.

El LINE_AXIS y X_AXIS contrajo la altura de los componentes a lo que parecía cero, pero no tocó el ancho.

Respuesta

7

Primero, puede medir sus cadenas utilizando la clase TextLayout y sus elementos asociados.Por ejemplo

public static void main(final String[] args) throws Exception 
{ 
    final FontRenderContext frc = new FontRenderContext(null, true, true); 
    final Font font = new Font("serif", Font.PLAIN, 18); 
    final TextLayout layout = new TextLayout("This is a test", font, frc); 
    final Rectangle2D bounds = layout.getBounds(); 
    System.err.println((int) (bounds.getWidth() + .5)); 
} 

En segundo lugar, puede ser informado cuando el componente se ha hecho visible mediante el uso de un ComponentListener, pero eso no es necesario para la medición de sus cadenas de "avance"!

+0

Veo que está creando su fuente? Cuando probé getFont(), la fuente es nula. ¿Asumo que un JComponent no tiene una fuente predeterminada? – Jeach

+0

Un componente cuya fuente no está explícitamente establecida utiliza la fuente de sus padres. Si no tienes padres, entonces no tienes ninguna fuente. Sería mejor configurar explícitamente tu propia fuente en tu constructor. –

+0

Gracias Jonathan! Configurar la fuente es lo que comencé a hacer. Ahora puedo representar el componente correctamente, pero por alguna razón este componente todavía se niega a dimensionarse según mis dimensiones. Si creo un marco con un diseño de cuadrícula (0 filas, 1 columna) y agrego 10 de mis componentes, entonces hago el cuadro a pantalla completa. Cada elemento obtiene 1/10 de la altura de la pantalla en altura cuando no deben ser mucho más pequeños. Configuré min, max, preferred, setSize() y de alguna manera se vuelve a su gusto. – Jeach

2

Use un JLabel para representar sus cadenas, entonces puede usar el método getPreferredSize() de la etiqueta thel.

+0

Supongo que esperaba que alguien me dijera que use componentes Swing existentes para hacer esto . Mis requisitos son eliminar gran parte de la hinchazón existente de este componente y presentarla yo mismo. Solía ​​haber etiquetas e íconos dentro de los paneles y dentro de más paneles con diseños, etc. Supongo que fue creado con una herramienta automatizada. ¡Ahora debe seguir una dieta que me digan! – Jeach

+0

Pensándolo bien, los eventos de JLabel son problemáticos porque como mencioné en mi comentario anterior a Jonathan, la etiqueta debe permanecer a una altura fija no mucho mayor que el tamaño de la fuente. JLabel tiene una tendencia a hacer exactamente lo que mi componente está haciendo ... ¡estirar! – Jeach

+0

Según lo mencionado por Jonathan, este es un problema de diseño, no un cálculo de "tamaño preferido". Si aún desea utilizar un GridLayout para su panel, entonces otro enfoque es crear un panel principal con un BorderLayout. Agregue su panel con el GridLayout al NORTE del panel principal. Ahora todo el espacio extra se le dará al centro y su panel se mostrará en su tamaño preferido. – camickr

Cuestiones relacionadas