1

This is my JButton code:

JButton Savebtn = new JButton();//("Save");
Savebtn.setFont(btnFont);
Savebtn.setOpaque(false);
Savebtn.setContentAreaFilled(false);
Savebtn.setBorder(null);
Savebtn.setMargin(new Insets(0, 0, 0, 0));
Savebtn.setIcon(new ImageIcon("src/Pic2/menubtn0.png"));
Savebtn.setPressedIcon(new ImageIcon("src/Pic2/menubtn1.png"));
//Savebtn.setText("Save");

The effect is like this :

pic1

I tried to do this:

JButton Savebtn = new JButton();//("Save");
Savebtn.setFont(btnFont);
Savebtn.setOpaque(false);
Savebtn.setContentAreaFilled(false);
Savebtn.setBorder(null);
Savebtn.setMargin(new Insets(0, 0, 0, 0));
Savebtn.setIcon(new ImageIcon("src/Pic2/menubtn0.png"));
Savebtn.setPressedIcon(new ImageIcon("src/Pic2/menubtn1.png"));
Savebtn.setText("Save");

pic2

The text did not appear and a white line occured at the right side. Could any one help me with this?

PS:I can't just put the words onto my picture because the button text I want to show is related to my program.

The button picture: button

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Shuxin
  • 17
  • 4
  • 2
    1) For better help sooner, [edit] to add a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) 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. The code in [this answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). 3) Application resources will become embedded resources by the time of deployment, so it is wise to start accessing them as if they were, right now. .. – Andrew Thompson Dec 13 '20 at 05:40
  • 1
    .. An [tag:embedded-resource] must be accessed by URL rather than file. See the [info. page for embedded resource](http://stackoverflow.com/tags/embedded-resource/info) for how to form the URL. – Andrew Thompson Dec 13 '20 at 05:40
  • 3
    4) Please learn common Java nomenclature (naming conventions - e.g. `EachWordUpperCaseClass`, `firstWordLowerCaseMethod()`, `firstWordLowerCaseAttribute` unless it is an `UPPER_CASE_CONSTANT`) and use it consistently. 5) Consider using a factory method to configure these buttons. Using the method's arguments, pass the button text and both icons / icon paths. – Andrew Thompson Dec 13 '20 at 05:55
  • Very sorry for my mistakes in putting images and naming, and thanks for all those who helped to edit. And also sorry for being too busy to not check out the answers as soon as possible. I have picked the best solution now, and it's very easy and clear. Hope it can help others who have similar problems! – Shuxin Dec 15 '20 at 11:14

3 Answers3

1

I took your code snippet and put it in a GUI I created.

Here's what I came up with.

Cutsom Button GUI

Now, it's not a very responsive button. You can't tell whether it's pressed or not.

What I did was comment out all of the unusual JButton methods and made sure I could display an ordinary JButton.

Then I uncommented out one line at a time and tested.

Test, test, test.

Here's the code I tested with.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class CustomButtonGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CustomButtonGUI());
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Custom Button");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createButtonPanel(), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setPreferredSize(new Dimension(300, 100));
        
        Font font = panel.getFont().deriveFont(48f);
        
        JButton saveButton = new JButton("Save");
        saveButton.setFont(font);
        saveButton.setOpaque(false);
        saveButton.setContentAreaFilled(false);
        saveButton.setBorder(null);
        saveButton.setMargin(new Insets(0, 0, 0, 0));
//      saveButton.setIcon(new ImageIcon("src/Pic2/menubtn0.png"));
//      saveButton.setPressedIcon(new ImageIcon("src/Pic2/menubtn1.png"));
//      
        panel.add(saveButton, BorderLayout.CENTER);
        
        return panel;
    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111
  • 2
    Just out of interest how does this answer the OPs question? You commented out the 2 lines which OP said was causing the issue? So not sure on the point of the answer – David Kroukamp Dec 13 '20 at 15:25
  • 1
    @David Kroukamp: The question, at the time of this comment, is "How to set text on a self-customized JButton?" I displayed text on a customized JButton. If the OP wants me to use images. the OP has to provide images. Anyway, my answer stands. Test, test, test, test. – Gilbert Le Blanc Dec 13 '20 at 16:20
  • Ah I see... okay cool was just wondering mate! Thanks for the clarification. And yup test, debug, comment out and test some more the life of programming lol. +1 – David Kroukamp Dec 13 '20 at 16:22
1

I think you are using the JButton wrong, the setIcon and setPressedIcon is literally for an icon next to the JButton, however, for a game you probably want the background to change when pressed from one image to another, which by default the JButton class does not support.

Here is a custom JButton I made that allows exactly this:

enter image description here

CustomJButton.java:

import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.swing.JButton;

public class CustomJButton extends JButton {

    private final BufferedImage normalIcon;
    private final BufferedImage selectedIcon;

    public CustomJButton(BufferedImage normalImage, BufferedImage selectedImage) {
        super();
        setOpaque(false);
        setContentAreaFilled(false);
        setBorder(null);
        setFocusPainted(false);
        setMargin(new Insets(0, 0, 0, 0));
        this.normalIcon = normalImage;
        this.selectedIcon = selectedImage;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(normalIcon.getWidth(), normalIcon.getHeight());
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        // lets anti-alias for better quality
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        // lets anti-alias for text too
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // lets draw the correct image depending on if the button is pressed or not
        if (getModel().isPressed()) {
            g2d.drawImage(selectedIcon, 0, 0, getWidth(), getHeight(), this);
        } else {
            g2d.drawImage(normalIcon, 0, 0, getWidth(), getHeight(), this);
        }

        // calc string x and y position
        Font font = getFont();
        String text = getText();
        FontMetrics metrics = g2d.getFontMetrics(font);
        int textWidth = metrics.stringWidth(text);
        int textHeight = metrics.getHeight();
        int textY = getWidth() / 2 - textWidth / 2;
        int textX = getHeight() / 2 - textHeight / 2 + metrics.getAscent();

        // draw the text
        g2d.drawString(text, textY, textX);
    }
}

Which you would then use like this:

CustomJButton button = new CustomJButton(ImageIO.read(new URL("https://i.stack.imgur.com/xCGQQ.png")), ImageIO.read(new URL("https://i.stack.imgur.com/R9i1s.png")));
button.setFont(new Font("Jokerman", Font.BOLD, 22));
button.setForeground(Color.WHITE);
button.setText("Press Me!");
button.addActionListener((ActionEvent e) -> {
    JOptionPane.showMessageDialog(frame, "You pressed me");
});
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
1

The text did not appear and a white line occured at the right side

I suspect your issue is that you are not using layout managers (or you are manually setting the preferred size of your button) and the size of your button is incorrect and the text is being truncated.

By default the text will appear to the right of the Icon. So what you see is your Icon and then the gap between the Icon and the text.

You need to configure the button for the text to display centered on top the Icon (not right of the Icon):

JButton button = new JButton( "Save" );
button.setIcon(...);
button.setPressedIcon(...);   
button.setHorizontalTextPosition(JLabel.CENTER);
button.setVerticalTextPosition(JLabel.CENTER);
camickr
  • 321,443
  • 19
  • 166
  • 288