写了Java这么久,居然发现想手写一个带网格袋布局的JFrame,还不记得怎么写,写了这么多代码真不敢说记得所有细节。
幸好,只要记清楚概念就能快速开发。首先,明确一下3种容器类的差别和用途:
No. | 区别 |
---|---|
1 | Panel
JPanel用于放置其他控件,也包含其他panels。 |
2 | Frame
JFrame 是包含 title and a border的第一层级的容器,其中通过布局设置JPanel或其他控件的位置。 |
3 | Window
JWindow是不包含 title and a border的第一层级的容器。 |
JFrame构造函数
S.N. | Description |
---|---|
1 | JFrame()
Constructs a new frame that is initially invisible. |
2 | JFrame(GraphicsConfiguration gc)
Creates a Frame in the specified GraphicsConfiguration of a screen device and a blank title. |
3 | JFrame(String title) 带标题
Creates a new, initially invisible Frame with the specified title. |
4 | JFrame(String title, GraphicsConfiguration gc)
Creates a JFrame with the specified title and the specified GraphicsConfiguration of a screen device. |
Class methods
S.N. Method & Description 1 protected void addImpl(Component comp, Object constraints, int index) Adds the specified child Component. 添加子控件 2 protected JRootPane createRootPane() Called by the constructor methods to create the default rootPane. 3 protected void frameInit() Called by the constructors to init the JFrame properly. 4 AccessibleContext getAccessibleContext() Gets the AccessibleContext associated with this JFrame. 5 Container getContentPane() 返回容器Pane,经常使用 Returns the contentPane object for this frame. 6 int getDefaultCloseOperation() Returns the operation that occurs when the user initiates a "close" on this frame. 7 Component getGlassPane() Returns the glassPane object for this frame. 8 Graphics getGraphics() Creates a graphics context for this component. 9 JMenuBar getJMenuBar() 返回菜单 Returns the menubar set on this frame. 10 JLayeredPane getLayeredPane() Returns the layeredPane object for this frame. 11 JRootPane getRootPane() 返回根容器,经常使用 Returns the rootPane object for this frame. 12 TransferHandler getTransferHandler() Gets the transferHandler property. 13 static boolean isDefaultLookAndFeelDecorated() Returns true if newly created JFrames should have their Window decorations provided by the current look and feel. 14 protected boolean isRootPaneCheckingEnabled() Returns whether calls to add and setLayout are forwarded to the contentPane. 15 protected String paramString() Returns a string representation of this JFrame. 16 protected void processWindowEvent(WindowEvent e) Processes window events occurring on this component. 17 void remove(Component comp) Removes the specified component from the container. 18 void repaint(long time, int x, int y, int width, int height) Repaints the specified rectangle of this component within time milliseconds. 19 void setContentPane(Container contentPane) Sets the contentPane property. 20 void setDefaultCloseOperation(int operation) Sets the operation that will happen by default when the user initiates a "close" on this frame. 21 static void setDefaultLookAndFeelDecorated(boolean defaultLookAndFeelDecorated) Provides a hint as to whether or not newly created JFrames should have their Window decorations (such as borders, widgets to close the window, title...) provided by the current look and feel. 22 void setGlassPane(Component glassPane) Sets the glassPane property. 23 void setIconImage(Image image) 设置图标 Sets the image to be displayed as the icon for this window. 24 void setJMenuBar(JMenuBar menubar) 设置菜单 Sets the menubar for this frame. 25 void setLayeredPane(JLayeredPane layeredPane) Sets the layeredPane property. 26 void setLayout(LayoutManager manager) 设置布局 Sets the LayoutManager. 27 protected void setRootPane(JRootPane root) Sets the rootPane property. 28 protected void setRootPaneCheckingEnabled(boolean enabled) Sets whether calls to add and setLayout are forwarded to the contentPane. 29 void setTransferHandler(TransferHandler newHandler) Sets the transferHandler property, which is a mechanism to support transfer of data into this component. 30 void update(Graphics g) Just calls paint(g).
代码1:第一个JFrame简单例子
import java.awt.*; import javax.swing.*; public class JFrameExample implements Runnable { public static void main(String[] args) { JFrameExample example = new JFrameExample(); SwingUtilities.invokeLater(example); } public void run() { JFrame frame = new JFrame("My JFrame Example"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setPreferredSize(new Dimension(400, 200)); frame.pack(); frame.setVisible(true); } }
代码2,另一个写法
public static void main(String[] args) { // schedule this for the event dispatch thread (edt) SwingUtilities.invokeLater(new Runnable() { public void run() { displayJFrame(); } }); } static void displayJFrame() { JFrame frame = new JFrame("My JFrame Example"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setPreferredSize(new Dimension(400, 200)); frame.pack(); frame.setVisible(true); }
代码3:带有GridLayout的简单JFrame
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SwingContainerDemo { private JFrame mainFrame; private JLabel headerLabel; private JLabel statusLabel; private JPanel controlPanel; private JLabel msglabel; public SwingContainerDemo(){ prepareGUI(); } public static void main(String[] args){ SwingContainerDemo swingContainerDemo = new SwingContainerDemo(); swingContainerDemo.showJPanelDemo(); } private void prepareGUI(){ mainFrame = new JFrame("Java Swing "); mainFrame.setSize(400,400); mainFrame.setLayout(new GridLayout(3, 1)); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowEvent){ System.exit(0); } }); headerLabel = new JLabel("headerLabel ", JLabel.CENTER); statusLabel = new JLabel("statusLabel ",JLabel.CENTER); statusLabel.setSize(350,100); msglabel = new JLabel("Welcome SWING ", JLabel.CENTER); controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); mainFrame.add(headerLabel); mainFrame.add(controlPanel); mainFrame.add(statusLabel); mainFrame.setVisible(true); } private void showJPanelDemo(){ headerLabel.setText("Container in action: JPanel"); JPanel panel = new JPanel(); panel.setBackground(Color.magenta); panel.setLayout(new FlowLayout()); panel.add(msglabel); controlPanel.add(panel); mainFrame.setVisible(true); } }
代码4:带有GridLayout和按钮事件的JFrame
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SwingContainerDemo { private JFrame mainFrame; private JLabel headerLabel; private JLabel statusLabel; private JPanel controlPanel; private JLabel msglabel; public SwingContainerDemo(){ prepareGUI(); } public static void main(String[] args){ SwingContainerDemo swingContainerDemo = new SwingContainerDemo(); swingContainerDemo.showJFrameDemo(); } private void prepareGUI(){ mainFrame = new JFrame("Java Swing"); mainFrame.setSize(400,400); mainFrame.setLayout(new GridLayout(3, 1)); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowEvent){ System.exit(0); } }); headerLabel = new JLabel("Head", JLabel.CENTER); statusLabel = new JLabel("Status",JLabel.CENTER); statusLabel.setSize(350,100); msglabel = new JLabel("Welcome SWING", JLabel.CENTER); controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); mainFrame.add(headerLabel); mainFrame.add(controlPanel); mainFrame.add(statusLabel); mainFrame.setVisible(true); } private void showJFrameDemo(){ headerLabel.setText("Container in action: JFrame"); final JFrame frame = new JFrame(); frame.setSize(300, 300); frame.setLayout(new FlowLayout()); frame.add(msglabel); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowEvent){ frame.dispose(); } }); JButton okButton = new JButton("Open a Frame"); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { statusLabel.setText("A Frame shown to the user."); frame.setVisible(true); } }); controlPanel.add(okButton); mainFrame.setVisible(true); } }
代码5:带有菜单的JFrame
import java.awt.*; import java.awt.event.*; public class SwingMenuDemo { private JFrame mainFrame; private JLabel headerLabel; private JLabel statusLabel; private JPanel controlPanel; public SwingMenuDemo(){ prepareGUI(); } public static void main(String[] args){ SwingMenuDemo swingMenuDemo = new SwingMenuDemo(); swingMenuDemo.showMenuDemo(); } private void prepareGUI(){ mainFrame = new JFrame("Java SWING Examples"); mainFrame.setSize(400,400); mainFrame.setLayout(new GridLayout(3, 1)); headerLabel = new JLabel("",JLabel.CENTER ); statusLabel = new JLabel("",JLabel.CENTER); statusLabel.setSize(350,100); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowEvent){ System.exit(0); } }); controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); mainFrame.add(headerLabel); mainFrame.add(controlPanel); mainFrame.add(statusLabel); mainFrame.setVisible(true); } private void showMenuDemo(){ //create a menu bar final JMenuBar menuBar = new JMenuBar(); //create menus JMenu fileMenu = new JMenu("File"); JMenu editMenu = new JMenu("Edit"); final JMenu aboutMenu = new JMenu("About"); final JMenu linkMenu = new JMenu("Links"); //create menu items JMenuItem newMenuItem = new JMenuItem("New"); newMenuItem.setMnemonic(KeyEvent.VK_N); newMenuItem.setActionCommand("New"); JMenuItem openMenuItem = new JMenuItem("Open"); openMenuItem.setActionCommand("Open"); JMenuItem saveMenuItem = new JMenuItem("Save"); saveMenuItem.setActionCommand("Save"); JMenuItem exitMenuItem = new JMenuItem("Exit"); exitMenuItem.setActionCommand("Exit"); JMenuItem cutMenuItem = new JMenuItem("Cut"); cutMenuItem.setActionCommand("Cut"); JMenuItem copyMenuItem = new JMenuItem("Copy"); copyMenuItem.setActionCommand("Copy"); JMenuItem pasteMenuItem = new JMenuItem("Paste"); pasteMenuItem.setActionCommand("Paste"); MenuItemListener menuItemListener = new MenuItemListener(); newMenuItem.addActionListener(menuItemListener); openMenuItem.addActionListener(menuItemListener); saveMenuItem.addActionListener(menuItemListener); exitMenuItem.addActionListener(menuItemListener); cutMenuItem.addActionListener(menuItemListener); copyMenuItem.addActionListener(menuItemListener); pasteMenuItem.addActionListener(menuItemListener); final JCheckBoxMenuItem showWindowMenu = new JCheckBoxMenuItem("Show About", true); showWindowMenu.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if(showWindowMenu.getState()){ menuBar.add(aboutMenu); }else{ menuBar.remove(aboutMenu); } } }); final JRadioButtonMenuItem showLinksMenu = new JRadioButtonMenuItem("Show Links", true); showLinksMenu.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if(menuBar.getMenu(3)!= null){ menuBar.remove(linkMenu); mainFrame.repaint(); }else{ menuBar.add(linkMenu); mainFrame.repaint(); } } }); //add menu items to menus fileMenu.add(newMenuItem); fileMenu.add(openMenuItem); fileMenu.add(saveMenuItem); fileMenu.addSeparator(); fileMenu.add(showWindowMenu); fileMenu.addSeparator(); fileMenu.add(showLinksMenu); fileMenu.addSeparator(); fileMenu.add(exitMenuItem); editMenu.add(cutMenuItem); editMenu.add(copyMenuItem); editMenu.add(pasteMenuItem); //add menu to menubar menuBar.add(fileMenu); menuBar.add(editMenu); menuBar.add(aboutMenu); menuBar.add(linkMenu); //add menubar to the frame mainFrame.setJMenuBar(menuBar); mainFrame.setVisible(true); } class MenuItemListener implements ActionListener { public void actionPerformed(ActionEvent e) { statusLabel.setText(e.getActionCommand() + " JMenuItem clicked."); } } }
代码6:带有BorderLayout的JFrame
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SwingLayoutDemo { private JFrame mainFrame; private JLabel headerLabel; private JLabel statusLabel; private JPanel controlPanel; private JLabel msglabel; public SwingLayoutDemo(){ prepareGUI(); } public static void main(String[] args){ SwingLayoutDemo swingLayoutDemo = new SwingLayoutDemo(); swingLayoutDemo.showBorderLayoutDemo(); } private void prepareGUI(){ mainFrame = new JFrame("Java SWING Examples"); mainFrame.setSize(400,400); mainFrame.setLayout(new GridLayout(3, 1)); headerLabel = new JLabel("",JLabel.CENTER ); statusLabel = new JLabel("",JLabel.CENTER); statusLabel.setSize(350,100); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowEvent){ System.exit(0); } }); controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); mainFrame.add(headerLabel); mainFrame.add(controlPanel); mainFrame.add(statusLabel); mainFrame.setVisible(true); } private void showBorderLayoutDemo(){ headerLabel.setText("Layout in action: BorderLayout"); JPanel panel = new JPanel(); panel.setBackground(Color.darkGray); panel.setSize(300,300); BorderLayout layout = new BorderLayout(); layout.setHgap(10); layout.setVgap(10); panel.setLayout(layout); panel.add(new JButton("Center"),BorderLayout.CENTER); panel.add(new JButton("Line Start"),BorderLayout.LINE_START); panel.add(new JButton("Line End"),BorderLayout.LINE_END); panel.add(new JButton("East"),BorderLayout.EAST); panel.add(new JButton("West"),BorderLayout.WEST); panel.add(new JButton("North"),BorderLayout.NORTH); panel.add(new JButton("South"),BorderLayout.SOUTH); controlPanel.add(panel); mainFrame.setVisible(true); } }
代码7:带有CardLayout的JFrame
CardLayout是非常特殊的布局,其他的布局是控制相对位置,它的用法是把控件置于不同“卡片”,其目的是控制每次只显示一个卡片(绝不同时出现两个卡片)。
就像一个堆栈,每次放在最前的只有一个元素。比如需要制作Step by Step的桌面程序,使用CardLayout就非常方便。
其中用于控制展示卡片的关键代码:cardLayout.show(panel,name);name就是卡片的name
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class SwingLayoutDemo { private JFrame mainFrame; private JLabel headerLabel; private JLabel statusLabel; private JPanel controlPanel; private JLabel msglabel; public SwingLayoutDemo(){ prepareGUI(); } public static void main(String[] args){ SwingLayoutDemo swingLayoutDemo = new SwingLayoutDemo(); swingLayoutDemo.showCardLayoutDemo(); } private void prepareGUI(){ mainFrame = new JFrame("Java SWING Examples"); mainFrame.setSize(400,400); mainFrame.setLayout(new GridLayout(3, 1)); headerLabel = new JLabel("",JLabel.CENTER ); statusLabel = new JLabel("",JLabel.CENTER); statusLabel.setSize(350,100); mainFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent windowEvent){ System.exit(0); } }); controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); mainFrame.add(headerLabel); mainFrame.add(controlPanel); mainFrame.add(statusLabel); mainFrame.setVisible(true); } private void showCardLayoutDemo(){ headerLabel.setText("Layout in action: CardLayout"); final JPanel panel = new JPanel(); panel.setBackground(Color.CYAN); panel.setSize(300,300); CardLayout layout = new CardLayout(); layout.setHgap(10); layout.setVgap(10); panel.setLayout(layout); JPanel buttonPanel = new JPanel(new FlowLayout()); buttonPanel.add(new JButton("确定")); buttonPanel.add(new JButton("取消")); JPanel textBoxPanel = new JPanel(new FlowLayout()); textBoxPanel.add(new JLabel("姓名:")); textBoxPanel.add(new JTextField(20)); panel.add("Button", buttonPanel); panel.add("Text", textBoxPanel); final DefaultComboBoxModel panelName = new DefaultComboBoxModel(); panelName.addElement("Button"); panelName.addElement("Text"); final JComboBox listCombo = new JComboBox(panelName); listCombo.setSelectedIndex(0); JScrollPane listComboScrollPane = new JScrollPane(listCombo); JButton showButton = new JButton("展示"); showButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String data = ""; if (listCombo.getSelectedIndex() != -1) { CardLayout cardLayout = (CardLayout)(panel.getLayout()); cardLayout.show(panel, (String)listCombo.getItemAt(listCombo.getSelectedIndex())); } statusLabel.setText(data); } }); controlPanel.add(listComboScrollPane); controlPanel.add(showButton); controlPanel.add(panel); mainFrame.setVisible(true); } }
其他不常用布局1:带有FlowLayout的JFrame
FlowLayout就是一种从左到右(left-to-right)排列的布局,代码略。
其他不常用布局2:带有GroupLayout的JFrame
GroupLayout在一些场景上可以替代布局之王网格袋布局,代码会更清晰.
有几篇不错的文章:
http://docs.oracle.com/javase/tutorial/uiswing/layout/group.html
http://www.cnblogs.com/taoweiji/archive/2012/12/10/2812221.html
http://saupb.blog.163.com/blog/static/471241782010105105525362/
代码8:带有GridBagLayout的JFrame
真正的布局之王,复杂但值得学习
GridBagConstraints可以从11个方面来进行控制和操纵,也可以给你提供一些帮助。这些内容是:
- Gridx——组件的横向坐标
- Girdy——组件的纵向坐标
- Gridwidth——组件的横向宽度,也就是指组件占用的列数,这与HTML的colspan类似
- Gridheight——组件的纵向长度,也就是指组件占用的行数,这与HTML的rowspan类似
- Weightx——指行的权重,告诉布局管理器如何分配额外的水平空间
- Weighty——指列的权重,告诉布局管理器如何分配额外的垂直空间
- Anchor——告诉布局管理器组件在表格空间中的位置
- Fill——如果显示区域比组件的区域大的时候,可以用来控制组件的行为。控制组件是垂直填充,还是水平填充,或者两个方向一起填充
- Insets——指组件与表格空间四周边缘的空白区域的大小
- Ipadx—— 组件间的横向间距,组件的宽度就是这个组件的最小宽度加上ipadx值
- ipady—— 组件间的纵向间距,组件的高度就是这个组件的最小高度加上ipady值
最好的教程在这里:
http://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
import java.awt.*; import javax.swing.JButton; import javax.swing.JFrame; public class SwingLayoutDemo { final static boolean shouldFill = true; final static boolean shouldWeightX = true; final static boolean RIGHT_TO_LEFT = false; public static void addComponentsToPane(Container pane) { if (RIGHT_TO_LEFT) { pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); } JButton button; pane.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); if (shouldFill) { //natural height, maximum width c.fill = GridBagConstraints.HORIZONTAL; } button = new JButton("Button 1"); if (shouldWeightX) { c.weightx = 0.5; } c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; pane.add(button, c); button = new JButton("Button 2"); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 0.5; c.gridx = 1; c.gridy = 0; pane.add(button, c); button = new JButton("Button 3"); c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 0.5; c.gridx = 2; c.gridy = 0; pane.add(button, c); button = new JButton("Long-Named Button 4"); c.fill = GridBagConstraints.HORIZONTAL; c.ipady = 40; //make this component tall c.weightx = 0.0; c.gridwidth = 3; c.gridx = 0; c.gridy = 1; pane.add(button, c); button = new JButton("5"); c.fill = GridBagConstraints.HORIZONTAL; c.ipady = 0; //reset to default c.weighty = 1.0; //request any extra vertical space c.anchor = GridBagConstraints.PAGE_END; //bottom of space c.insets = new Insets(10,0,0,0); //top padding c.gridx = 1; //aligned with button 2 c.gridwidth = 2; //2 columns wide c.gridy = 2; //third row pane.add(button, c); } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Create and set up the window. JFrame frame = new JFrame("GridBagLayoutDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Set up the content pane. addComponentsToPane(frame.getContentPane()); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application‘s GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } }