简体   繁体   English

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

[英]JAVA GUI - How to reproduce my GUI with a layout manager?

I am using a simple Main Menu for my application, however the problem is that it is all hard coded using layout=null and not being resizeable. 我为我的应用程序使用了一个简单的主菜单,但是问题是所有这些都是使用layout = null进行硬编码的,并且无法调整大小。

Since this is really really bad practice, I wanted to go head with some layout manager. 由于这确实是一种糟糕的做法,因此我想请一些布局经理。

Even though since it is not resizable, there should not be issues, but still it feels wrong. 即使由于它不能调整大小,也不应该有问题,但是仍然感觉不对。

It looks like this : https://i.imgur.com/k1Ne5v9.png 看起来像这样: https : //i.imgur.com/k1Ne5v9.png

and the code for it is: 它的代码是:

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);
            }
        }
    });

}

How could I convert this into GUI that uses some layout manager? 如何将其转换为使用某些布局管理器的GUI? Also I dont mind if you point out any mistakes/bad practices used in the code, because I am self-taught and I would definitely like to avoid them in the future. 同样,我也不介意您指出代码中使用的任何错误/不良做法,因为我是自学成才的,因此我将来一定会避免它们。

Thank you for your time 感谢您的时间

I have done your layout using layout managers and i have added comments inside the code about the how and why i prefer things like this. 我已经使用布局管理器完成了布局,并且在代码中添加有关如何以及为什么喜欢这样的东西的注释 However, layout managers need practice in order be able to handle them fast and easy. 但是,布局经理需要练习才能快速,轻松地处理它们。 Just don't avoid to use them. 只是不要避免使用它们。

Please, have in mind that all of these are personal preferences. 请记住,所有这些都是个人喜好。 You can keep what you like and ignore what you don't. 您可以保留自己喜欢的内容,而忽略自己不喜欢的内容。

Here it is: 这里是:

Main class: 主班:

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 class: 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;
    }
}

Ps: Ignore if some numbers are not equal to yours (heights and sizes). 附言:忽略一些数字是否不等于您的数字(高度和大小)。 I have just giving you an example :) 我只是给你一个例子:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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