I'm working on a project in which I am trying to make a paint program. So far I've used Netbeans to create a GUI and set up the program.
As of right now I am able to call all the coordinated necessary to draw inside it but I am very confused with how to actually paint inside it.
Towards the end of my code I have a failed attempt at drawing inside the panel.
Can anyone explain/show how to use graphics in a example like this?
All examples I have found make a class and extend it with JPanel
but I don't know if I can do this since it was generated in netbeans.
I need to draw inside a JPanel
, inside my JFrame
. I don't know where to put the graphics class.
package javapaint; import java.awt.*; import javax.swing.*; public class JavaPaintUI extends javax.swing.JFrame { public JavaPaintUI() { initComponents(); } private void initComponents() { jPanel2 = new javax.swing.JPanel(); jPanel2.setBackground(new java.awt.Color(255, 255, 255)); jPanel2.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); jPanel2.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { jPanel2MousePressed(evt); } public void mouseReleased(java.awt.event.MouseEvent evt) { jPanel2MouseReleased(evt); } }); jPanel2.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { public void mouseDragged(java.awt.event.MouseEvent evt) { jPanel2MouseDragged(evt); } }); pack(); }// </editor-fold> int currentX, currentY, oldX, oldY; private void jPanel2MouseDragged(java.awt.event.MouseEvent evt) { if (tool == 1) { currentX = evt.getX(); currentY = evt.getY(); oldX = currentX; oldY = currentY; System.out.println(currentX + " " + currentY); System.out.println("PEN!!!!"); } } private void jPanel2MousePressed(java.awt.event.MouseEvent evt) { oldX = evt.getX(); oldY = evt.getY(); System.out.println(oldX + " " + oldY); } //mouse released// private void jPanel2MouseReleased(java.awt.event.MouseEvent evt) { if (tool == 2) { currentX = evt.getX(); currentY = evt.getY(); System.out.println("line!!!! from" + oldX + "to" + currentX); } } //set ui visible// public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new JavaPaintUI().setVisible(true); } }); } // Variables declaration - do not modify private javax.swing.JPanel jPanel2; // End of variables declaration class jPanel2 extends JPanel { @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawString("BLAH", 20, 20); g.drawRect(200, 200, 200, 200); } } }
The whole thing is a JFrame
and the white section in the center is jPanel2
which is what I want to draw on.
Instead, in Swing, we usually draw on a JPanel. Turns out, you can draw on most Swing components, but are not advised to draw on top-level components like JFrame. The all-important technique of overriding paintComponent() (and, sometimes, repaint()): Like AWT, Swing does not maintain "bit-mapped memory".
Solution: Write a method, drawCircle() , which has parameters for the coordinates of the center point and a radius. It then calls drawOval with transformed parameters. To make a drawing, define a new component by subclassing JPanel and overriding the paintComponent() method.
Displaying graphics in swing: java.awt.Graphics class provides many methods for graphics programming. Commonly used methods of Graphics class: public abstract void drawString (String str, int x, int y): is used to draw the specified string.
When working with graphical user interfaces, you need to remember that drawing on a pane is done in the Java AWT/Swing event queue. You can't just use the Graphics object outside the paint () / paintComponent () /etc. methods. However, you can use a technique called " Frame buffering ".
Basically, every component that extends JComponent has a paint () method, which is automatically passed in a Graphics g object. You then reference that object to draw graphics on the current element. Look up the paint () doc for more.
The Java Graphics objects group (combined) the state information which is necessary for the basic rendering operations which Java supports. The state information includes below some of the properties.
Note the extra comments.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; class JavaPaintUI extends JFrame { private int tool = 1; int currentX, currentY, oldX, oldY; public JavaPaintUI() { initComponents(); } private void initComponents() { // we want a custom Panel2, not a generic JPanel! jPanel2 = new Panel2(); jPanel2.setBackground(new java.awt.Color(255, 255, 255)); jPanel2.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); jPanel2.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent evt) { jPanel2MousePressed(evt); } public void mouseReleased(MouseEvent evt) { jPanel2MouseReleased(evt); } }); jPanel2.addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent evt) { jPanel2MouseDragged(evt); } }); // add the component to the frame to see it! this.setContentPane(jPanel2); // be nice to testers.. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); }// </editor-fold> private void jPanel2MouseDragged(MouseEvent evt) { if (tool == 1) { currentX = evt.getX(); currentY = evt.getY(); oldX = currentX; oldY = currentY; System.out.println(currentX + " " + currentY); System.out.println("PEN!!!!"); } } private void jPanel2MousePressed(MouseEvent evt) { oldX = evt.getX(); oldY = evt.getY(); System.out.println(oldX + " " + oldY); } //mouse released// private void jPanel2MouseReleased(MouseEvent evt) { if (tool == 2) { currentX = evt.getX(); currentY = evt.getY(); System.out.println("line!!!! from" + oldX + "to" + currentX); } } //set ui visible// public static void main(String args[]) { EventQueue.invokeLater(new Runnable() { public void run() { new JavaPaintUI().setVisible(true); } }); } // Variables declaration - do not modify private JPanel jPanel2; // End of variables declaration // This class name is very confusing, since it is also used as the // name of an attribute! //class jPanel2 extends JPanel { class Panel2 extends JPanel { Panel2() { // set a preferred size for the custom panel. setPreferredSize(new Dimension(420,420)); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawString("BLAH", 20, 20); g.drawRect(200, 200, 200, 200); } } }
HFOE put a good link as the first comment on this thread. Camickr also has a description of active painting vs. drawing to a BufferedImage
in the Custom Painting Approaches article.
See also this approach using painting in a BufferedImage
.
When working with graphical user interfaces, you need to remember that drawing on a pane is done in the Java AWT/Swing event queue. You can't just use the Graphics
object outside the paint()
/paintComponent()
/etc. methods.
However, you can use a technique called "Frame buffering". Basically, you need to have a BufferedImage and draw directly on it (see it's createGraphics()
method; that graphics context you can keep and reuse for multiple operations on a same BufferedImage
instance, no need to recreate it all the time, only when creating a new instance). Then, in your JPanel
's paintComponent()
, you simply need to draw the BufferedImage
instance unto the JPanel
. Using this technique, you can perform zoom, translation and rotation operations quite easily through affine transformations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With