rombo poligono example ejemplo dibujar clase java swing graphics

poligono - paint java



java+Swing: superposición eficiente de rectángulo u otro "sprite" (4)

No estoy muy seguro de cómo decir esto, así que tengan paciencia conmigo.

Tengo dos JPanel en un contenedor JPanel con OverlayLayout . Ambos JPanel s en el contenedor anulan la paint(Graphics) .

El JPanel inferior es opaco y dibuja algunos gráficos bastante complicados, por lo que tarda un tiempo "largo" (10s o 100s de milisegundos) en renderizarse.

El JPanel superior es transparente y solo dibuja un rectángulo o línea o una forma simple basada en la entrada del mouse, por lo que es realmente rápido.

¿Hay alguna manera de configurar las cosas así que cuando cambio la forma simple en el panel superior, no vuelve a dibujar el panel inferior? (por ejemplo, de alguna manera almacena en caché el panel inferior)

Estoy vagamente familiar con conceptos como bitblt, doble almacenamiento en búfer y dibujo XOR, pero no estoy seguro de qué aplicar aquí.


Centrándonos en el panel complicado, la clave es factorizar todo fuera de paintComponent() excepto drawImage() . Coloque todo lo demás en otro hilo que actualice continuamente un buffer fuera de pantalla. Actualice periódicamente la pantalla a un ritmo que mantenga la respuesta del panel simple. La única parte difícil es la sincronización, pero SwingWorker es una buena opción. Hay más aquí .


Adenda para la respuesta por trashgod y jfpoilpret

1 / OverlayLayout es una forma extraña de cómo distribuir JPanels, ¿tiene el mismo resultado con una vez JPanel (sin OverlayLayout y Translucentcy)?

2 / (10s o 100s de milisegundos) es quizás de pequeño valor porque hay latencia del sistema operativo nativo (45-75ms para el sistema operativo y la PC de hoy)

3 / las sincronizaciones se administrarían mediante el uso de SwingWorker en Tarea BackGround y con el orden, las direcciones y las sincronizaciones para pintar procesos en JPanel, tal vez sus pinturas sean demasiado rápidas / rápidas

4 / no describiste más acerca de cómo, dónde y qué sobre paint () / paintComponent ()

if (SwingUtilities.isEventDispatchThread()) { paintImmediately(int x, int y, int w, int h) // or Rectangle r } else { Runnable doRun = new Runnable() { @Override public void run() { repaint(long tm, int x, int y, int width, int height) // or Rectangle r } }; SwingUtilities.invokeLater(doRun); }


Lo mejor sería usar un solo JComponent y crear una Imagen BufferedImage para almacenar la imagen inferior. Cuando ocurre la operación paintComponent en el JComponent , usted simplemente ajusta la imagen inferior y usa el objeto Graphics para hacer cualquier dibujo adicional sobre eso (desde un estado almacenado). Debería ser bastante eficiente.

Querrá hacer las complejas operaciones de dibujo para la BufferedImage inferior en otro hilo, como menciona el otro cartel (omitido esto por accidente, lo siento :)). Sin embargo, no desea causar contención en esta imagen, por lo que debe almacenar una Imagen BufferedImage adicional para esto y ajustarla de forma síncrona a la otra imagen en el mismo momento en que se completan las operaciones de dibujo.


Lo que es seguro es que si el panel superior es el objetivo para un repaint() completo repaint() , entonces el inferior también lo será.

Tal vez pueda tratar de optimizar la región para volver a pintar en el panel superior a fin de evitar volver a pintar todo el inferior. Pero si el rectángulo pintado en el panel superior cubre toda el área, entonces terminará con el repaint() completo repaint() una vez más.

Normalmente, Swing intenta optimizar las regiones que necesitan un repintado, pero también agrega estas regiones cuando se repintan varias veces en poco tiempo, y si recuerdo bien, la región agregada es solo un rectángulo que es la unión de todos los rectángulos de repintar , que no siempre está optimizado, pero permite un cálculo rápido de la creación de eventos de repintado.

Ahora, creo que debes seguir los consejos dados en las respuestas anteriores; de hecho, realmente debería evitar tener un método paint() que pueda realizar cálculos que pueden ser tan largos (unos 10s de ms deberían ser el máximo real). La pintura debe ser lo más rápida posible si no desea tener una GUI que no responda al usuario final. Por lo tanto, a favor de realizar el cálculo solo una vez (y fuera del EDT, si es posible), almacene el resultado en una BufferedImage que simplemente dibujará más adelante en el método paint() .

EDITAR : agregó otras fuentes de reflexión

Si desea optimizar la actualización de la lista de puntos pero aún mantenerla en el método paint() , puede usar la región de recorte de los Graphics pasados ​​para limitar las llamadas a los métodos de dibujo, como por ejemplo:

Rectangle clip = g.getClipBounds(); for (Point p: allPoints) { if (clip.contains(p)) { // draw p with g graphics } }

Incluso puede intentar optimizar la lista de puntos para dibujar usando un QuadTree en lugar de una simple List , pero tendrá que codificarlo usted mismo (o encontrar algunas implementaciones gratuitas, probablemente haya algunas por ahí). Con un árbol cuádruple, puede optimizar el tiempo para encontrar la lista de todos los puntos que tienen que volver a dibujarse (según el rectángulo de recorte de Graphics ) y solo volver a dibujar esos puntos.