我正在为我的应用程序使用一个简单的主菜单,但问题是它全部使用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? 另外我不介意你指出代码中使用的任何错误/不良做法,因为我是自学成才,我肯定希望将来避免使用它们。
感谢您的时间
答案 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:如果某些数字不等于你的数字(高度和大小),请忽略。我刚给你举个例子:)