0

I'm making a application with Swing, and I want to add to the main panel a button with a cross icon on it. But when I draw an image on it, the image is rendering weirdly.

I've already tried several things like resizing the image outside the application, and the cross is made with IllustratorCC so I don't think it's the quality of the source image that's the issue.

import javax.imageio.*;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

public class ImageRenderingBadly extends JPanel
{
    BufferedImage cross;

    public ImageRenderingBadly()
    {
        try {
            URL url = new URL("https://i.stack.imgur.com/bWO4o.png");
            cross = ImageIO.read(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void paintComponent(Graphics g)
    {
        g.drawImage(cross,0,0,null);
    }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setSize(new Dimension(200,200));
        frame.setBackground(new Color(0));

        ImageRenderingBadly panel = new ImageRenderingBadly();

        frame.setContentPane(panel);
        frame.setVisible(true);
    }
}

Source:

Rendering badly:

FOUND THE SOLUTION

Use antialiasing in paintComponent :(https://docs.oracle.com/javase/tutorial/2d/advanced/quality.html)

@Override
    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        RenderingHints rh = new RenderingHints(
                RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHints(rh);
        g2.drawImage(cross,0,0,null);
    }

Result

Elex XVII
  • 15
  • 4
  • JButtons do much of the rendering using delegates, and so this is not the best way of getting an image on a button. Have you tried setting the button's Icon? You can eliminate the button's borders/margins if desired so that just the icon shows. – Hovercraft Full Of Eels May 25 '19 at 20:19
  • Ah ok, I just deleted the ".drawImage" and added "this.setIcon(image)" on the constructor : Same result ! Another idea ? – Elex XVII May 25 '19 at 20:24
  • 1
    Your main problem I can see is that you're expanding an image that can't be expanded well. Better to simply use an image that is the right size to begin with. – Hovercraft Full Of Eels May 25 '19 at 20:47
  • I set the preferedSize as 30px by 30px and the image is 30px by 30px – Elex XVII May 25 '19 at 20:48
  • you need to use the clipping in your paint component so that nothing gets painted outside the bounding rect of the button. – Sudhir Dhumal May 25 '19 at 21:27
  • 1) *"application with JSwing"* There's no such thing as 'JSwing'. It is 'Swing'. 2) `Frame frame;` ..but `Frame` is AWT. Use a `JFrame` (yes, it is the Swing components that start with `J`). 3) For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 4) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. [This answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). – Andrew Thompson May 25 '19 at 23:35
  • 5) `.. extends FlatButton // FlatButton extends JButton` Does it render badly when the code extend `JButton` instead of `FlatButton`? If so, `FlatButton` is irrelevant to the problem and can be factored out. If not, we need to see the code for that as well. Hance the request for a [mcve]. – Andrew Thompson May 25 '19 at 23:45
  • Hello sorry for the mistakes ! 2) Just my bad : Frame it's my class extended from JFrame (I just changed it to make it more clear) 3) Ok I'm will make it right now 4) I already saw this post and it doesn't give me anwser to my question : why the image is rendering badly 5) Yep, I will make it more clear ! – Elex XVII May 26 '19 at 08:47

2 Answers2

1

It works for me:

Note that I have used the image to create two images and Icons, one for the button, and one for the depressed state, to indicate that it has been pressed.

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class XButtonTest {
    private static final String X_IMG_PATH = "https://i.imgur.com/cWGntek.png";

    public static void main(String[] args) {
        try {
            URL xImgUrl = new URL(X_IMG_PATH);
            BufferedImage xImage = ImageIO.read(xImgUrl);
            int w = xImage.getWidth();
            int h = xImage.getHeight();
            BufferedImage pressedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = pressedImg.createGraphics();
            g2.setColor(Color.LIGHT_GRAY);
            g2.fillRect(0, 0, w, h);
            g2.drawImage(xImage, 0, 0, null);
            g2.dispose();

            Icon icon = new ImageIcon(xImage);
            Icon pressedIcon = new ImageIcon(pressedImg);

            JButton button = new JButton(icon);
            button.setPressedIcon(pressedIcon);
            button.setBorderPainted(false);
            button.setFocusPainted(false);
            button.setContentAreaFilled(false);
            JPanel panel = new JPanel();
            panel.add(button);
            JOptionPane.showMessageDialog(null, panel, "Test", JOptionPane.PLAIN_MESSAGE);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

I figured out that the "drawImage" render badly image and that' the problem I think :


public class Panel extends JPanel
{
    BufferedImage image;

    public Panel() {
        super();

        try {
            image = ImageIO.read(new File("images/BMW-TA.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
    }
}

Source : https://i.stack.imgur.com/qlLIA.jpg

Rendering : https://i.stack.imgur.com/BDg3v.png

FOUND THE SOLUTION

Use antialiasing in paintComponent :

@Override
    public void paintComponent(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        RenderingHints rh = new RenderingHints(
                RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHints(rh);
        g2.drawImage(cross,0,0,null);
    }
Elex XVII
  • 15
  • 4