Click here to Skip to main content
15,851,510 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:

I'm rather new to Java and Netbeans so please bare with me. I'm trying to draw 2D graphics on a jPanel and I am having a hard time getting it to work right. I'm not sure if I'm following the correct procedure for this or if I'm just missing something silly.

It seems like my graphic is being erased each time it is resized or if something appears on top of it like a menu bar. I have tried my best to have this redraw each time something happens but now I am at a dead end. Because now if a menu appears it erases the image, if I redraw the image while the menu is active it erases the menu.

When I resize the form with the controls docked something very interesting happens. I put an event that listens if the jScrollPane resizes, which reapplies the 2D graphics to the jPanel. It sometimes does it, sometimes not.

package my.SnapToGrid;

import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.InputEvent;

public class SnapGrid extends javax.swing.JFrame {

     int ViewPortWidth = 1000;//viewport width
     int ViewPortHeight = 2000;//viewport Height
     Color ViewPortBackgroundColor = Color.white;
     Color ViewPortGridColor = Color.darkGray;
     Color ViewPortSnapColor = Color.BLUE;
     int GridWidth = 30;//grid width
     int GridHeight = 30;//grid heiGridHeightt
     int npx, npy;//current snap coords
     BufferedImage buf;//double buffer
    public SnapGrid() {
        buf = new BufferedImage(ViewPortWidth, ViewPortHeight, BufferedImage.TYPE_INT_RGB);
        jplGraphic.setPreferredSize(new Dimension(ViewPortWidth,ViewPortHeight));

    // Calculate the snap position and Redraw and Reapply the 2D Graphics
    private void jplGraphicMouseMoved(java.awt.event.MouseEvent evt) {                                      
                    int x = evt.getX(), y = evt.getY();
                    int mx = x % GridWidth, my = y % GridHeight;

                    if (mx<GridWidth/2) npx = x - mx;
                    else npx = x + (GridWidth-mx);

                    if (my<GridHeight/2) npy = y - my;
                    else npy = y + (GridHeight-my);

                    status.setText(npx+", "+npy);

    // Reapply the 2D Graphic when it is moved
    private void jplGraphicComponentMoved(java.awt.event.ComponentEvent evt) {                                          
    // Draw the 2D Graphic and apply it
    private void formComponentShown(java.awt.event.ComponentEvent evt) {                                    

     // Reapply the 2D Graphics when resized
    private void jplGraphicComponentResized(java.awt.event.ComponentEvent evt) {                                            

    // Scroll and Move the ViewPort and Reapply the 2D Graphics
    private void jplGraphicMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {                                           
        // Are just the CTRL switches left on
        if(evt.getModifiers() == InputEvent.CTRL_MASK) {    // Zoom Functionality
        else{   // Scroll Functionality      
            Point ViewPortPosition = jscpViewPort.getViewport().getViewPosition();
            int UnitsToScroll = evt.getUnitsToScroll();
            if(evt.getModifiers() == InputEvent.SHIFT_MASK) {   // Scroll Horizontally
                ViewPortPosition.x += UnitsToScroll;
                if(ViewPortPosition.x < 0)ViewPortPosition.x = 0;
                int WidthLimit = ViewPortWidth-jscpViewPort.getHorizontalScrollBar().getWidth();
                if(ViewPortPosition.x > WidthLimit)ViewPortPosition.x = WidthLimit;
            else{   // Scroll Vertically
                ViewPortPosition.y += UnitsToScroll;
                if(ViewPortPosition.y < 0)ViewPortPosition.y = 0;
                int HeightLimit = ViewPortHeight-jscpViewPort.getVerticalScrollBar().getHeight();
                if(ViewPortPosition.y > HeightLimit)ViewPortPosition.y = HeightLimit;
            System.out.println("("+ViewPortPosition.x+", " +ViewPortPosition.y+")");

    // Reapply the 2D Graphics when resized
    private void jscpViewPortComponentResized(java.awt.event.ComponentEvent evt) {                                              

    // Draws the 2D Graphics and stores it in memory
    private void GenerateDrawing(){
               Graphics2D g = (Graphics2D)buf.createGraphics();
        g.setBackground(ViewPortBackgroundColor);   //Set Img Background
        g.clearRect(0, 0, ViewPortWidth, ViewPortHeight);   //Erase Everything
        //Draw Grid Markers
        g.setColor(ViewPortGridColor);  //Set Grid Marker Color
        for (int j=GridHeight;j<ViewPortHeight;j+=GridHeight) {
            for (int i=GridWidth;i<ViewPortWidth;i+=GridWidth) {
                g.drawLine(i, j, i, j);
        //Draw Snapped Point
        if (npx>=0 && npy>=0 && npx<=ViewPortWidth && npy<=ViewPortHeight) {
             g.drawOval(npx-4, npy-4, 8, 8);
    // Applies the 2D graphics to the jPanel
    private void UpdateDrawing(){
        jplGraphic.getGraphics().drawImage(buf, 0, 0, Color.BLACK, null);

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new SnapGrid().setVisible(true);

I didn't include all of the NetBeans generated code because it was simply too long.
Updated 14-Apr-15 7:36am

1 solution

After many hours of searching and trying various examples I finally figured out my problem was that I was attempting to redraw the entire UI to redraw my graphic, or redrawing my graphic independently causing other weird problems. Problems that I thought I was generating unnecessary workarounds.

What fixed it at the end was creating an extending class of JPanel that draws/displays the graphic on a JPanel, and then redraws the graphic only when the component is supposed to redraw. This fixed all problems with scrolling, resizing, moving, menus etc. It also obviously uses less resources.

public void paintComponent(Graphics g) {
Share this answer

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900