问题
Please have a look at the following code
WizardPanel
package wizardGUI;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class WizardPanel extends JDialog
{
private JPanel cardPanel, buttonPanel;
private JButton next,previous;
private CardLayout c1;
private FileSelector fileSelector;
private DelemeterSelector delemeterSelector;
private int count = 1;
public WizardPanel()
{
//Intializing instance variables
fileSelector = FileSelector.getInstance();
delemeterSelector = DelemeterSelector.getInstance();
cardPanel = new JPanel();
c1 = new CardLayout();
cardPanel.setLayout(c1);
cardPanel.add(fileSelector,"1");
cardPanel.add(delemeterSelector,"2");
c1.show(cardPanel, "1");;
buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
next = new JButton("Next");
next.addActionListener(new NextButtonAction());
previous = new JButton("Previous");
buttonPanel.add(next);
buttonPanel.add(previous);
//Creating the GUI
this.setLayout(new BorderLayout());
this.add(cardPanel,"Center");
this.add(buttonPanel,"South");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.setResizable(true);
this.pack();
this.setVisible(true);
}
private class NextButtonAction implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
c1.show(cardPanel, "2");
}
}
}
FileSelector
package wizardGUI;
/*This is the first panel is wazard GUI. Using this window user can select the correct file
which contains the data required to create the table
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FileSelector extends JPanel
{
private JLabel fileName, description;
private JTextField fileTxt;
private JButton browse;
private GridBagLayout gbl;
private GridBagConstraints gbc;
private static FileSelector instance = null;
private FileSelector()
{
//Intializing instance variables
fileName = new JLabel("File Name: ");
description = new JLabel("Specify the source of the data");
fileTxt = new JTextField(10);
browse = new JButton("Browse");
gbl = new GridBagLayout();
gbc = new GridBagConstraints();
//Creating GUI
this.setLayout(gbl);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 0.0;
gbc.weighty = 0.0;
gbc.fill = GridBagConstraints.BOTH;
this.add(description,gbc);
gbc.gridx = 1;
gbc.gridy = 2;
gbc.weightx = 1.0;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(0,10,0,0);
this.add(locationPanel(),gbc);
this.setBorder(BorderFactory.createEmptyBorder());
}
private JPanel locationPanel()
{
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.add(fileName);
panel.add(fileTxt);
panel.add(browse);
return panel;
}
public static FileSelector getInstance()
{
if(instance==null)
{
instance = new FileSelector();
}
return instance;
}
}
DelemeterSelector
/*This is the second windows in wizard
This class is designed to let the user to select the delemeter to break information */
package wizardGUI;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class DelemeterSelector extends JPanel
{
private JLabel description;
private JRadioButton tabBtn, semicolanBtn, commaBtn, spaceBtn;
private JTextArea txtArea;
private JScrollPane scroll;
private ButtonGroup btnGroup;
private GridBagLayout gbl;
private GridBagConstraints gbc;
private static DelemeterSelector instance = null;
private DelemeterSelector()
{
//Initializing instance variables
description = new JLabel("What delemeter separates your fields? Select the appropreiate delemeter");
tabBtn = new JRadioButton("Tab");
semicolanBtn = new JRadioButton("Semicolan");
commaBtn = new JRadioButton("Comma");
spaceBtn = new JRadioButton("Space");
btnGroup = new ButtonGroup();
btnGroup.add(tabBtn);
btnGroup.add(semicolanBtn);
btnGroup.add(commaBtn);
btnGroup.add(spaceBtn);
txtArea = new JTextArea(20,70);
scroll = new JScrollPane(txtArea);
gbl = new GridBagLayout();
gbc = new GridBagConstraints();
this.setLayout(gbl);
//Creating the GUI
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(20,0,0,0);
this.add(description,gbc);
gbc.gridx = 1;
gbc.gridy = 2;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(20,0,0,0);
this.add(radioPanel(),gbc);
gbc.gridx = 1;
gbc.gridy = 3;
gbc.insets = new Insets(10,0,0,0);
gbc.fill = GridBagConstraints.BOTH;
this.add(scroll,gbc);
}
private JPanel radioPanel()
{
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.add(tabBtn);
panel.add(semicolanBtn);
panel.add(commaBtn);
panel.add(spaceBtn);
panel.setBorder(BorderFactory.createTitledBorder("Choose the Delimeter that seperates your fields"));
return panel;
}
public static DelemeterSelector getInstance()
{
if(instance == null)
{
instance = new DelemeterSelector();
}
return instance;
}
}
When I run the code, the "FileSelector" looks really ugly. I want everything to be appear at the top of the pane, but instead, everything appears in middle!! I have even tried GridBagLayout options to make it resizable, it also failed. The look of it is in the attached image
How can I make it look nice and scalable? Please help
回答1:
Just a quick example which shows the same behavior and a fix, without the need for all that external code (an SSCCE)
import javax.swing.*;
import java.awt.*;
public class CardLayoutDemo {
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame( "TestFrame" );
CardLayout cardLayout = new CardLayout();
JPanel contentPane = new JPanel( cardLayout );
JPanel firstPanel = new JPanel( );
firstPanel.setLayout( new BorderLayout( ) );
firstPanel.add( new JLabel( "Contents" ) );
//wrap the smallest panel instead of directly adding it
contentPane.add( firstPanel, "first" );
// JPanel wrappedPanel = new JPanel( new BorderLayout( ) );
// wrappedPanel.add( firstPanel, BorderLayout.NORTH );
// contentPane.add( wrappedPanel, "first" );
JPanel secondPanel = new JPanel( new BorderLayout( ) );
secondPanel.add( new JComponent() {
@Override
public Dimension getPreferredSize() {
return new Dimension( 500, 500 );
}
}, BorderLayout.CENTER );
contentPane.add( secondPanel, "second" );
cardLayout.show( contentPane, "first" );
frame.setContentPane( contentPane );
frame.pack();
frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
frame.setVisible( true );
}
} );
}
}
When you run the code without making changes, it will show you a panel where the contents is centered (the firstPanel). Without making any changes to the firstPanel, but simply by wrapping it you can keep it at the top. Just replace the contentPane.add( firstPanel, "first" ) by the 3 lines (in comment) underneath.
There are a lot of times where nesting layouts makes it easier to get the desired result, and imo this is one of them.
回答2:
The fill constraints are not necessary in this case. Also, gridx and gridy start from 0. This sample code
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(10,0,0,0);
this.add(description,gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weighty = 1;
gbc.insets = new Insets(0,10,0,0);
this.add(locationPanel(),gbc);
produces this
Not sure if this is what you want though.
来源:https://stackoverflow.com/questions/13496874/issues-in-locating-elements-and-re-sizing