Putting an image in JPanel

So I’m developing a custom GUI as a plugin for ImageJ, Has 4 buttons, each with its own operation, InverseFFT, FFT, 3d-plot and Crop. I want the plugin in to run so you select an image and it pastes it to the top left of my GUI with the buttons to the right. Each button performs the operation on the Image and updates the Image in the GUI. I’m stuck on how I get the image to appear in the gui. Am I ment to use a canvas or am I ment to have it as its own Jpanel. Does anyone have any experience with this idea. My code needs to be cleaned up a little but I’ll post it below. Any guidance would be appreciated.

 * @author boomer
//import static Surface_Plotter.plotWidth;
import ij.*;
//import ij.plugin.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
//import java.awt.image.*;
//import java.math.*;
import ij.IJ; 
import ij.ImagePlus;
import ij.plugin.PlugIn; 
import ij.process.ImageProcessor;
import java.awt.BorderLayout; 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame; 
import javax.swing.JButton; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import javax.swing.JPanel;

public class Ij_onefile extends JFrame implements PlugIn, ActionListener { 

    static int plotWidth =400;
    static double angleInDegrees =  40;
    static double angle = (angleInDegrees/360.0)*2.0*Math.PI;
    static int polygonMultiplier = 100;
    static boolean oneToOne;
    double picsize;
    ImagePlus img;
    int[] x,y;
   public void run(String arg) { 
       new Ij_onefile().setVisible(true); 

    public Ij_onefile() { 
       super("ImageJ Custom filter GUI");
       setSize(800, 600);
       //setLayout(new GridBagLayout()); 
       JPanel buttonPanel = new JPanel(new GridBagLayout());
       GridBagConstraints c = new GridBagConstraints();
       JPanel imagePanel = new JPanel();
       //imagePanel.setBackground(Color.RED);//try to save image into this panel
       //imagePanel.setSize(400, 300);
       ImagePlus imp = IJ.openImage();//this open as image dialog box and saves as imp
       ImageProcessor imgP = imp.getProcessor();//imgP now has image data
       imgP.convertToByte(true);//converts to 8 bit binarry
       //imagePanel = imgP;
       JButton button1 = new JButton("FFT"); 
       JButton button2 = new JButton("InverseFFT"); 
       JButton button3 = new JButton("3d_plot");
       JButton button4 = new JButton("captureImage");


       c.insets = new Insets(10, 10, 10, 10);
       buttonPanel.add(button1, c); //ADDs a button
       c.gridx = 0;
       c.gridy = 1;
       buttonPanel.add(button2, c);
       c.gridx = 0;
       c.gridy = 2;
       buttonPanel.add(button3, c);
       c.gridx = 0;
       c.gridy = 3;
       buttonPanel.add(button4, c);
       c.gridx = 0;
       c.gridy = 4;
       add(buttonPanel, BorderLayout.EAST);
       add(imagePanel, BorderLayout.CENTER);
       //add(button4, GridBagLayout.NORTH);

   public void actionPerformed(ActionEvent e) { 
       String name = e.getActionCommand(); 
       if (name.equals("FFT")) { 
           IJ.log("FFT clicked"); 
       else if (name.equals("InverseFFT")) { 
           IJ.log("InverseFFT clicked"); 
       else if(name.equals("3d_plot")) 
           ImagePlus myimage = img;
           myimage = WindowManager.getCurrentImage();
            if (img==null)
                        IJ.log("No Image selected");
            if (!showDialog())
            if (img.getType()!=ImagePlus.GRAY8) 
                    ImageProcessor ip = img.getProcessor();
                    ip = ip.crop(); // duplicate
                    img = new ImagePlus("temp", ip);
                     new ImageConverter(img).convertToGray8();
            ImageProcessor plot = makeSurfacePlot(img.getProcessor());	
            new ImagePlus("Surface Plot", plot).show();
       else if(name.equals("take snapshot")) 
          ImagePlus imp = IJ.openImage(); 

    boolean showDialog() 
            GenericDialog gd = new GenericDialog("Surface Plotter");
            gd.addNumericField("Width (pixels):", plotWidth, 0);
            gd.addNumericField("Angle (-90-90 degrees):", angleInDegrees, 0);
            gd.addNumericField("Polygon Multiplier (10-200%):", polygonMultiplier, 0);
            gd.addCheckbox("One Polygon Per Line", oneToOne);
            if (gd.wasCanceled())
                    return false;
            plotWidth = (int) gd.getNextNumber();
            angleInDegrees = gd.getNextNumber();
            polygonMultiplier = (int)gd.getNextNumber();
            oneToOne = gd.getNextBoolean();
            if (polygonMultiplier>400) polygonMultiplier = 400;
            if (polygonMultiplier<10) polygonMultiplier = 10;
            return true;

    public ImageProcessor makeSurfacePlot(ImageProcessor ip) 
            double angle = (angleInDegrees/360.0)*2.0*Math.PI;
            int polygons = (int)(plotWidth*(polygonMultiplier/100.0)/4);
            if (oneToOne)
                    polygons = ip.getHeight();
            double xinc = 0.8*plotWidth*Math.sin(angle)/polygons;
            double yinc = 0.8*plotWidth*Math.cos(angle)/polygons;
            boolean smooth = true;
            ip = ip.resize(plotWidth, polygons);
            int width = ip.getWidth();
            int height = ip.getHeight();
            double min = ip.getMin();
            double max = ip.getMax();

            if (smooth)
            //new ImagePlus("Image", ip).show();

            int windowWidth =(int)(plotWidth+polygons*Math.abs(xinc) + 20.0);
            int windowHeight = (int)(255+polygons*yinc + 10.0);
            Image plot =IJ.getInstance().createImage(windowWidth, windowHeight);
            Graphics g = plot.getGraphics();
            g.fillRect(0, 0, windowWidth, windowHeight);

            x = new int[width+2];
            y = new int[width+2];
            double xstart = 10.0;
            if (xinc<0.0)
                    xstart += Math.abs(xinc)*polygons;
            double ystart = 0.0;
            for (int row=0; row<height; row++) {
                    double[] profile = ip.getLine(0, row, width-1, row);
                    Polygon p = makePolygon(profile, xstart, ystart);
                    xstart += xinc;
                    ystart += yinc;
                    if ((row%5)==0) IJ.showProgress((double)row/height);

            ip = new ColorProcessor(plot);
            byte[] bytes = new byte[windowWidth*windowHeight];
            int[] ints =(int[]) ip.getPixels();
            for (int i=0; i<windowWidth*windowHeight; i++)
                    bytes[i] = (byte)ints[i];
            ip = new ByteProcessor(windowWidth,windowHeight, bytes, null);
            return ip;

    Polygon makePolygon(double[] profile, double xstart, double ystart) {
            int width = profile.length;
            for (int i=0; i<width; i++) 
                    x[i] =(int)( xstart+i);
            for (int i=0; i<width; i++) 
                    y[i] =(int)(ystart+255.0-profile[i]);
            x[width] =(int)xstart+width-1;
            y[width] = (int)ystart+255;
            x[width+1] =(int)xstart;
            y[width+1] = (int)ystart+255;

            //for (int i=0; i<width; i++)
            //	IJ.write("dbg: "+i+"  "+profile[i]+"  "+x[i]+"  "+y[i]);

            return new Polygon(x, y, width+2);
   public static void main(String args[])
       new Ij_onefile();
       //JFrame fullbox = new JFrame("Custom GUI");
       //fullbox.setContentPane(new Ij_onefile());


Why did you choose to develop your own GUI? I would not recommend doing that unless you have really good reasons to do so. By creating your own interface, your plugin will:

  • lose the ability to be recorded in the Macro recorder (unless you explicitly support it with some additional programming effort)
  • probably not be able to be run headlessly.

Furthermore, you might be writing a lot of code that has nothing to do with the fundamental image processing task you want to achieve. To make your plugin re-usable for others in the future, keep the user interface and the functionality separated (separation of concerns).

That said, here are some options.

  • If you just want to have a nice 4-button UI to start different processing tasks, use e.g. the ActionBar, available from the IBMP-CNRS update site
  • If you implement specific functionality, consider creating an ImageJ2 plugin for that specific task. This will then also be callable from scripts and usable from e.g. KNIME or Icy in the future. You can still use a custom UI (e.g. your own customized action bar) to make it accessible to users.

If you still think you want to implement your own UI, here are some great examples to learn from:

1 Like

Cheers for the reply, Its part of a college project, The idea is to make a piece of software that takes an image and can perform these certain operations on the image, its meant to be just a basic UI that focuses on certain tasks. I had a bigger plan for the whole thing but as I get closer to my deadline I’m looking just to get basic functionality up and running.

Have you looked at this example? It seems similar to what you’re trying to do.



Jon your a hero, that’s nearly exactly what I’m looking for, Thank you.

Alright, I didn’t get that from your first post…

Oh, and if you cross-post on other forums like stackoverflow.com, please do so transparently, by including a link to the respective other post on both places, such that others can find the answers as well.

Yes I will do in future, thanks

Hi Brian,

I am too stuck in the same situation where our requirements are somewhat on the same line. So if possible can you please share the code that you had implemented because that can guide me further on this.