I am trying to create a JPanel which has 3 components arranged in a line. It should have a coloured box, a label and then a delete button.
I have got a JPanel set as a GridLayout which stores a JPanel for the coloured box, a JLabel for the label and a JButton with a custom ImageIcon.
The problem is that there is a blank space between the coloured box and the label. I have highlighted the borders of each component and no component seems to be overstretched.
Here is a screenshot of what I mean:

Here is the code I am working with:
Label class:
public class Label extends JPanel {
JButton btnDeleteObject;
// Delete icon
ImageIcon delIcon = new ImageIcon("Delete.png");
Image img = delIcon.getImage();
Image newimg = img.getScaledInstance(28, 28, java.awt.Image.SCALE_SMOOTH);
ImageIcon scaledDelIcon = new ImageIcon(newimg);
Color labelColour;
public Label(String labelName, Color labelColour) {
this.labelColour = labelColour;
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
addComponents(labelName);
}
private void addComponents(String labelName) {
JPanel innerContainer = new JPanel(new GridLayout(1, 3));
JLabel name = new JLabel(labelName);
LabelColourBox cBox = new LabelColourBox();
name.setMaximumSize(new Dimension(80, 40));
name.setPreferredSize(new Dimension(80, 40));
name.setSize(new Dimension(80, 40));
name.setBorder(BorderFactory.createLineBorder(Color.blue));
setBorder(BorderFactory.createLineBorder(Color.black));
// name.setBorder(new EmptyBorder(5, 5, 5, 5));
// Add action to delete button for Icon
Action action = new AbstractAction("Button Label", scaledDelIcon) {
// This method is called when the button is pressed
public void actionPerformed(ActionEvent evt) {
System.out.println("delete");
}
};
btnDeleteObject = new JButton(action);
// Remove label, background
btnDeleteObject.setText("");
btnDeleteObject.setContentAreaFilled(false);
setAlignmentX(LEFT_ALIGNMENT);
innerContainer.add(cBox);
innerContainer.add(name);
innerContainer.add(btnDeleteObject);
add(innerContainer);
}
}
and here is the LabelColourBox:
public class LabelColourBox extends JPanel{
public LabelColourBox() {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBorder(BorderFactory.createLineBorder(Color.green));
setMaximumSize(new Dimension(40, 40));
setPreferredSize(new Dimension(40, 40));
setSize(new Dimension(40, 40));
g.setColor(Color.RED);
g.fillRect(0, 0, 40, 40);
}
}
As Guillaume has pointed, there are some serious issues with your code.
NEVER make any changes to ANY UI component from within any
paintXxxmethodDoing so will cause a repaint request to be sent to the repaint manager, which will eventually call your
paintComponentwhich will trigger a repaint request … and say good bye to your CPU as it cycles up to 100% and your program becomes unresponsive.You should avoid calling
setPreferred/Minimum/MaximumSizeas much as possible. Let the individual components work it out. If you’re customizing a component, override these methods, it will stop some way-ward developer from changing the size of the component under you.You should avoid absolute values, especially when painting.
This is very dangerous. What if this component gets added to a
BorderLayout? It will only ever paint a square in the top left corner of your component…not really useful, instead usegetWidthandgetHeightas a bases for the area you need to effect. You also need to take into consideration the componentsInsetsto make sure you content is being painted within the usable visual bounds.This also means you can change the size of the component without needing to rewrite whole sections of code 😛
As to your program. Use a more flexible layout manager.
GridLayoutcreates a uniform grid in which to layout out its components…