Mark Coats
Mark Coats

Reputation: 11

Trouble Drawing In JPanel

I'm going to start off by saying that I can almost guarantee that this question is going to be a copy but I couldn't find any other answers that suited my needs / worked on my program. I need to draw on a JPanel, but I can't seem to be able to get the line I need to draw to show up.

JFrame drawF = new JFrame("Simulator");
        JPanel simPanel = new JPanel();
        drawF.setVisible(true);
        drawF.setSize(1000,650);
        drawF.add(simPanel);
        drawF.pack();
        simPanel.setLayout(null);
        simPanel.setSize(1000,650);
        simPanel.setVisible(true);
        simPanel.setBackground(Color.BLACK);

        //add drawing surface


        //start drawing
            simPanel.add(new JComponent()
            {
            public void paint(Graphics g)
            {
                g.setColor(Color.RED);
                int xLast,yLast;
                for(int i=0;i < 5000000; i++)  // five million
                {

                    double dX = (Math.E*Math.exp(-numd1*i)*Math.sin(i*numf1+nump1))+(Math.E*Math.exp(-numd2*i)*Math.sin(i*numf2*nump2));
                    double dY = (Math.E*Math.exp(-numd3*i)*Math.sin(i*numf3+nump3))+(Math.E*Math.exp(-numd4*i)*Math.sin(i*numf4*nump4));
                    int drawX = (int)dX;
                    int drawY = (int)dY;
                    if (i==0)
                    {
                        xLast = 0;
                        yLast = 0;
                        g.drawLine(xLast,yLast,drawX,drawY);

                        simPanel.revalidate();
                        simPanel.repaint();
                    }
                    else
                    {
                        xLast = drawX;
                        yLast = drawY;
                        g.drawLine(xLast,yLast,drawX,drawY);

                        simPanel.revalidate();
                        simPanel.repaint();
                    }
                }
            }
        });





        repaint();

is there something wrong with adding a JComponent to my JPanel?

Upvotes: 0

Views: 67

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285430

Your problem is likely one of layout manager. JPanel uses FlowLayout by default, so your JComponent will size to its natural preferred size which is [0, 0], and so nothing will show in this situation. Try making your JPanel's layout BorderLayout and add the JComponent BorderLayout.CENTER.

Other problems:

  • Override the JComponent's paintComponent method, not the paint method, otherwise you risk unexpected side effects by not taking into account the painting of borders and children.
  • Call the super's painting method in your override, super.paintComponent(g); if you're overriding paintComponent as I recommend. This will help clean any dirty pixels.
  • Get rid of all those unnecessary calls to repaint and revalidate and setVisible.
  • Call setVisible on the JFrame after adding all components to the GUI.
  • Myself, I prefer to paint within a JPanel's paintComponent method, not a JComponent, since it won't paint the background automatically.
  • And I prefer to do my painting in its own stand alone class, not buried within an anonymous inner class. It's too important a function to bury in such a way.
  • The more long running or CPU-intense code you call within a painting method, the less responsive your GUI will seem. Off load the for loops and the math calculations in your class's constructor and out of the painting method. Store the results in an array or list, or if you desire paint to a BufferedImage and then display that image within the paintComponent method.

For example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;

@SuppressWarnings("serial")
public class DrawingStuff extends JPanel {
    private static final int PREF_W = 1000;
    private static final int PREF_H = 650;
    private static final Color BG = Color.BLACK;
    private static final Color GRAPHICS_COLOR = Color.RED;
    private static final int LOOP_COUNT = 5000000; // 5 million

    private BufferedImage image = null;
    private MathParams[] params;

    public DrawingStuff(MathParams[] params) {
        this.params = params;
        setBackground(BG);
        image = drawImage();
    }

    private BufferedImage drawImage() {
        BufferedImage img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();

        g2.setColor(GRAPHICS_COLOR);
        int xLast, yLast;
        for (int i = 0; i < LOOP_COUNT; i++) {
            double dX = params[0].doCalc0(i) + params[1].doCalc1(i);
            double dY = params[2].doCalc0(i) + params[3].doCalc1(i);
            int drawX = (int) dX;
            int drawY = (int) dY;
            if (i == 0) {
                xLast = 0;
                yLast = 0;
                g2.drawLine(xLast, yLast, drawX, drawY);
            } else {
                xLast = drawX;
                yLast = drawY;
                g2.drawLine(xLast, yLast, drawX, drawY);
            }
        }

        g2.dispose();
        return img;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (image != null) {
            g.drawImage(image, 0, 0, this);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Drawing Stuff");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // TODO: fix this -- what numbers to use??? These don't work
        MathParams[] paramArray = { 
                new MathParams(1, 2, 3), 
                new MathParams(1, 2, 3), 
                new MathParams(3, 4, 5),
                new MathParams(3, 4, 5)
                };

        frame.getContentPane().add(new DrawingStuff(paramArray));
        frame.setResizable(false);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

public class MathParams {
    private int numd;
    private int numf;
    private int nump;

    public MathParams(int numd, int numf, int nump) {
        this.numd = numd;
        this.numf = numf;
        this.nump = nump;
    }

    public double doCalc0(int i) {
        return (Math.E * Math.exp(-numd * i) * Math.sin(i * numf + nump));
    }

    public double doCalc1(int i) {
        return (Math.E * Math.exp(-numd * i) * Math.sin(i * numf * nump));
    }
}

Upvotes: 2

Related Questions