Search code examples
javaswinggraphics2d

Java - How to properly add several panels with background image?


I'm trying to code a puzzle game in which content is displayed in two different panels:

-SplitTable: In this panel a couple of labels will display some relevant data. Half the size of SplitPanel and vertical, in the left side of screen.

-SplitPanel:Here a puzzle will be displayed in a panel which will be on top of the existing image.

-SplitMainView: Here everything is put together

-SplitCustomPanel: The code for the custom panels

Apparently everything works fine, but if you look closely and add some borders to the panels, you see that there is being an overlap of some sort.

What should i do to fix this and make them take the correct space?

public SplitTable(SplitModel model){
    this.model = model;
    setLayout(new GridLayout(1,6));

    java.net.URL urls = ClassLoader.getSystemResource("Imagenes/vertical.jpg");
    Toolkit kit = Toolkit.getDefaultToolkit();
    Image back = kit.createImage(urls);
    p = new SplitCustomPanel(back, 346, 900, 0, 0);
    p.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, true));
    la1 = new JLabel(" ");
    la2 = new JLabel(" ");
    la3 = new JLabel(" ");
    la4 = new JLabel(" ");
    la5 = new JLabel(" ");
    la6 = new JLabel(" ");
    p.add(la1);
    p.add(la2);
    p.add(la3);
    p.add(la4);
    p.add(la5);
    p.add(la6);
    add(p);}


public SplitPanel(SplitModel model){
    this.model = model;

    setLayout(new GridLayout(1,6));

    java.net.URL urls = ClassLoader.getSystemResource("Imagenes/tap1.jpg");
    Toolkit kit = Toolkit.getDefaultToolkit();
    Image back = kit.createImage(urls);
    p = new SplitCustomPanel(back, 1200, 900, 300, 0);
    p.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2, true));        
    la1 = new JLabel(" ");
    la2 = new JLabel(" ");
    la3 = new JLabel(" ");
    la4 = new JLabel(" ");
    la5 = new JLabel(" ");
    la6 = new JLabel(" ");
    p.add(la1);
    p.add(la2);
    p.add(la3);
    p.add(la4);
    p.add(la5);
    p.add(la6);  
    add(p);}

public SplitMainView(SplitModel model){
    super("Splitter");

    java.net.URL urls = ClassLoader.getSystemResource("Imagenes/ese.jpg");
    Toolkit kit = Toolkit.getDefaultToolkit();
    Image imgs = kit.createImage(urls);
    this.setIconImage(imgs);

    this.model = model;
    JPanel p = new JPanel();

    p.setLayout(new GridBagLayout());

    GridBagConstraints ct = new GridBagConstraints();
    GridBagConstraints cp = new GridBagConstraints();

    ct.fill = GridBagConstraints.BOTH;
    cp.fill = GridBagConstraints.BOTH;

    ct.weightx = 1.0;
    ct.weighty = 1.0;
    cp.weightx = 1.0;
    cp.weighty = 1.0;

    ct.gridheight = 8;
    ct.gridwidth = 2;
    ct.gridx = 0;
    ct.gridy = 0;
    cp.gridheight = 8;
    cp.gridwidth = 8;
    cp.gridx = 0;
    cp.gridy = 2;

    menu = new SplitMenuBar();
    panel = new SplitPanel(model);
    table = new SplitTable(model);

    this.setJMenuBar(menu);
    p.add(table, ct);
    p.add(panel, cp);
    this.add(p);


    setVisible(true);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);

public class SplitCustomPanel extends JPanel {

private Image back;
private int w;
private int h;
private int x;
private int y;

public SplitCustomPanel(Image backe, int w, int h, int x, int y) {
    this.back = backe;
    this.w = w;
    this.h = h;
    this.x = x;
    this.y = y;
}


@Override
public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.drawImage(back, x, y, w, h, this);
}

This is how it looks like: https://i.sstatic.net/An0hg.jpg


Solution

  • As shown here, use getSubimage() to slice a pristine image along pixel boundaries. In the example, resize the frame to see how the borderless components align. Use drawImage() to merge the pieces, only if required. If so, invoke super.paintComponent() to avoid rendering artifacts.