Java Swing: How to set text on a self customized Jbutton? - java

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 :
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");
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:

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);

I took your code snippet and put it in a GUI I created.
Here's what I came up with.
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;
}
}

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:
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");
});

Related

Swing Java Rotate JLabel but text be erased

I'm using swing Java to try to do something with java. Now I want to rotate JLabel and I did that. But unfortunelately, a part of my text in JLabel is erased (as in the image below). I have tried search but seem no one has problems as same as mine. I guess it's occured caused JLabels they overlaped.
and this is my code
serviceName[j] = new JLabel(name){
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
AffineTransform aT = g2.getTransform();
Shape oldshape = g2.getClip();
aT.rotate(Math.toRadians(300));
g2.setTransform(aT);
g2.setClip(oldshape);
super.paintComponent(g);
}
};
Can you give me the way to solved it
You should restore original transform and clip after your painting. Like this
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
AffineTransform aT = g2.getTransform();
Shape oldshape = g2.getClip();
g2.rotate(Math.toRadians(300));
super.paintComponent(g);
g2.setTransform(aT);
g2.setClip(oldshape);
}
Your JLabel subclass should also override getPreferredSize() to report the size it will be when it is rotated; otherwise the any layout manager that uses asks your component for its preferred size will use JLabel's version, which assumes the text is drawn horizontally.
Instead of attempting to rotate the component, another approach would be to create a Text Icon and add the Icon to a JLabel.
Once you have created the TextIcon you can then create a Rotated Icon to add to the label. The RotatedIcon will calculate the proper size of the Icon so therefore the size of the label will also be correct and no custom painting is required.
So the basic code would be something like:
JLabel label = new JLabel();
TextIcon textlIcon = new TextIcon(label, "Rotated Text");
label.setIcon( new RotatedIcon(textIcon, 300) );
Edit:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.border.*;
import javax.swing.table.*;
import java.io.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
OverlapLayout layout = new OverlapLayout(new Point(20, 0));
setLayout( layout );
addLabel("one");
addLabel("two");
addLabel("three or more");
addLabel("four");
}
private void addLabel(String text)
{
JLabel label = new JLabel();
TextIcon textIcon = new TextIcon(label, text);
label.setIcon( new RotatedIcon(textIcon, 300) );
label.setVerticalAlignment(JLabel.BOTTOM);
add(label);
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
This example also uses the Overlap Layout so the labels can be painted over top of one another.
You may find some hints from this small program. Experiment on the values of setPrefferedSize to have more ideas. If you still can't solve the problem, please edit and add more codes in your question above.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import javax.swing.*;
public class InclinedLabels extends JFrame{
/** Creates a new instance of InclinedLabels */
public InclinedLabels() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel jPanel1 = new JPanel();
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
add(jPanel1);
JPanel jPanel2 = new JPanel();
jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
jPanel2.setPreferredSize(new Dimension(10, 100));
add(jPanel2, BorderLayout.NORTH);
jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
jPanel1.setPreferredSize(new java.awt.Dimension(200, 200));
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-400)/2, (screenSize.height-352)/2, 300, 352);
String str = "The quick brown fox jumps over the lazy dog";
String[] word = str.split(" ");
JLabel[] serviceName = new JLabel[str.length()];
String name;
for (int j=0; j<word.length; j++) {
name = word[j];
serviceName[j] = new JLabel(name){
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
AffineTransform aT = g2.getTransform();
Shape oldshape = g2.getClip();
aT.rotate(Math.toRadians(300));
g2.setTransform(aT);
g2.setClip(oldshape);
super.paintComponent(g);
}
};
serviceName[j].setPreferredSize(new Dimension(50,20));
serviceName[j].setBorder(BorderFactory.createLineBorder(Color.RED));
jPanel1.add(serviceName[j]);
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new InclinedLabels().setVisible(true);
}
});
}
}
Update:
I found a much closer hint that may solve this problem. The big factor here is the component layout. The null layout allows overlapping of JLabel components so it is the most appropriate layout to be used here. Then you have to customize the location and size of the labels through the setBounds method. In the code below there is serviceName[j].setBounds(xOffset + j*20,180, 170, 15); So in every loop iteration, the x location of the label is increased by 20. The size of all labels is 170 by 15. I also placed temporary borders to the components to help in understanding the output.
import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
public class InclinedLabels extends JFrame{
/** Creates a new instance of InclinedLabels */
public InclinedLabels() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-360)/2, (screenSize.height-352)/2, 360, 352);
JPanel jPanel1 = new JPanel();
jPanel1.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
jPanel1.setLayout(null); // null layout allows overlapping of components
add(jPanel1);
JPanel jPanel2 = new JPanel();
jPanel2.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
jPanel2.setPreferredSize(new Dimension(10, 100));
add(jPanel2, BorderLayout.NORTH);
String str = "The quick brown fox jumpsssssssssssss123456 over the lazy dogssssssssssssss123456";
String[] word = str.split(" ");
JLabel[] serviceName = new JLabel[str.length()];
String name;
int xOffset = 30;
for (int j=0; j<word.length; j++) {
name = word[j];
serviceName[j] = new JLabel(name){
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
AffineTransform aT = g2.getTransform();
Shape oldshape = g2.getClip();
aT.rotate(Math.toRadians(300));
g2.setTransform(aT);
g2.setClip(oldshape);
super.paintComponent(g2);
}
};
serviceName[j].setBounds(xOffset + j*20,180, 170, 15); // experiment here
serviceName[j].setBorder(BorderFactory.createLineBorder(Color.RED));
jPanel1.add(serviceName[j]);
}
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new InclinedLabels().setVisible(true);
}
});
}
}
The limitation that I found in the code above is the width of the parent panel. In the example, the label having the text dogssssssssssssss123456 was not printed in whole. This can be overcome by increasing the width of the frame which in turn increases the width of jPanel1.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
public class Test {
public static void main(String[] args) {
// Create the first label, which will be rotated later.
Test.RotateLabel one = new Test.RotateLabel( "Rotated", 100, 100 );
one.setRotation( 270 );
JLayeredPane pane = new JLayeredPane();
pane.setLayer( one, JLayeredPane.DEFAULT_LAYER );
pane.add( one );
pane.setBorder(new javax.swing.border.LineBorder(Color.BLACK,1));
// Put the container pane in a frame and show the frame.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( pane );
frame.setSize( 500, 500 );
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
static class RotateLabel extends JLabel {
private static final long serialVersionUID = 1L;
private int angle = 0;
public RotateLabel( String text, int x, int y ) {
super( text );
setBorder( new javax.swing.border.CompoundBorder(
new javax.swing.border.LineBorder( Color.red, 1), getBorder() ) );
int width = getPreferredSize().width;
int height = getPreferredSize().height;
setBounds(x, y, width, height);
}
#Override
public void paintComponent( Graphics g ) {
Graphics2D gx = (Graphics2D) g;
Shape old = gx.getClip();
gx.rotate(-Math.toRadians(45), getWidth() / 2, getHeight() / 2);
gx.setClip(old);
super.paintComponent(gx);
}
public void setRotation( int angle ) { this.angle = angle; }
}

How to make a jPanel semi transparent?

I want to add a jPanel which is semi transparent. But other components which are placed inside the jPanel such as buttons and labels should be displayed with 100% opacity. I am using netbeans to design the GUIs. Normally i drag and drop the swing components in the palette to design the GUI(I don't code them). I can't see any property in properties window to achieve this. Please help me. As I am quite new to java please give me a detailed answer. Thanks in advance.
You can use
JPanel.setBackground(Color bg);
to make the panel semi-transparent. What matter is the color's property.
You can construct a color with alpha values to set the transparent degree of the color.
panel.setBackground(new Color(213, 134, 145, 123));
The last parameter is actual the alpha value and you can adjust it to see the effect.
Here is the code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class PanelTest {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
PanelTest test = new PanelTest();
test.createUI();
}
};
SwingUtilities.invokeLater(runnable);
}
public void createUI(){
JFrame frame = new JFrame("Panel Test");
JPanel panel = new JPanel();
panel.setBackground(new Color(213, 134, 145, 123));
JButton button = new JButton("I am a button");
JLabel label = new JLabel("I am a label");
label.setFont(new Font("Arial", Font.BOLD, 15));
JTextField textField = new JTextField();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(button);
panel.add(Box.createVerticalStrut(20));
panel.add(label);
panel.add(Box.createVerticalStrut(20));
panel.add(textField);
panel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
BottomPanel buttomPanel = new BottomPanel();
buttomPanel.add(panel);
frame.add(buttomPanel,BorderLayout.CENTER);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#SuppressWarnings("serial")
class BottomPanel extends JPanel{
#Override
protected void paintComponent(Graphics g) {
for (int y = 0; y < 200; y = y + 20) {
g.drawString("I am the string on the bottom", 5, y);
}
}
}
}
Here is the effect and hope it can help you.
You can simply create your jPanel using drag and drop, as you always do and then for changing the panel's color and making it transparent or semi-transparent you can use this code:
panel.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.5f));
You can change the color by changing first three parameters of Color constructor, which represent RGB and you can change transparency by changing fourth parameter, which is the alpha value of color.

Some readability problems when a JLabel is on a background inmmage of a JPanel in Swing, how to solve?

I am very new in Java Swing develompment and I have the following problem.
I have to create a JFrame window that have a background immage.
So I have perform the following operation to do it:
1) I have create a class named JPanelWithBackground that extends JPanel:
package com.test.login;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class JPanelWithBackground extends JPanel {
private Image backgroundImage;
// Some code to initialize the background image.
// Here, we use the constructor to load the image. This
// can vary depending on the use case of the panel.
public JPanelWithBackground(String fileName) throws IOException {
backgroundImage = ImageIO.read(new File(fileName));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw the background image.
// g.drawImage(backgroundImage, 0, 0, this);
g.drawImage(backgroundImage, 0, 0, 550, 230, this);
}
}
As you can see this class read an immage file and put its reference into an Image object named backgroundImage and then draw it on a Graphics object.
2) Then I have create a class named LoginFrame2:
package com.test.login;
import javax.swing.JButton;
import java.awt.Container;
import java.awt.Dimension;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu.Separator;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import net.miginfocom.swt.MigLayout;
import org.jdesktop.application.SingleFrameApplication;
public class LoginFrame2 extends SingleFrameApplication {
private static final int FIXED_WIDTH = 550;
private static final Dimension INITAL_SIZE = new Dimension(FIXED_WIDTH, 230);
public static void main(String[] args) {
System.out.println("DENTRO: LoginFrame() ---> main()");
launch(LoginFrame2.class, args);
}
#Override
protected void startup() {
// TODO Auto-generated method stub
System.out.println("Inside startup()");
JFrame mainFrame = this.getMainFrame(); // main JFrame that represents the Windows
mainFrame.setTitle("Chilli Login");
mainFrame.setPreferredSize(INITAL_SIZE);
mainFrame.setResizable(false);
Container mainContainer = mainFrame.getContentPane(); // main Container into the main JFrame
// JPanel creation and settings of the MigLayout on it:
// JPanel externalPanel = new JPanel();
JPanelWithBackground externalPanel = null;
try {
externalPanel = new JPanelWithBackground("/home/andrea/Immagini/logo2.jpg");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
externalPanel.setLayout(new net.miginfocom.swing.MigLayout("fill"));
externalPanel.add(new JLabel("Username"), "w 50%, wrap");
JTextField userNameTextField = new JTextField(20);
externalPanel.add(userNameTextField, "w 90%, wrap");
externalPanel.add(new JLabel("Password"), "w 50%, wrap");
JTextField pswdTextField = new JTextField(20);
externalPanel.add(pswdTextField, "w 90%, wrap");
JButton loginButton = new JButton("Login");
externalPanel.add(loginButton, "w 25%, wrap");
mainContainer.add(externalPanel);
//mainFrame.add(mainContainer);
show(mainFrame);
}
}
This class extends SingleFrameApplication abstract class of the JDesktop Swin framework that provide me a JFrame istance.
This class simply create the JPanelWithBackground object by the line:
externalPanel = new JPanelWithBackground("/home/andrea/Immagini/logo2.jpg");
and put in this object some Swing component.
This is my result:
My doubt/problem is: as you can see the JLabel that show the string Password is on the red part of the immage (of my chilli logo) and so is not very readable.
What can I do to make it more readable? For example can I set in some way that the background of my JLabel have to be white?
Tnx
Andrea
You could set the background of the JLabel, but that would look ugly. I would suggest just changing the foreground of only the Password label to be white. Possibly increase the size of font of both labels as well to help readability.
JLabel password = new JLabel("Password");
password.setForeground(Color.WHITE);
More extreme mods: would be to extend the label to output white text that is outlined by black, or to use images for the words in nice fonts that have transparency.
EDIT:
Here is how to set the background to white.
password.setBackground(Color.WHITE);
password.setOpaque(true);
You could change the opacity of the back ground image...
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g.create();
// Draw the background image.
// g.drawImage(backgroundImage, 0, 0, this);
g2d.setComposite(AlphaComposite.SrcOvr.derive(0.5f));
g2d.drawImage(backgroundImage, 0, 0, 550, 230, this);
g2d.dispose();
}

Removing borders on custom buttons

I've written this small program which attempts to create a custom JButton unfortunately I can't manage to remove the border. I thought button.setBorder(null); would remove it but this has been ineffective. Does anyone know how to remove the border from the button so it's just the icon? Any help greatly appreciated.
My code is as follows:
package custombuttons;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CustomButtons {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
CustomButtons h = new CustomButtons();
h.setUp();
}
JFrame frame;
JPanel panel;
JButton button;
BufferedImage b;
String toolTip = "Configure";
public void setUp() {
frame = new JFrame("Custom Buttons");
try {
b = ImageIO.read(CustomButtons.class.getResource("/images/config.png"));
} catch (IOException ex) {
Logger.getLogger(CustomButtons.class.getName()).log(Level.SEVERE, null, ex);
ex.printStackTrace();
}
Image b1 = (Image) b;
ImageIcon iconRollover = new ImageIcon(b1);
int w = iconRollover.getIconWidth();
int h = iconRollover.getIconHeight();
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
Image image = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g = (Graphics2D) image.getGraphics();
g.drawImage(iconRollover.getImage(), 0, 0, null);
g.dispose();
ImageIcon iconDefault = new ImageIcon(b1);
image = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
g = (Graphics2D) image.getGraphics();
g.drawImage(iconRollover.getImage(), 2, 2, null);
g.dispose();
ImageIcon iconPressed = new ImageIcon(b1);
JButton button = new JButton();
button.setIgnoreRepaint(true);
button.setFocusable(false);
button.setToolTipText(toolTip);
button.setBorder(null);
button.setContentAreaFilled(false);
button.setIcon(iconDefault);
button.setRolloverIcon(iconRollover);
button.setPressedIcon(iconPressed);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
panel = new JPanel();
panel.setOpaque(false);
panel.add(button);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
}
have look at button.setBorderPainted(false) more about JButton here
actually i tested your code on my Netbeans IDE and got no borders as you desire
using only button.setBorder(null); or button.setBorderPainted(false); or both of them but
i think you should make sure that your original image is really do not have any borders it self

Swing: vertically stacked components without MigLayout

I finally got the behavior I want for vertically stacking components that have a preferred height that changes with time. But I needed to use MigLayout.
Is there a way to do this w/o MigLayout? (It's for a library and I don't want to force the dependency unless I have to)
Here's the behavior I'm looking for (which my test program achieves):
In vertical order, there's a resize button, "empty space" (well, a JLabel marked as such), a red rectangle, and a green square. The resize button has fixed height. The red square has a random size that can change at arbitrary times. The green square sets its preferred height to match its width, and I want to expand its width to fill the container. The empty space expands horizontally and vertically to fill the remaining space in the container.
What would work instead of MigLayout?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class AutoResizeDemo extends JPanel
{
static private class ResizingPanel extends JPanel
{
final private Color color;
private Dimension dpref = new Dimension(100,100);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(this.color);
g.fillRect(0, 0, w, h);
g.setColor(Color.BLACK);
g.drawRect(0, 0, w-1, h-1);
String s = this.dpref.width+"x"+this.dpref.height;
FontMetrics fm = g.getFontMetrics();
g.drawString(s, 0, fm.getHeight());
}
public ResizingPanel(Color color, boolean isSquare)
{
this.color = color;
if (isSquare)
{
addComponentListener(new ComponentAdapter() {
#Override public void componentResized(ComponentEvent e) {
doResize(getWidth(), getWidth());
}
});
}
}
#Override public Dimension getPreferredSize() {
return this.dpref;
}
public void doResize(int w, int h)
{
this.dpref = new Dimension(w, h);
revalidate();
}
}
public AutoResizeDemo()
{
super(new MigLayout("","[grow]",""));
setPreferredSize(new Dimension(200, 800));
final ResizingPanel resizingPanelRandom = new ResizingPanel(Color.RED, false);
ResizingPanel resizingPanelSquare = new ResizingPanel(Color.GREEN, true);
JPanel buttonPanel = new JPanel(new FlowLayout());
final Random rand = new Random();
addButton(buttonPanel, "resize",new Runnable() {
#Override public void run() {
resizingPanelRandom.doResize(
rand.nextInt(100)+100,
rand.nextInt(100)+100
);
}
});
add(buttonPanel, "wrap");
JLabel spaceLabel = new JLabel("empty space");
spaceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(spaceLabel, "push, grow, wrap");
add(resizingPanelRandom, "wrap");
add(resizingPanelSquare,"pushx, growx, wrap");
}
private void addButton(JPanel panel, String title, final Runnable r) {
JButton button = new JButton(title);
button.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
r.run();
}
});
panel.add(button);
}
public static void main(String[] args) {
JFrame frame = new JFrame(AutoResizeDemo.class.getSimpleName());
frame.setContentPane(new AutoResizeDemo());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Use a BoxLayout.
You would use Box.createVerticalGlue() for the empty space.
BoxLayout respects the maximum size of a component, so you would probably need to override the getMaximumSize() method to return the preferred size for the red and green boxes.
For the green box you would also need to Override getPreferredSize() to keep the height in sync with the width.
You can solve this using SpringLayout by wiring all your compenents together and to the edges of their container.
Button Panel
left and top of the button panel to left and top of the container panel
Green Panel
left, right and bottom to the left, right and bottom of the container panel
Red Panel
left to left of container panel and bottom to top of the green panel
Space Label
top to south of the button panel, left and right to left and right of the container panel, bottom to top of the red panel
Edit: I love SpringLayout, there's nothing it can't do.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
public class AutoResizeDemo2 extends JPanel {
static private class ResizingPanel extends JPanel {
final private Color color;
private Dimension dpref = new Dimension(100, 100);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(this.color);
g.fillRect(0, 0, w, h);
g.setColor(Color.BLACK);
g.drawRect(0, 0, w - 1, h - 1);
String s = this.dpref.width + "x" + this.dpref.height;
FontMetrics fm = g.getFontMetrics();
g.drawString(s, 0, fm.getHeight());
}
public ResizingPanel(Color color, boolean isSquare) {
this.color = color;
if (isSquare) {
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
doResize(getWidth(), getWidth());
}
});
}
}
#Override
public Dimension getPreferredSize() {
return this.dpref;
}
public void doResize(int w, int h) {
this.dpref = new Dimension(w, h);
revalidate();
}
}
public AutoResizeDemo2() {
SpringLayout layout = new SpringLayout();
setLayout(layout);
setPreferredSize(new Dimension(200, 800));
final ResizingPanel resizingPanelRandom = new ResizingPanel(Color.RED, false);
ResizingPanel resizingPanelSquare = new ResizingPanel(Color.GREEN, true);
JPanel buttonPanel = new JPanel(new FlowLayout());
final Random rand = new Random();
addButton(buttonPanel, "resize", new Runnable() {
#Override
public void run() {
resizingPanelRandom.doResize(rand.nextInt(100) + 100, rand.nextInt(100) + 100);
}
});
add(buttonPanel);
layout.putConstraint(SpringLayout.NORTH, buttonPanel, 5, SpringLayout.NORTH, this);
layout.putConstraint(SpringLayout.WEST, buttonPanel, 5, SpringLayout.WEST, this);
JLabel spaceLabel = new JLabel("empty space");
spaceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
add(resizingPanelSquare);
layout.putConstraint(SpringLayout.SOUTH, resizingPanelSquare, -5, SpringLayout.SOUTH, this);
layout.putConstraint(SpringLayout.WEST, resizingPanelSquare, 5, SpringLayout.WEST, this);
layout.putConstraint(SpringLayout.EAST, resizingPanelSquare, -5, SpringLayout.EAST, this);
add(resizingPanelRandom);
layout.putConstraint(SpringLayout.SOUTH, resizingPanelRandom, -5, SpringLayout.NORTH, resizingPanelSquare);
layout.putConstraint(SpringLayout.WEST, resizingPanelRandom, 5, SpringLayout.WEST, this);
add(spaceLabel);
layout.putConstraint(SpringLayout.NORTH, spaceLabel, 5, SpringLayout.SOUTH, buttonPanel);
layout.putConstraint(SpringLayout.WEST, spaceLabel, 5, SpringLayout.WEST, this);
layout.putConstraint(SpringLayout.EAST, spaceLabel, -5, SpringLayout.EAST, this);
layout.putConstraint(SpringLayout.SOUTH, spaceLabel, -5, SpringLayout.NORTH, resizingPanelRandom);
}
private void addButton(JPanel panel, String title, final Runnable r) {
JButton button = new JButton(title);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
r.run();
}
});
panel.add(button);
}
public static void main(String[] args) {
JFrame frame = new JFrame(AutoResizeDemo2.class.getSimpleName());
frame.setContentPane(new AutoResizeDemo2());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
SpringLayout is difficult to determine how it is laid out without a lot of analyzing. Try TableLayout. The only tricky part of your layout is the green square's height being equal to its width. This is a bit unusual for a layout manager to support, so I would just special case it. A runnable example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.esotericsoftware.tablelayout.swing.Table;
public class Test extends JFrame {
JButton button;
JPanel red, green;
public Test () {
button = new JButton("Resize");
button.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
red.setPreferredSize(new Dimension(138, new Random().nextInt(190) + 10));
red.revalidate();
}
});
red = new JPanel();
red.setPreferredSize(new Dimension(138, 145));
red.setBackground(Color.red);
green = new JPanel();
green.setPreferredSize(new Dimension(100, 100));
green.setBackground(Color.green);
// The DSL can be much easier to describe complex hierarchies.
boolean dsl = false;
if (dsl)
dsl();
else
javaApi();
setSize(160, 400);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
private void javaApi () {
final Table table = new Table() {
public void layout () {
green.setPreferredSize(new Dimension(getWidth(), getWidth()));
super.layout();
}
};
table.pad(10).defaults().left().space(5);
table.addCell(button);
table.row();
table.addCell().expandY();
table.row();
table.addCell(red);
table.row();
table.addCell(green).expandX().fillX();
getContentPane().add(table);
}
private void dsl () {
final Table table = new Table() {
public void layout () {
green.setPreferredSize(new Dimension(getWidth(), getWidth()));
super.layout();
}
};
table.register("button", button);
table.register("red", red);
table.register("green", green);
table.parse("pad:10 * left space:5 " //
+ "[button] ---" //
+ "[] expandy ---" //
+ "[red] ---" //
+ "[green] expandx fillx" //
);
getContentPane().add(table);
}
public static void main (String[] args) throws Exception {
new Test();
}
}
Being table based, it is easy to get an idea of the layout at a glance. I included code for using the Java API and also the DSL. The Java API is nice since you get completion. Here is just the layout code:
table.pad(10).defaults().left().space(5);
table.addCell(button);
table.row();
table.addCell().expandY();
table.row();
table.addCell(red);
table.row();
table.addCell(green).expandX().fillX();
The DSL is nice for describing hierarchies, probably not necessary for this example. Unfortunately Java doesn't have a verbatim string, though a large UI could be described in a file. The DSL for this example without the Java string quotes would be:
pad:10 * left space:5
[button]
---
[] expandy
---
[red]
---
[green] expandx fillx

Categories