1

I am making a minimally small paint application for a class in Java. I need to make several buttons for the user to select different shapes, and on those buttons I am supposed to put an image of the shape they are using. For example, a button that lets a user draw a line should have have an image of a line on it. A button that draws a rectangle, a rectangle should be on it. I need to be able to do this from within the program without using an external image source.

Here is my current button code example.

lineB = new JButton();
lineB.setBounds(0, 25, 20, 20);
lineB.setBackground(Color.WHITE);
shapePanel.add(lineB);
lineB.addActionListener(this);
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Chris Campbell
  • 155
  • 2
  • 11

2 Answers2

5
  1. Create a BufferedImage of the desired size -- BufferedImage img = new BufferedImage(biWidth, biHeight, BufferedImage.TYPE_INT_ARGB);
  2. Get its Graphics context by calling getGraphics() or createGraphics() (better because it gives you a Graphics2D object) on it.
  3. I'd set the RenderingHints of this Graphics2D object to all for antialiasing using the setRenderingHints(...) method. This can smooth out jaggies.
  4. Draw your shape with this object.
  5. Dispose of the Graphics object.
  6. Create an ImageIcon from the above Image using new ImageIcon(Image image) constructor.
  7. Set your button's icon with the above icon using setIcon(...).
  8. Do not call setBounds(...) on the button or on anything.

e.g.,

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

@SuppressWarnings("serial")
public class ImageButton extends JPanel {
   private static final int IMG_WIDTH = 50;
   private static final Color SHAPE_COLOR = Color.RED;
   private static final int GAP = 4;
   private JButton circleButton = new JButton();
   private JButton squareButton = new JButton();

   public ImageButton() {
      BufferedImage circleImg = new BufferedImage(IMG_WIDTH, IMG_WIDTH, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = circleImg.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(SHAPE_COLOR);
      int x = GAP;
      int y = x;
      int width = IMG_WIDTH - 2 * x;
      int height = IMG_WIDTH - 2 * y;
      g2.fillOval(x, y, width, height);
      g2.dispose();
      circleButton.setIcon(new ImageIcon(circleImg));

      BufferedImage squareImg = new BufferedImage(IMG_WIDTH, IMG_WIDTH, BufferedImage.TYPE_INT_ARGB);
      g2 = squareImg.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(SHAPE_COLOR);
      g2.fillRect(x, y, width, height);
      g2.dispose();
      squareButton.setIcon(new ImageIcon(squareImg));

      add(circleButton);
      add(squareButton);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("ImageButton");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new ImageButton());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Also note that swing components all have override-able paint/update methods, and this is intentional. However, please prefer Hovercraft's solution, which is the "right" way to do this 99.999% of the time. – BadZen May 05 '15 at 17:06
  • 1
    @BadZen: Yes that would not be good since you'd prevent the button's delegate from doing its drawing. – Hovercraft Full Of Eels May 05 '15 at 17:07
  • Well, yeah, you'd have to call paintComponent() to have the delegate render and then doodle on top of it. Not great in general. But maybe some use case. Was just pointing it out, since it generalizes to all kinds of GUI elements in Swing... – BadZen May 05 '15 at 17:09
0

One Easy way is to add an image to JButton and make it like an image button.

try {
 Image icon = ImageIO.read(getClass().getResource("icons/line.jpg"));
 lineButton.setIcon(new ImageIcon(icon));
} catch (IOException ex) {
}

edited :

since you are urged to create shapes in your code u can do the code below to create a image in memory draw on graphic of the image and then assign it to the button.

    final int BI_WIDTH = 50;
    final int BI_HEIGHT = 50;
    BufferedImage lineImage = new BufferedImage(BI_WIDTH, BI_HEIGHT,
            BufferedImage.TYPE_INT_RGB);
    lineImage.createGraphics().drawLine(2, 25, 48, 25);
    JButton lineButton = new JButton();
    lineButton.setIcon(new ImageIcon(lineImage));

graphic object has many different functions and you could draw whatever you like on it.

Morteza Adi
  • 2,413
  • 2
  • 22
  • 37
  • 1
    Which goes directly against one of the assignment's requirements: `"I need to be able to do this from within the program without using an external image source."` – Hovercraft Full Of Eels May 05 '15 at 17:11
  • We haven't gone over anything like that in our class, and even though I am sure that would work, I also know my professor wants me to stick to something we have at least touched on. He just never discussed how to do a g.drawLine on a button. I have tried different combinations of lineB.set**** and I am always getting the error that "void type not allowed here" – Chris Campbell May 05 '15 at 17:18
  • Also, it's not safe to recommend that a newbie (or anyone) use an empty catch block: `catch (...) { }` – Hovercraft Full Of Eels May 05 '15 at 17:18
  • @ChrisCampbell: I have given you the outline of what you need to do. – Hovercraft Full Of Eels May 05 '15 at 17:19
  • @HovercraftFullOfEels I’m not here to teach how to code in Java I just trying to give an easy solution for the problem, how ppl handle their exceptions is out of the topic. However you are right about catching every exception appropriately. – Morteza Adi May 05 '15 at 17:29
  • I read the @HovercraftFullOfEels answer after submitting my answer, what i proposed is exactly same as he elaborately described. IMO His answer should be selected. – Morteza Adi May 05 '15 at 17:35
  • Whether you're here to teach or not, newbies will treat your answer as gospel. Please at least print a stacktrace. Don't consider this teaching if you don't want to teach but rather "leading by example". Also inline use of a Graphics object can cause a program to run out of resources since this way you can't dispose of it when you're done. – Hovercraft Full Of Eels May 05 '15 at 19:00
  • @HovercraftFullOfEels As i said what I was trying to do was to give a minimal answer to the question and not going into every detail of implementation such as disposing graphic objects!! seems while i was writing, your answer was posted so i commented that your answer is thorough and should be selected. – Morteza Adi May 06 '15 at 04:43