Java JPanel组件放置
我试图得到一个基本的图形用户界面程序。它不需要做很多事情,但底部的按钮必须工作。我无法将文本、组合框等组件放置在正确的位置。使用GridBag,我可以用c.gridx和c.gridy更改位置,但方式非常奇怪。如果我把网格值0-7,x为0,所有的东西都在上面。我试图通过更改gridx值将组合框放在文本旁边,结果一切都搞砸了。在我试图移动的组件之后,组件上的对齐已关闭。我该如何解决这个问题?我试过边界布局,但没有成功。实际的变化根本不起作用,然后移动到底部。我该如何解决这个问题?谢谢Java JPanel组件放置,java,swing,user-interface,jframe,jpanel,Java,Swing,User Interface,Jframe,Jpanel,我试图得到一个基本的图形用户界面程序。它不需要做很多事情,但底部的按钮必须工作。我无法将文本、组合框等组件放置在正确的位置。使用GridBag,我可以用c.gridx和c.gridy更改位置,但方式非常奇怪。如果我把网格值0-7,x为0,所有的东西都在上面。我试图通过更改gridx值将组合框放在文本旁边,结果一切都搞砸了。在我试图移动的组件之后,组件上的对齐已关闭。我该如何解决这个问题?我试过边界布局,但没有成功。实际的变化根本不起作用,然后移动到底部。我该如何解决这个问题?谢谢 /* * T
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javaredesign;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
/**
*
* @author
*/
public class Window extends JFrame {
//Default global variables
private JButton submit;
private JButton cancel;
private JButton reset;
private JPanel panel = new JPanel(new GridBagLayout());
private String searchOutput = "";
//Default constructor
public Window() {
//Title of the window
super("LIBSYS: Search");
//Creating the flow layout to which we can work on and adding panel to frame
setLayout(new FlowLayout());
add(panel, BorderLayout.SOUTH);
//Creating the grid to location of the parts
GridBagConstraints c = new GridBagConstraints();
//Initializing the buttons
submit = new JButton("Submit");
c.insets = new Insets(10, 10, 10, 5);
c.gridx = 1;
c.gridy = 20;
panel.add(submit, c);
reset = new JButton("Reset");
c.gridx = 2;
c.gridy = 20;
panel.add(reset, c);
cancel = new JButton("Cancel");
c.gridx = 3;
c.gridy = 20;
panel.add(cancel, c);
//Handler constructor to do the actionlistening
Handler handler = new Handler();
submit.addActionListener(handler);
reset.addActionListener(handler);
cancel.addActionListener(handler);
//Creating the two dropdowns with the words next to them
JLabel chooseCollection = new JLabel("Choose Collection");
String[] ccString = {"All", "Mostly", "Some", "Few"};
JComboBox ccComboBox = new JComboBox(ccString);
JLabel searchUsing = new JLabel("Search Using");
String[] suString = {"Title", "Artist", "Arthor", "Type"};
JComboBox suComboBox = new JComboBox(suString);
//Adding all the text and dropdown menus to the panel
c.gridx = 0;
c.gridy = 24;
panel.add(chooseCollection, c);
c.gridx = 0;
c.gridy = 25;
panel.add(ccComboBox, c);
c.gridx = 1;
c.gridy = 25;
panel.add(searchUsing, c);
c.gridx = 0;
c.gridy = 27;
panel.add(suComboBox, c);
c.gridx = 1;
c.gridy = 27;
//Setting up the text inputbox
JLabel keyword = new JLabel("Keyword or phrase");
JTextField textField = new JTextField(20);
//Adding lable and text box to the panel
panel.add(keyword);
panel.add(textField);
}
}
问题是您需要了解GridBagLayout。您需要将组件布局到适当的网格上: 因此,您应该有5行12列,以您在图片中描述的方式进行布局。不要介意填充,我试着添加它以使其更具说明性。前三行的每个元素都应该是gridwidth=6,第一行应该是gridx=0,第二行应该是gridx=6。然后,在gridx=6和gridx=9处,yes和no按钮应分别具有gridwidth=3。最后,最后一行按钮应分别具有gridwidth=2和gridx=1、gridx=5和gridx=9。我不使用填充,而是对所有组件使用gbc.anchor=GridBagConstraints.CENTER,以便组件在其网格内居中 我建议对文本字段和组合框使用gbc.fill=GridBagConstraints.HORIZONTAL,这样它们就可以很好地排列起来,但不要忘记将单选按钮和常规按钮设置回gbc.fill=GridBagConstraints.NONE,除非您希望它们也拉伸 我非常随意地更改了您的代码,似乎不符合逻辑顺序:
// Creating the grid to location of the parts
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.CENTER;
// Initializing the buttons
submit = new JButton("Submit");
c.insets = new Insets(10, 10, 10, 5);
c.gridx = 1;
c.gridy = 5;
c.gridwidth = 2;
panel.add(submit, c);
reset = new JButton("Reset");
c.gridx = 5;
// c.gridy = 20;
panel.add(reset, c);
cancel = new JButton("Cancel");
c.gridx = 9;
// c.gridy = 20;
panel.add(cancel, c);
// Handler constructor to do the actionlistening
Handler handler = new Handler();
submit.addActionListener(handler);
reset.addActionListener(handler);
cancel.addActionListener(handler);
// Creating the two dropdowns with the words next to them
JLabel chooseCollection = new JLabel("Choose Collection");
String[] ccString = { "All", "Mostly", "Some", "Few" };
JComboBox ccComboBox = new JComboBox(ccString);
JLabel searchUsing = new JLabel("Search Using");
String[] suString = { "Title", "Artist", "Arthor", "Type" };
JComboBox suComboBox = new JComboBox(suString);
// Adding all the text and dropdown menus to the panel
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 6;
c.anchor = GridBagConstraints.WEST;
panel.add(chooseCollection, c);
c.gridx = 6;
// c.gridy = 25;
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(ccComboBox, c);
c.gridx = 0;
c.gridy = 2;
c.fill = GridBagConstraints.NONE;
panel.add(searchUsing, c);
c.gridx = 6;
// c.gridy = 27;
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(suComboBox, c);
// Setting up the text inputbox
JLabel keyword = new JLabel("Keyword or phrase");
JTextField textField = new JTextField(20);
// Adding lable and text box to the panel
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.NONE;
panel.add(keyword, c);
c.gridx = 6;
panel.add(textField, c);
产生了以下布局:
我会做一个外部边界布局。中间是标签/控件对的GroupLayout。在页面的末尾是按钮的流程布局。 这使用标题边框而不是JLabel来显示LIBSYS搜索。如果它真的需要一个标签,把它放在页面开始的边框布局
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.*;
public class LibSysSearch {
private JComponent ui = null;
LibSysSearch() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
// Here is our control. This puts a titled border around it,
// instead of using a label in the PAGE_START
JPanel libSysSearchControl = new JPanel(new BorderLayout());
ui.add(libSysSearchControl);
JPanel actionPanel = new JPanel(
new FlowLayout(FlowLayout.CENTER, 15, 15));
libSysSearchControl.add(actionPanel, BorderLayout.PAGE_END);
String[] actionNames = {"Search", "Reset", "Cancel"};
for (String name : actionNames) {
actionPanel.add(new JButton(name));
}
// Use GroupLayout for the label/cotrnl combos.
// make the arrays for the factory method
String[] labels = {
"Choose Collection", "Search Using",
"Keyword or phrase", "Adjacent words"
};
String[] ccString = {"All", "Mostly", "Some", "Few"};
String[] suString = {"Title", "Artist", "Arthor", "Type"};
JPanel confirmAdjacent = new JPanel(new FlowLayout(FlowLayout.LEADING,5,0));
confirmAdjacent.add(new JRadioButton("Yes", true));
confirmAdjacent.add(new JRadioButton("No"));
JComponent[] controls = {
new JComboBox(ccString),
new JTextField(20),
new JComboBox(suString),
confirmAdjacent
};
libSysSearchControl.add(getTwoColumnLayout(labels, controls));
// throw in a few borders for white space
Border border = new CompoundBorder(
new EmptyBorder(10, 10, 10, 10),
new TitledBorder("LIBSYS Search"));
border = new CompoundBorder(
border,
new EmptyBorder(10, 10, 10, 10));
libSysSearchControl.setBorder(border);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
LibSysSearch o = new LibSysSearch();
JFrame f = new JFrame("Library System Search");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
/**
* Provides a JPanel with two columns (labels & fields) laid out using
* GroupLayout. The arrays must be of equal size.
*
* Typical fields would be single line textual/input components such as
* JTextField, JPasswordField, JFormattedTextField, JSpinner, JComboBox,
* JCheckBox.. & the multi-line components wrapped in a JScrollPane -
* JTextArea or (at a stretch) JList or JTable.
*
* @param labels The first column contains labels.
* @param fields The last column contains fields.
* @param addMnemonics Add mnemonic by next available letter in label text.
* @return JComponent A JPanel with two columns of the components provided.
*/
public static JComponent getTwoColumnLayout(
JLabel[] labels,
JComponent[] fields,
boolean addMnemonics) {
if (labels.length != fields.length) {
String s = labels.length + " labels supplied for "
+ fields.length + " fields!";
throw new IllegalArgumentException(s);
}
JComponent panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
panel.setLayout(layout);
// Turn on automatically adding gaps between components
layout.setAutoCreateGaps(true);
// Create a sequential group for the horizontal axis.
GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
GroupLayout.Group yLabelGroup = layout.createParallelGroup(GroupLayout.Alignment.TRAILING);
hGroup.addGroup(yLabelGroup);
GroupLayout.Group yFieldGroup = layout.createParallelGroup();
hGroup.addGroup(yFieldGroup);
layout.setHorizontalGroup(hGroup);
// Create a sequential group for the vertical axis.
GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup();
layout.setVerticalGroup(vGroup);
int p = GroupLayout.PREFERRED_SIZE;
// add the components to the groups
for (JLabel label : labels) {
yLabelGroup.addComponent(label);
}
for (Component field : fields) {
yFieldGroup.addComponent(field, p, p, p);
}
for (int ii = 0; ii < labels.length; ii++) {
vGroup.addGroup(layout.createParallelGroup().
addComponent(labels[ii]).
addComponent(fields[ii], p, p, p));
}
if (addMnemonics) {
addMnemonics(labels, fields);
}
return panel;
}
private final static void addMnemonics(
JLabel[] labels,
JComponent[] fields) {
Map<Character, Object> m = new HashMap<Character, Object>();
for (int ii = 0; ii < labels.length; ii++) {
labels[ii].setLabelFor(fields[ii]);
String lwr = labels[ii].getText().toLowerCase();
for (int jj = 0; jj < lwr.length(); jj++) {
char ch = lwr.charAt(jj);
if (m.get(ch) == null && Character.isLetterOrDigit(ch)) {
m.put(ch, ch);
labels[ii].setDisplayedMnemonic(ch);
break;
}
}
}
}
/**
* Provides a JPanel with two columns (labels & fields) laid out using
* GroupLayout. The arrays must be of equal size.
*
* @param labelStrings Strings that will be used for labels.
* @param fields The corresponding fields.
* @return JComponent A JPanel with two columns of the components provided.
*/
public static JComponent getTwoColumnLayout(
String[] labelStrings,
JComponent[] fields) {
JLabel[] labels = new JLabel[labelStrings.length];
for (int ii = 0; ii < labels.length; ii++) {
labels[ii] = new JLabel(labelStrings[ii]);
}
return getTwoColumnLayout(labels, fields);
}
/**
* Provides a JPanel with two columns (labels & fields) laid out using
* GroupLayout. The arrays must be of equal size.
*
* @param labels The first column contains labels.
* @param fields The last column contains fields.
* @return JComponent A JPanel with two columns of the components provided.
*/
public static JComponent getTwoColumnLayout(
JLabel[] labels,
JComponent[] fields) {
return getTwoColumnLayout(labels, fields, true);
}
}
我可能会这样做:
public class Test {
public Test() {
JFrame frame = new JFrame();
JPanel mainPanel = new JPanel(new GridLayout(0, 1));
JPanel chooseCollectionPanel = new JPanel(new BorderLayout());
JPanel keywordPanel = new JPanel(new BorderLayout());
JPanel searchCategoryPanel = new JPanel(new BorderLayout());
// ...
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
chooseCollectionPanel.setBorder(BorderFactory.createEmptyBorder(5, 0,
5, 0));
keywordPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
searchCategoryPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5,
0));
JLabel chooseCollectionLabel = new JLabel("Choose Collection: ");
JComboBox<String> chooseCollectionCB = new JComboBox<String>();
chooseCollectionCB.addItem("All");
chooseCollectionPanel.add(chooseCollectionLabel, BorderLayout.WEST);
chooseCollectionPanel.add(chooseCollectionCB, BorderLayout.CENTER);
JLabel chooseCollectionkeywordLabel = new JLabel("Choose Collection: ");
JTextField keywordCB = new JTextField(10);
keywordPanel.add(chooseCollectionkeywordLabel, BorderLayout.WEST);
keywordPanel.add(keywordCB, BorderLayout.CENTER);
// ...
mainPanel.add(chooseCollectionPanel);
mainPanel.add(keywordPanel);
mainPanel.add(searchCategoryPanel);
// ...
frame.add(mainPanel);
frame.setSize(400, 400);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new Test();
}
}
我不会强迫按钮与其他组件的布局相同。它们是独立的,并且应该自由浮动,间隔均匀 按钮面板应位于具有flowlayout的面板集中。然后,此面板应添加到边框布局位于南部的框架中 其余的组件应放入带有gridbaglayout的面板中,并添加到中心的框架中 gridbaglayout面板应将其所有组件设置在图片中列出的坐标处。如果组件包含两个以上的单元格ie combo,则将gridWidth属性设置为2
提供所需GUI布局的ASCII艺术图或简单绘图,并提供一个没有诸如公共类处理程序实现ActionListener之类的东西的图形{..我知道没有功能的按钮在真实的应用程序中是无用的,但是没有必要演示布局问题。不要尝试在单个组件中执行此操作,使用多个JPanel来维护UI的各个元素,并关注它们的布局要求,构建每个层,如果需要,使用不同的布局管理器o在你得到你需要的结果之前,你不可能有像c.gridy=25这样的东西。我不明白你想用这样的东西做什么。你有27行吗?这似乎很不可能。你的目标是得到你的图片的样子吗?另外,在最后,你只需添加关键字和文本字段,而没有GridBagConstaints对象。我只是使用25作为测试值,看看是否有任何变化。我只是不断增加值,看看它是否会离开屏幕,但是的。当然,GridBagLayouts的强大演示是可行的,但我更喜欢在它的关系容器字段和按钮中分别分解UI,例如,通过这种方式可以添加将更多组件放入容器中,而不会对其他组件的布局产生不利影响……只是说;@MadProgrammer是的,我不是GUI向导,事实上,我希望避免像瘟疫一样的GUI布局。对我来说,我发现GridBagLayout足够通用,我可以用它做任何事情,而不必了解其他组件布局,这就是我一直在做的事情。说实话,据我所知,swing已经死了,甚至JavaFX也没有得到广泛的应用。在我看来,CSS已经赢得了胜利,布局应该通过web技术来完成,Java应该留在后端。一幅图描绘了千言万语,所以一个人的世界THA+1。解释得很好。