简体   繁体   中英

Adding Canvas on JPanel on JFrame

I hope the title wasn´t too confusing. First off, I am still a beginner, I only started learning java a few months ago and didn´t start working with graphic components until a few weeks ago. Here is my problem: I got a JFrame as a container and then a Canvas "canvas" to store BufferedImages and JPanel "bPanel" to hold three JButtons. For some reason, even though I used bPanel.setOpaque(false) and/or bPanel.setBackground(new Color(0, 0, 0, 0) the JPanel would still block the Canvas, no matter which one I add first and which one I add second, no matter if I add the Canvas onto the JFrame or the JPanel. I looked around the internet for hours and tried at least 5 different solutions that did not work. For some reason, I can´t get loading images through a JPanel to work, probably because my display class is not extending anything. Anyway, let´s continue: Here is the code I have (yes I know I could go for Display extends JFrame but that doesn´t solve the problem, I already tried that).

public class Display {

private Game game;

private JFrame frame;
private Canvas canvas;
private JPanel bPanel;

private String title;
private int width, height;

private JButton stand, draw, reset;
private Icon drawIMG, standIMG, resetIMG;
private int bwidth, bheight;

public Display(String title, int width, int height) {

    this.title = title;
    this.width = width;
    this.height = height;

    createDisplay();

}

private void createDisplay() {

    frame = new JFrame(title);
    frame.setSize(width, height);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    canvas = new Canvas();
    canvas.setPreferredSize(new Dimension(width, height));
    canvas.setMaximumSize(new Dimension(width, height));
    canvas.setMinimumSize(new Dimension(width, height));
    canvas.setFocusable(false);

    bPanel = new JPanel();
    bPanel.setSize(width, height);
    bPanel.setPreferredSize(new Dimension(width, height));
    //bPanel.setOpaque(false);
    bPanel.setBackground(new Color(0, 0, 0, 0));
    bPanel.setLayout(null);

    drawIMG = new ImageIcon(this.getClass().getResource("/textures/button_draw.png"));
    standIMG = new ImageIcon(this.getClass().getResource("/textures/button_stand.png"));
    resetIMG = new ImageIcon(this.getClass().getResource("/textures/button_reset.png"));
    draw = new JButton(drawIMG);
    stand = new JButton(standIMG);
    reset = new JButton(resetIMG);
    draw.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent drawClicked) {
            if (game.getPhase() == 1)
                game.playerDraw();
        }
    });
    stand.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent standClicked) {
            if (game.getPhase() == 1)
            {
                game.setPhase(2);
                removeButtons();
            }
        }
    });
    reset.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent resetClicked) {
            game.reset();
        }
    });
    bwidth = 300;
    bheight = 100;
    //bPanel.add(new JLabel(new ImageIcon(getClass().getResource("/textures/background.png"))), BorderLayout.CENTER);
    addButton(draw);
    addButton(stand);
    addButton(reset);
    draw.setBounds(100, ((height/2)-(bheight/2)), bwidth, bheight);
    stand.setBounds(((width-100)-bwidth), ((height/2)-(bheight/2)), bwidth, bheight);
    reset.setBounds(((width/2)-40), (height-120), 80, 80);

    frame.add(canvas);
    frame.add(bPanel);
    frame.pack();

}

public void showImage(String path) {

    JLabel jl = new JLabel();
    jl.setIcon(new javax.swing.ImageIcon(getClass().getResource(path)));
    frame.add(jl);
    frame.repaint();

}

public void setGame(Game game) {
    this.game = game;
}

public void addButton(JButton button) {
    bPanel.add(button);
    bPanel.setLayout(null);
}

public void showButtons() {
    draw.setVisible(true);
    stand.setVisible(true);
}

public void removeButtons() {
    draw.setVisible(false);
    stand.setVisible(false);
}

public void removePanel(JPanel panel) {
    frame.remove(panel);
}

public Canvas getCanvas() {
    return canvas;
}

public JFrame getFrame() {
    return frame;
}

public JPanel getBPanel() {
    return bPanel;
}

}

In this try of mine for example the picture was only displayed after the JButton "stand" was pressed:

public void showImage(String path) {

    JLabel jl = new JLabel();
    jl.setIcon(new javax.swing.ImageIcon(getClass().getResource(path)));
    frame.add(jl);
    frame.repaint();

}

I am pretty desperate bc I spent many hours trying to figure out a solution to load graphics in. Thanks for help in advance:D

Several issues:

  1. Don't use a null layout. Swing was designed to be using with layout managers.
  2. The default layout manager for a JFrame is a BorderLayout. If you don't specify a constraint, the component is added to the CENTER. Only one component can be displayed in the CENTER. So you can't just keep adding components to the frame. You need to have a parent/child hierarchy.
  3. Don't use a Canvas. That is an AWT component. If you want to do custom painting in Swing you can use the JPanel

So your code might be something like:

//addButton(draw);
//addButton(stand);
//addButton(reset);
bPanel(draw);
bPanel(stand);
bPanel(reset);

The default layout manager for a JPanel is a FlowLayout. So the buttons will be added from left to right and centered on the panel.

//frame.add(bPanel);
frame.add(bPanel, BorderLayout.PAGE_START);

Now all the buttons will be added at the top of the frame.

//private Canvas canvas;
private JPanel canvas;
….
//canvas = new Canvas();
canvas = new JPanel(new BorderLayout());
…
//frame.add(canvas);
frame.add(canvas, BorderLayout.CENTER);

Now the "canvas" will be added to the CENTER of the BorderLayout of the frame, which means it will take up all the space not used by the button panel.

public void showImage(String path) {

    JLabel jl = new JLabel();
    jl.setIcon(new javax.swing.ImageIcon(getClass().getResource(path)));
    frame.add(jl);
    frame.repaint();

}

You can't add the image directly to the frame because you have already added other components to the frame. Instead use:

    //frame.add(jl);
    //frame.repaint();
    canvas.add(jl);
    canvas.repaint();

So the image is added to the canvas which is added to the frame so you have a parent/child hierarchy.

//draw.setBounds(100, ((height/2)-(bheight/2)), bwidth, bheight);
//stand.setBounds(((width-100)-bwidth), ((height/2)-(bheight/2)), bwidth, bheight);
//reset.setBounds(((width/2)-40), (height-120), 80, 80);

Above code is not needed, since it is the job of the layout manager to set the size and location of each component based on the rules of the layout manager.

So basically you need to start over and learn some Swing basics. Maybe the Swing tutorial will help. There are demos of how to use each of the layout managers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM