简体   繁体   中英

How to add to a JFrame 3 JPanels: The 1st JPanel to take up 90% of the frame, the second to be on skinny top, 3rd to be drawer panel that can close

I am stuck on getting this swing UI to act the way I was hoping. I wrote this demo code to showcase what it is doing and I will now explain what I was hoping to make it do.

I have a JFrame and 3 JPanels

https://i.stack.imgur.com/B82tF.png

I want the JFrame to have an image in the background on the JFrame, like a world map, then on top of that I was trying to have: a top nav bar with buttons, then on top of the map, I want buttons that a player can click on for different areas of the map on the layer below, then I want to have a drawer that opens and closes if the user clicks on the show/hide drawer button that gives info about the action they performed by clicking the buttons.

What I have so far is three panels all aligned side by side and that is not what I want.

How can i get this UI to act like I described above?

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


class TestFrame extends JFrame {

    static JFrame frame;
    static JButton btnExit, btnShowHide;
    static JPanel gridPanel, drawerPanel;

    public static void main(String[] args)
    {

        GridLayout layout = new GridLayout(1,1,0,0);
        frame = new JFrame("Main Frame");
        frame.setLayout(layout);

        // 1: Creating grid panel
        gridPanel = new JPanel();
        gridPanel.setBackground(Color.yellow);

        gridPanel.setLayout(new GridLayout(5, 5, 0, 0));
        gridPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
        gridPanel.setOpaque(false);
        gridPanel.setBorder(BorderFactory.createLineBorder(Color.gray));
        placeButtons();

        // 2: Creating button panel
        JPanel buttonPanel = new JPanel();
        buttonPanel.setBackground(Color.red);

        // add buttons
        btnExit = new JButton("Exit");
        buttonPanel.add(btnExit);
        btnExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                try {

                    System.exit(0);

                } catch (Exception err) {
                    System.out.println("doh");
                }

             

            }
        });

        // 3: Creating button panel
        drawerPanel = new JPanel();
        drawerPanel.setBackground(Color.blue);

        btnShowHide = new JButton("show drawer");
        buttonPanel.add(btnShowHide);
        btnShowHide.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                try {

                    System.out.println("show drawer");
                    drawerPanel.setVisible(true);

                } catch (Exception err) {
                    System.out.println("Could not close the DB: " + err);
                }

                if(btnShowHide.getText().equals("show drawer")){
                    btnShowHide.setText("hide drawer");
                } else{
                    btnShowHide.setText("show drawer");
                    drawerPanel.setVisible(false);
                }

            }
        });

        // Adding panels to frame
        frame.add(gridPanel);
        frame.add(buttonPanel);
        frame.add(drawerPanel);

        frame.setSize(500, 500);
        frame.setVisible(true);
    }


    public static void placeButtons(){

        System.out.println("place buttons");

        int dbx = 0;
        int dby = 0;

        for(int xCnt = 0; xCnt < 5; xCnt++){
            dby = 0;
            for(int yCnt = 0; yCnt < 5; yCnt++) {

                JButton click = new JButton("x:"+xCnt+" y:"+yCnt);

                gridPanel.add(click);
                dby++;
            }
            dbx++;
        }
    }


}```

Something like this?

public static void main(String[] args) {
    JFrame frame = new JFrame("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new GridBagLayout());
    JToolBar toolBar = new JToolBar(JToolBar.HORIZONTAL);
    toolBar.setFloatable(false);
    frame.add(toolBar, new GridBagConstraints(0, 0, 2, 3, 0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
    JPanel drawer = new JPanel();
    drawer.setBackground(Color.BLUE);
    drawer.setOpaque(true);
    drawer.setVisible(false);
    
    JPanel content = new JPanel();
    content.setBackground(Color.GREEN);
    content.setOpaque(true);
    
    frame.add(drawer, new GridBagConstraints(0, 1, 1, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
    frame.add(content, new GridBagConstraints(1, 1, 1, 2, 1, 1, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
    
    Action toggleDrawer = new AbstractAction("Toggle Drawer") {
        
        @Override
        public void actionPerformed(ActionEvent e) {
            drawer.setVisible(!drawer.isVisible());
            frame.revalidate();
            frame.repaint();
        }
    };
    toolBar.add(new JButton(toggleDrawer));
    
    frame.pack();
    frame.setSize(300, 500);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

A common strategy to solve complex computing tasks is to break them into small, well-defined manageable tasks. Divide and conquer. This also applies to gui: break the design into small, easy-to-layout containers and take it step by step.
First step: to have a background image implement a main panel, override its paintComponent to draw the image:

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

public class TestFrame /*extends JFrame*/ {

    private static final String imageURL = "https://previews.123rf.com/images/pingebat/pingebat1710/pingebat171000035/88604429-great-detail-illustration-of-the-world-map-in-vintage-style-.jpg";

    public static void main(String[] args) throws IOException  {

        URL url = new URL(imageURL);
        BufferedImage image = ImageIO.read(url);
        JFrame frame = new JFrame("Main Frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new MainPane(image));
        frame.pack();
        frame.setVisible(true);
    }
}

class MainPane extends JPanel{

    private final Image background;
    private final Dimension size;

    MainPane(Image background) {
        this.background = background;
        size = new Dimension(background.getWidth(null), background.getHeight(null));
    }

    @Override
    public Dimension preferredSize() {
        return size;
    }
    @Override //Override to paint image at the background
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(background, 0, 0, null);
    }
} 

在此处输入图片说明

Second step: add controls buttons at the top. Define the buttons panel:

class ControlsPane extends JPanel{

    public ControlsPane(ActionListener listener) {

        setOpaque(false);
        JButton btnShowHide = new JButton("Show Drawer");
        add(btnShowHide);
        btnShowHide.addActionListener(listener);

        JButton btnExit = new JButton("Exit");
        add(btnExit);
        btnExit.addActionListener(e-> System.exit(0));
    }
}

and modify MainPane constructor to use BorderLayout and add the buttons panel as suggested by @camickr:

MainPane(Image background) {
    this.background = background;
    size = new Dimension(background.getWidth(null), background.getHeight(null));
    setLayout(new BorderLayout(5,5));
    //action listener for show drawer button
    ActionListener  listener = e-> System.out.println("Show Drawer clicked");
    add(new ControlsPane(listener), BorderLayout.PAGE_START);
}

在此处输入图片说明

Now take it to the next step (for example add a drawer).

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