¿Cómo hacer un canvas con Swing?

Estoy intentando hacer un editor de pintura con Java en el que tengo una barra de herramientas con los objetos que me gustaría pegar en el canvas. Estoy usando componentes Swing para hacer la GUI, pero cuando busqué la manera de hacer el canvas, solo encontré el canvas de clase de AWT.

¿Hay alguna manera de hacer algo similar a un canvas con Swing? (por ejemplo, JPanel?) He leído que usar el canvas de clase de AWT con una GUI hecha con swing no funcionará correctamente, ¿es cierto?

Para hacer un ‘Lienzo’ personalizado en swing, generalmente escribes una subclase de un JPanel . Luego, debe sobrescribir el protected paintComponent(Graphics g) JPanel de JPanel .

En el método de pintura, puede llamar a métodos en el objeto Graphics para dibujar realmente en el JPanel .

Como siempre, los Tutoriales de Java tienen una gran referencia sobre esto para que comiences.

Probablemente quiera crear una subclase de JPanel e implementar su propia forma de pintar los componentes que desea dibujar en el panel.

El enfoque básico probablemente estará en la línea de asignar un MouseListener a la subclase de JPanel , luego implementar la funcionalidad de pintura.

La idea básica puede ser algo en la línea de:

 class MyCanvas extends JPanel implements MouseListener { Image img; // Contains the image to draw on MyCanvas public MyCanvas() { // Initialize img here. this.addMouseListener(this); } public void paintComponent(Graphics g) { // Draws the image to the canvas g.drawImage(img, 0, 0, null); } public void mouseClicked(MouseEvent e) { int x = e.getX(); int y = e.getY(); Graphics g = img.getGraphics(); g.fillOval(x, y, 3, 3); g.dispose(); } // ... other MouseListener methods ... // } 

El ejemplo anterior está incompleto (y no probado, definitivamente no comstackrá), pero da una idea sobre cómo implementar una clase MyCanvas en la que un usuario puede hacer clic y dibujar círculos.

El objeto img se usa para contener la imagen del canvas. El método paintComponent se usa para pintar el objeto img en el canvas. En el método mouseClicked , el objeto Graphics asociado con img se recupera para fillOval en la imagen.

Como uno de los requisitos es pegar imágenes en el canvas, puede ser una buena idea guardar algunas Image que desee pegar en el canvas. Tal vez algo en la línea de:

 Image[] myImages; // Used to store images to paint to screen. 

Luego, en la rutina para pintar la imagen en img almacenada en MyCanvas :

 g.drawImage(myImage[INDEX_OF_DESIRED_IMAGE], 0, 0, null); 

Al utilizar el método drawImage del objeto Graphics , se pueden dibujar otras Image en Image s.


En cuanto a la pregunta sobre AWT y Swing, sí, es cierto que no desea mezclar componentes de AWT y Swing, ya que difieren en la forma en que representan los componentes de la GUI. AWT se basa en componentes pesados, lo que significa que son ventanas nativas para pintar la GUI, mientras que Swing se basa en componentes ligeros, lo que significa que la GUI es dibujada por Java sin usar componentes nativos.

Una buena guía sobre la diferencia de AWT y Swing se proporciona en Pintura en AWT y artículo Swing de Sun.

Simplemente subclase JComponent .

JPanel es una clase inapropiada. A menudo se sugiere ya que parece tener setOpaque(true) invocado automáticamente. En realidad, PL & F es lo que hace eso, y si realmente sucede o no depende de la implementación y del proveedor.

Canvas es un componente pesado. Es decir que está controlado por el sistema de ventanas subyacente. El resultado es que normalmente se dibujará sobre la parte superior de los componentes de Swing, sin importar el orden Z o el recorte (colocarlo en un panel de desplazamiento dará un comportamiento extraño).

Es posible que desee ver la API de Minueto. Es una aplicación de gráficos muy simple de usar, y puede combinar el evento de Java escuchando con ella para proporcionar su capacidad de dibujo.

http://minueto.cs.mcgill.ca/