JAVA GUI - 如何使用布局管理器重现我的GUI?

时间:2018-05-23 08:35:13

标签: java jframe

我正在为我的应用程序使用一个简单的主菜单,但问题是它全部使用layout = null进行硬编码而不是可调整大小。

由于这真的是非常糟糕的做法,我想与一些布局管理员合作。

即使由于它不可调整大小,也不应该存在问题,但仍然感觉不对。

看起来像这样:https://i.imgur.com/k1Ne5v9.png

,代码为:

public class MainMenu {
private static JFrame mF = new JFrame("Main Menu");

public static void main(String[] args) {
    System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");

    Font menuFont = new Font("Courier",Font.BOLD,16);
    mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mF.setSize(465,230);
    mF.setLocationRelativeTo(null);
    mF.getContentPane().setBackground(Color.WHITE);

    Color blueSteel = new Color(70,107,176);
    JPanel p = new JPanel();
    p.setSize(600,50);
    p.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    p.setLocation((mF.getWidth() - p.getWidth()) /2, 20);
    p.setBackground(blueSteel);
    JLabel l = new JLabel("Welcome to the menu GENERATORRRR");
    l.setFont(menuFont);
    l.setForeground(Color.WHITE);
    p.add(l, gbc);

    JButton runMenuButt = new JButton("Generate Menu");
    runMenuButt.setLocation(20 , 90);
    JButton manageRecipButt = new JButton("Manage Recipients");
    manageRecipButt.setLocation(240 , 90);
    menuUtilities.formatButton(runMenuButt);
    menuUtilities.formatButton(manageRecipButt);

    mF.setResizable(false);
    mF.setLayout(null);
    mF.add(runMenuButt);
    mF.add(manageRecipButt);
    mF.add(p);
    mF.setVisible(true);

    runMenuButt.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Generate Menu pressed");
            mF.dispose();
            getMenuInJavaNow.main();
            //MenuGenerator.generateTheMenu();
        }
    });

    manageRecipButt.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            DeliveryPackage menuRecipients = new DeliveryPackage();
            if (menuRecipients.recipientList != menuRecipients.fileNotFoundMessage) {
                editRecipientList(menuRecipients);
            } else {
                JOptionPane.showMessageDialog(null,"File not found at " + menuRecipients.recipientFilePath ,menuRecipients.recipientFileName + " missing!" ,JOptionPane.ERROR_MESSAGE);
            }
        }
    });

}

如何将其转换为使用某些布局管理器的GUI? 另外我不介意你指出代码中使用的任何错误/不良做法,因为我是自学成才,我肯定希望将来避免使用它们。

感谢您的时间

1 个答案:

答案 0 :(得分:0)

我已经使用布局管理器完成了布局,并在代码中添加了注释,了解了我喜欢这样的内容的方式和原因。但是,布局管理人员需要练习才能快速轻松地处理它们。只是不要避免使用它们。

请记住,所有这些都是个人喜好。你可以保留你喜欢的东西,而忽略你不喜欢的东西。

这是:

主要课程:

package test;

import javax.swing.SwingUtilities;

public class Main {
    /*
     * Having a static JFrame is only recommended when you know exactly what you are
     * doing. 99% of the times (i could say 100% :)) you will never need it.
     */
    // private static JFrame mF = new JFrame("Main Menu");

    public static void main(String[] args) {
        System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
        /*
         * All Swing applications must run on their own thread, a.k.a Event Dispatch
         * Thread (EDT). I also like to use main method separated from GUI
         * methods/classes.
         */
        SwingUtilities.invokeLater(() -> {
            MyFrame frame = new MyFrame();
            // It is recommended to show the frame (make it visible) after its initiated and
            // not in its constructor
            frame.setVisible(true);
        });
    }
}

MyFrame类:

package test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class MyFrame extends JFrame {
    private static final long serialVersionUID = -5908534022988507382L;
    // Things like colours,fonts, dimensions or thing that won't change, i recommend
    // them to define them as static
    private static final Font FONT = new Font("Courier", Font.BOLD, 16);
    private static final Color BLUE_STEEL = new Color(70, 107, 176);
    private static final Dimension INITIAL_SIZE = new Dimension(500, 250);
    private static final Dimension MINIMUM_SIZE = new Dimension(300, 200);

    public MyFrame() {
        // Now start the standard things for a frame.
        super("Main Menu");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        getContentPane().setBackground(Color.WHITE);
        // setSize(465, 230); // Initial size. Do not use setSize() for other
        // components. Only for frames.

        /*
         * Now depends how you want the GUI, you choose the layout manager. In your
         * uploaded picture you showed a TextField/JLabel at the top and 2 buttons in
         * the center. You can always go either with GridBag layout, or as i like to go,
         * with inherited panels.
         */
        /*
         * In order to learn layout managers, read the java docs. For now i will show
         * you how to use 2 of them.
         */
        /*
         * JFrame's content pane uses either FlowLayout, either BorderLayout initially.
         * For me, i don't actually care, i will define it anyways, so when i'll see the
         * code i will be able to see easily the layout. A personal preference aswell.
         */
        /*
         * Read BorderLayout java doc in order to see how it works.
         */
        getContentPane().setLayout(new BorderLayout(1, 15)); // 15 pixels vertical gap
        /*
         * Try to describe the variable fully. Personally, i use the "txt" for simple
         * texts that won't change during runtime.
         */
        JLabel txtWelcome = new JLabel("Welcome to the menu GENERATORRRR");
        txtWelcome.setFont(FONT);
        txtWelcome.setHorizontalAlignment(SwingConstants.CENTER);// Centrize text
        txtWelcome.setForeground(Color.WHITE);
        txtWelcome.setBackground(BLUE_STEEL);
        /*
         * I describe with few words about heights and dimensions in
         * createMainButtonsPanel() method. This is the one line :)
         */
        txtWelcome.setPreferredSize(
                new Dimension(txtWelcome.getPreferredSize().width, txtWelcome.getPreferredSize().height + 15));
        /*
         * Since you want white foreground and blue background, the component must have
         * opacity. In our case, it is a JLabel which is not opaque initially.
         */
        txtWelcome.setOpaque(true);
        getContentPane().add(txtWelcome, BorderLayout.PAGE_START);// at the top

        /*
         * Now let's add the 2 buttons. For this, we are going to use an inhertied panel
         * inside the content pane.
         */
        JPanel mainButtonsPanel = createMainButtonsPanel();
        getContentPane().add(mainButtonsPanel, BorderLayout.CENTER); // at the center
        setSize(INITIAL_SIZE); // The initial frame size
        setMinimumSize(MINIMUM_SIZE);
    }

    /*
     * Use a different method for this panel creation, it will be easier to read the
     * code later.
     */
    private JPanel createMainButtonsPanel() {
        JPanel panel = new JPanel();
        /* Components at center with 20pixels gap horizontally */
        panel.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 1));
        /*
         * Panel's bg color is the initial color, if you want to have the background
         * color of the frame, must have no opacity.
         */
        panel.setOpaque(false);
        JButton runMenuButton = new JButton("Generate Menu");
        runMenuButton.setFont(FONT); // In case you want the font
        /*
         * Adding an actionlistener using an Anonymous inner class is fine. However, if
         * you use java8+ i would recommend you to go with lamdas since code will look
         * more clear.
         */
        runMenuButton.addActionListener(e -> {
            System.out.println("Generate Menu pressed");
            // Do more stuff here
        });

        JButton manageReceiptsButton = new JButton("Manage Receipts");
        manageReceiptsButton.setFont(FONT);
        manageReceiptsButton.addActionListener(e -> {
            JOptionPane.showMessageDialog(panel, "Manage Receipts pressed.");
            // Do more stuff here
        });
        /*
         * Now let's handle their height. Flow layout will add them with their initially
         * height. Initial height changes when you use bigger font/bigger icon, but if
         * you don't want to use a bigger font you have to increase the height manually.
         * Other layout managers would increase their height in order fit the whole
         * panel. I will add them some height directly, but its preferred to use the
         * extra height as a static field.
         */
        int extraHeight = 15;
        runMenuButton.setPreferredSize(new Dimension(runMenuButton.getPreferredSize().width,
                runMenuButton.getPreferredSize().height + extraHeight));
        manageReceiptsButton.setPreferredSize(new Dimension(manageReceiptsButton.getPreferredSize().width,
                manageReceiptsButton.getPreferredSize().height + extraHeight));
        /*
         * Now add them to the panel. I usually add them in the end of the method,
         * because it will be easier later to change their position. E.g: you might want
         * the manage receipts button first and then the generate menu button. So, it
         * will take you just 1 sec to change 2 lines. Adding them after they are
         * initialized is fine aswell.
         */
        panel.add(runMenuButton);
        panel.add(manageReceiptsButton);
        return panel;
    }
}

P.s:如果某些数字不等于你的数字(高度和大小),请忽略。我刚给你举个例子:)