摆动布局思路
Swing Layout Ideas
我正在尝试在 java 中创建 JFrame。
问题是我找不到做我想做的事情的方法,如果我要放一个 textField 我就不能放按钮,而且它有所有的项目...
我想做的事情就像图片的模型:
非常感谢您的所有回答,我需要它。
您的图片是 Swing nested layout.
的图片
你的Swing components会这样排列。
JFrame
JPanel - main panel, Box layout, Page axis
JPanel - drawing panel
JScrollPane
JTextArea
JPanel - Flow Layout
JTextField
JButton
您的绘图面板将定义为与图像大小相同的首选大小。您可以通过覆盖 paintComponent 方法直接在 JPanel 上绘制图像。
编辑以添加一些示例代码。
这是我根据您提供的轮廓创建的布局。
我不知道这个 GUI 应该做什么,所以这是 Swing GUI 的框架。
每当我创建 Swing GUI 时,我都会使用 model / view / controller pattern。这使我能够分离我的关注点并创建复杂的 GUI 而不会遇到太多问题。
我创建的第一个 class 是 LayoutDemo class。
package com.ggl.layout;
import javax.swing.SwingUtilities;
import com.ggl.layout.model.LayoutModel;
import com.ggl.layout.view.LayoutFrame;
public class LayoutDemo implements Runnable {
@Override
public void run() {
new LayoutFrame(new LayoutModel());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new LayoutDemo());
}
}
这 20 行 class 做了 3 件重要的事情。
通过执行 SwingUtilities invokeLater 方法,将 Swing 组件的创建和使用放在 Event Dispatch thread (EDT) 上。 创建 Swing 应用程序时必须这样做。
实例化 LayoutModel class。
实例化 LayoutFrame class。
接下来,我们来看看 LayoutModel class。
package com.ggl.layout.model;
import java.awt.Dimension;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
public class LayoutModel {
private Document document;
private String textString;
public LayoutModel() {
document = new DefaultStyledDocument();
}
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
public Document getDocument() {
return document;
}
public String getTextString() {
return textString;
}
public void setTextString(String textString) {
this.textString = textString;
}
}
因为我不知道这个 GUI 应该做什么,这个 class 包含 JTextArea 的文档和 JTextField 的字符串。我假设字符串将添加到文档中,并且将在绘图区域上绘制一些内容。图纸的数据将保存在模型中 class.
接下来,我们来看看LayoutFrameclass。
package com.ggl.layout.view;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.ggl.layout.model.LayoutModel;
public class LayoutFrame {
private ControlPanel controlPanel;
private DrawingPanel drawingPanel;
private JFrame frame;
private LayoutModel model;
private TextPanel textPanel;
public LayoutFrame(LayoutModel model) {
this.model = model;
createPartControl();
}
private void createPartControl() {
frame = new JFrame();
frame.setTitle("Swing Layout");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
drawingPanel = new DrawingPanel(model);
mainPanel.add(drawingPanel);
textPanel = new TextPanel(model);
mainPanel.add(textPanel.getScrollPane());
controlPanel = new ControlPanel(model);
mainPanel.add(controlPanel.getPanel());
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.getRootPane().setDefaultButton(controlPanel.getSubmitButton());
frame.setVisible(true);
}
private void exitProcedure() {
frame.dispose();
System.exit(0);
}
}
这 class 将 JPanel 放入 createPartControl 方法中的 JFrame 中。
我们使用 Swing 组件。我们不扩展 Swing 组件。我们扩展 Swing 组件或任何其他 Java class 的唯一一次是当我们想要覆盖其中一个组件方法时。我们将在讨论绘图面板时看到一个例子。
接下来,我们将查看 DrawingPanel class。
package com.ggl.layout.view;
import java.awt.Graphics;
import javax.swing.JPanel;
import com.ggl.layout.model.LayoutModel;
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 6305888561097318682L;
private LayoutModel model;
public DrawingPanel(LayoutModel model) {
this.model = model;
this.setPreferredSize(model.getPreferredSize());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
我们设置 DrawingPanel 的大小,然后在 paintComponent 方法中绘制我们要绘制的任何内容。对 super.paintComponent 的调用必须是重写方法的第一行。
由于我们重写了 paintComponent 方法,所以我们扩展了一个 JPanel。我们添加一个 serialVersionUID,因为 JPanel 实现了 Serializable 接口。此接口需要一个 serialVersionUID。每次从 JPanel 添加或删除 Swing 组件时,都应更改 serialVersionUID。
接下来,让我们看一下TextPanelclass。
package com.ggl.layout.view;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import com.ggl.layout.model.LayoutModel;
public class TextPanel {
private JScrollPane scrollPane;
private JTextArea textArea;
private LayoutModel model;
public TextPanel(LayoutModel model) {
this.model = model;
createPartControl();
}
private void createPartControl() {
textArea = new JTextArea(10, 60);
textArea.setDocument(model.getDocument());
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
scrollPane = new JScrollPane(textArea);
}
public JScrollPane getScrollPane() {
return scrollPane;
}
public JTextArea getTextArea() {
return textArea;
}
}
这 class 将 JTextArea 放入 JScrollFrame 中。滚动条不会出现,除非我们定义 JTextArea 的行数超过 10 行,每行 60 个字符。
保存 JTextArea 文本的文档保存在模型中 class。添加到 Document 的文本将通过模型 class.
中的方法传递给 Document
最后,让我们看一下控制面板class。
package com.ggl.layout.view;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.ggl.layout.model.LayoutModel;
public class ControlPanel {
private JButton submitButton;
private JPanel panel;
private JTextField textField;
private LayoutModel model;
public ControlPanel(LayoutModel model) {
this.model = model;
createPartControl();
}
private void createPartControl() {
panel = new JPanel();
panel.setLayout(new BorderLayout());
textField = new JTextField(20);
panel.add(textField, BorderLayout.CENTER);
submitButton = new JButton("Submit");
submitButton.addActionListener(new SubmitActionListener());
panel.add(submitButton, BorderLayout.EAST);
}
public JButton getSubmitButton() {
return submitButton;
}
public JPanel getPanel() {
return panel;
}
public class SubmitActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
// TODO Auto-generated method stub
model.setTextString(textField.getText().trim());
}
}
}
此 class 包含一个 JTextField 和一个 JButton。我使用了 BorderLayout,这样我就可以拉伸 JTextField 来填充主 JPanel。
JButton 附加了一个控制器 class、SubmitActionListener。单击 JButton 或按下 Enter 键时,将执行控制器代码。
感谢您阅读到这里。此代码可以作为几乎所有 Swing GUI 的基础。
可以,您可以在同一个 Frame
上使用多个 layout
,这样您就可以根据需要放置所有项目。
您可以使用 SwingConstants 定位很多 layouts
见
有几种布局可供您使用:
这给了你足够多的可能性。有关每个 layouts
的更多信息,请参阅 doc。然后您应该能够轻松定位所有组件。
我正在尝试在 java 中创建 JFrame。
问题是我找不到做我想做的事情的方法,如果我要放一个 textField 我就不能放按钮,而且它有所有的项目...
我想做的事情就像图片的模型:
非常感谢您的所有回答,我需要它。
您的图片是 Swing nested layout.
的图片你的Swing components会这样排列。
JFrame
JPanel - main panel, Box layout, Page axis
JPanel - drawing panel
JScrollPane
JTextArea
JPanel - Flow Layout
JTextField
JButton
您的绘图面板将定义为与图像大小相同的首选大小。您可以通过覆盖 paintComponent 方法直接在 JPanel 上绘制图像。
编辑以添加一些示例代码。
这是我根据您提供的轮廓创建的布局。
我不知道这个 GUI 应该做什么,所以这是 Swing GUI 的框架。
每当我创建 Swing GUI 时,我都会使用 model / view / controller pattern。这使我能够分离我的关注点并创建复杂的 GUI 而不会遇到太多问题。
我创建的第一个 class 是 LayoutDemo class。
package com.ggl.layout;
import javax.swing.SwingUtilities;
import com.ggl.layout.model.LayoutModel;
import com.ggl.layout.view.LayoutFrame;
public class LayoutDemo implements Runnable {
@Override
public void run() {
new LayoutFrame(new LayoutModel());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new LayoutDemo());
}
}
这 20 行 class 做了 3 件重要的事情。
通过执行 SwingUtilities invokeLater 方法,将 Swing 组件的创建和使用放在 Event Dispatch thread (EDT) 上。 创建 Swing 应用程序时必须这样做。
实例化 LayoutModel class。
实例化 LayoutFrame class。
接下来,我们来看看 LayoutModel class。
package com.ggl.layout.model;
import java.awt.Dimension;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
public class LayoutModel {
private Document document;
private String textString;
public LayoutModel() {
document = new DefaultStyledDocument();
}
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
public Document getDocument() {
return document;
}
public String getTextString() {
return textString;
}
public void setTextString(String textString) {
this.textString = textString;
}
}
因为我不知道这个 GUI 应该做什么,这个 class 包含 JTextArea 的文档和 JTextField 的字符串。我假设字符串将添加到文档中,并且将在绘图区域上绘制一些内容。图纸的数据将保存在模型中 class.
接下来,我们来看看LayoutFrameclass。
package com.ggl.layout.view;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.ggl.layout.model.LayoutModel;
public class LayoutFrame {
private ControlPanel controlPanel;
private DrawingPanel drawingPanel;
private JFrame frame;
private LayoutModel model;
private TextPanel textPanel;
public LayoutFrame(LayoutModel model) {
this.model = model;
createPartControl();
}
private void createPartControl() {
frame = new JFrame();
frame.setTitle("Swing Layout");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
drawingPanel = new DrawingPanel(model);
mainPanel.add(drawingPanel);
textPanel = new TextPanel(model);
mainPanel.add(textPanel.getScrollPane());
controlPanel = new ControlPanel(model);
mainPanel.add(controlPanel.getPanel());
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.getRootPane().setDefaultButton(controlPanel.getSubmitButton());
frame.setVisible(true);
}
private void exitProcedure() {
frame.dispose();
System.exit(0);
}
}
这 class 将 JPanel 放入 createPartControl 方法中的 JFrame 中。
我们使用 Swing 组件。我们不扩展 Swing 组件。我们扩展 Swing 组件或任何其他 Java class 的唯一一次是当我们想要覆盖其中一个组件方法时。我们将在讨论绘图面板时看到一个例子。
接下来,我们将查看 DrawingPanel class。
package com.ggl.layout.view;
import java.awt.Graphics;
import javax.swing.JPanel;
import com.ggl.layout.model.LayoutModel;
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 6305888561097318682L;
private LayoutModel model;
public DrawingPanel(LayoutModel model) {
this.model = model;
this.setPreferredSize(model.getPreferredSize());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
}
我们设置 DrawingPanel 的大小,然后在 paintComponent 方法中绘制我们要绘制的任何内容。对 super.paintComponent 的调用必须是重写方法的第一行。
由于我们重写了 paintComponent 方法,所以我们扩展了一个 JPanel。我们添加一个 serialVersionUID,因为 JPanel 实现了 Serializable 接口。此接口需要一个 serialVersionUID。每次从 JPanel 添加或删除 Swing 组件时,都应更改 serialVersionUID。
接下来,让我们看一下TextPanelclass。
package com.ggl.layout.view;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import com.ggl.layout.model.LayoutModel;
public class TextPanel {
private JScrollPane scrollPane;
private JTextArea textArea;
private LayoutModel model;
public TextPanel(LayoutModel model) {
this.model = model;
createPartControl();
}
private void createPartControl() {
textArea = new JTextArea(10, 60);
textArea.setDocument(model.getDocument());
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
scrollPane = new JScrollPane(textArea);
}
public JScrollPane getScrollPane() {
return scrollPane;
}
public JTextArea getTextArea() {
return textArea;
}
}
这 class 将 JTextArea 放入 JScrollFrame 中。滚动条不会出现,除非我们定义 JTextArea 的行数超过 10 行,每行 60 个字符。
保存 JTextArea 文本的文档保存在模型中 class。添加到 Document 的文本将通过模型 class.
中的方法传递给 Document最后,让我们看一下控制面板class。
package com.ggl.layout.view;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.ggl.layout.model.LayoutModel;
public class ControlPanel {
private JButton submitButton;
private JPanel panel;
private JTextField textField;
private LayoutModel model;
public ControlPanel(LayoutModel model) {
this.model = model;
createPartControl();
}
private void createPartControl() {
panel = new JPanel();
panel.setLayout(new BorderLayout());
textField = new JTextField(20);
panel.add(textField, BorderLayout.CENTER);
submitButton = new JButton("Submit");
submitButton.addActionListener(new SubmitActionListener());
panel.add(submitButton, BorderLayout.EAST);
}
public JButton getSubmitButton() {
return submitButton;
}
public JPanel getPanel() {
return panel;
}
public class SubmitActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
// TODO Auto-generated method stub
model.setTextString(textField.getText().trim());
}
}
}
此 class 包含一个 JTextField 和一个 JButton。我使用了 BorderLayout,这样我就可以拉伸 JTextField 来填充主 JPanel。
JButton 附加了一个控制器 class、SubmitActionListener。单击 JButton 或按下 Enter 键时,将执行控制器代码。
感谢您阅读到这里。此代码可以作为几乎所有 Swing GUI 的基础。
可以,您可以在同一个 Frame
上使用多个 layout
,这样您就可以根据需要放置所有项目。
您可以使用 SwingConstants 定位很多 layouts
见
有几种布局可供您使用:
这给了你足够多的可能性。有关每个 layouts
的更多信息,请参阅 doc。然后您应该能够轻松定位所有组件。