I use gridbaglayout to dynamically construct the JPANEL from an array of label and button. And i want the label to stretch its width as the panel dimension is been changed by user. I have the weightx and fill constraints and still this is not working. This inner Gridbaglayout panel is been enclosed by an another outer panel of grid layout.
Thanks in advance for your comments and suggestions.
Below is the SC for this case -
JPanel flowpanel = new JPanel(new GridBagLayout());
JPanel boxPanel = new JPanel(new GridLayout(2,0));
int valueCount =8;
void labelPropertySetter(JLabel label, JButton button, String name) throws IOException {
label.setPreferredSize(new Dimension(200,55));
label.setText(name);
button.setPreferredSize(new Dimension(100,55));
button.setName(name);
button.setText(name);
}
public static void main (String[] args) throws IOException {
DemoPanel dp = new DemoPanel();
JLabel[] numberLabel = new JLabel[dp.valueCount];
JButton[] button = new JButton[dp.valueCount];
for (int i=0;i<dp.valueCount;i++) {
try {
//jpanel[i]= new JPanel(new BorderLayout(0,0));
numberLabel[i]=new JLabel();
button[i]=new JButton();
button[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
((JButton)e.getSource()).setVisible(false);
System.out.println(((JButton)e.getSource()).getName());
}
});
dp.labelPropertySetter(numberLabel[i], button[i], new StringBuilder("Name :").append(i).toString());
//dp.boxPanel.add(jpanel[i]);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
GridBagConstraints gbc = new GridBagConstraints();
for(int i=0;i<dp.valueCount;i++)
{
gbc.gridx=1;
gbc.gridy=i;
gbc.gridheight=1;
gbc.gridwidth=1;
gbc.weightx=1.0;
gbc.fill=GridBagConstraints.HORIZONTAL;
gbc.anchor=GridBagConstraints.CENTER;
dp.flowpanel.add(numberLabel[i], gbc);
gbc.gridx=2;
gbc.gridy=i;
gbc.gridheight=1;
gbc.gridwidth=1;
gbc.weightx=0;
gbc.anchor=GridBagConstraints.LINE_END;
dp.flowpanel.add(button[i], gbc);
}
dp.boxPanel.setPreferredSize(new Dimension(500,500));
dp.boxPanel.add(dp.flowpanel);
dp.add(dp.boxPanel);
dp.pack();
dp.setVisible(true);
}
}
Related
I'm trying to put components into panels having different sizes. But, I realized that GridLayout divides the parts with same sizes. How can it be accomplished as explained below image
enter image description here
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class PanelDemo {
PanelDemo() {
// Create a new JFrame container. Use the default
// border layout.
JFrame jfrm = new JFrame("Use Three JPanels with Different Sizes");
// Specify FlowLayout manager.
jfrm.getContentPane().setLayout(new GridLayout(1, 3));
// Give the frame an initial size.
jfrm.setSize(900, 300);
// Terminate the program when the user closes the application.
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create the first JPanel.
JPanel jpnl = new JPanel();
jpnl.setLayout(new GridLayout(2, 4));
// Set the preferred size of the first panel.
jpnl.setPreferredSize(new Dimension(500, 300));
// Make the panel opaque.
jpnl.setOpaque(true);
// Add a blue border to the panel.
jpnl.setBorder(
BorderFactory.createLineBorder(Color.BLUE));
// Create the second JPanel.
JPanel jpnl2 = new JPanel();
//jpnl2.setLayout(new FlowLayout());
// Set the preferred size of the second panel.
jpnl2.setPreferredSize(new Dimension(300, 300));
// Make the panel opaque.
jpnl2.setOpaque(true);
jpnl2.setBorder(
BorderFactory.createLineBorder(Color.RED));
JPanel jpnl3 = new JPanel();
jpnl3.setOpaque(true);
jpnl3.setPreferredSize(new Dimension(100, 300));
jpnl3.setBorder(
BorderFactory.createLineBorder(Color.ORANGE));
// Add the panels to the frame.
jfrm.getContentPane().add(jpnl);
jfrm.getContentPane().add(jpnl3);
jfrm.getContentPane().add(jpnl2);
// Display the frame.
jfrm.setVisible(true);
}
public static void main(String args[]) {
// Create the frame on the event dispatching thread.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new PanelDemo();
}
});
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class TwoPanelWithButtonsLayout {
private JComponent ui = null;
private Insets buttonMargin = new Insets(10,10,10,10);
TwoPanelWithButtonsLayout() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new BorderLayout(4,4));
ui.setBorder(new EmptyBorder(4,4,4,4));
int gap = 5;
JPanel buttons1 = new JPanel(new GridLayout(2, 4, gap, gap));
// 50 is the gap on right, alter as needed
buttons1.setBorder(new EmptyBorder(0, 0, 0, 50));
for (int ii=1; ii<9; ii++) {
buttons1.add(getBigButton("" + ii));
}
ui.add(buttons1, BorderLayout.CENTER);
JPanel buttons2 = new JPanel(new GridLayout(2, 2, gap, gap));
for (int ii=1; ii<5; ii++) {
buttons2.add(getBigButton("" + ii));
}
ui.add(buttons2, BorderLayout.LINE_END);
}
private JButton getBigButton(String text) {
JButton b = new JButton(text);
Font f = b.getFont();
b.setFont(f.deriveFont(f.getSize()*3f));
b.setMargin(buttonMargin);
return b;
}
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) {
}
TwoPanelWithButtonsLayout o = new TwoPanelWithButtonsLayout();
JFrame f = new JFrame(o.getClass().getSimpleName());
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);
}
}
You could use FlowLayout but if they resize your frame then it will wrap the panels.
I have created a JFrame in which I have created JTextArea.I have passed this JTextArea as a constructor to the other class. The JFrame is as follows:
JFrame frame = new JFrame("Find");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
JTextArea textArea = new JTextArea(20,15);
frame.add(textArea,BorderLayout.NORTH);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
Texts text = new Texts(textArea);
frame.add(text.pane(),BorderLayout.CENTER);
JScrollPane pane = new JScrollPane(textArea);
pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
pane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
frame.setSize(400, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent ev) {
JOptionPane.showMessageDialog(null, "Thank you for using finder");
System.exit(0); //Close program
}
});
}
I have passed the JTextArea to other class however it is not being displayed in the JFrame only the buttons show up.:
public class Texts {
public JTextArea tx;
JTextField findField = new JTextField( 10);
int pos = 0;
public Texts(JTextArea textArea) {
// TODO Auto-generated constructor stub
tx=textArea;
tx.setVisible(true);
}
public Component pane() {
// TODO Auto-generated method stub
JButton findButton = new JButton("Find");
JButton clearButton = new JButton("Clear");
JPanel header = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
header.add(findField, gbc);
gbc.gridx++;
header.add(findButton, gbc);
tx.add(header, BorderLayout.SOUTH);
header.add(clearButton);
findButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Get the text to find...convert it to lower case for easier comparison
String find = findField.getText();
// Focus the text area, otherwise the highlighting won't show up
tx.requestFocusInWindow();
// Make sure we have a valid search term
if (find != null && find.length() > 0) {
Document document = tx.getDocument();
..........
First you do this...
frame.add(textArea,BorderLayout.NORTH);
Then you do this...
JScrollPane pane = new JScrollPane(textArea);
This effectively removes the textArea from the frame, this is because a component can only have a single parent.
Instead, try something like...
JScrollPane pane = new JScrollPane(textArea);
frame.add(pane,BorderLayout.NORTH);
I want to position the JPanel that contains the send button and the textfield (and right now uses a flowlayout) at the bottom of the JTextArea (The white area).
How can I achieve this?
public GUI()
{
mainWindow = new JFrame("Chat GUI");
lowerPanel = new JPanel(new FlowLayout());
usersPanel = new JPanel(new GridLayout(GRIDLAYOUT_ROWS, GRIDLAYOUT_COLS));
users = new JList(data);
usersPanel.add(users);
sendButton = new JButton("Send");
textField = new JTextField(TEXTFIELD_WIDTH);
textArea = new JTextArea(TEXTAREA_HEIGHT, TEXTAREA_WIDTH);
textArea.setEditable(false);
}
private void addButtonListener(JButton b) {
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
}
public void createGUI() {
addButtonListener(sendButton);
lowerPanel.add(sendButton);
lowerPanel.add(textField);
mainWindow.add(users);
mainWindow.add(textArea);
mainWindow.add(lowerPanel);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setVisible(true);
mainWindow.setLayout(new FlowLayout());
mainWindow.pack();
}
You Will have Layout :
this.add(buttonPanel,BorderLayout.SOUTH);
see this answer
So I'm adding this code to a JFrame which has other layout managers and components in them.
private JPanel testing123() {
JPanel j = new JPanel(new FlowLayout());
jbtOk = new JButton("OK");
jbtOk.setMnemonic('K');
jbtExit = new JButton("Exit");
jbtExit.setMnemonic('x');
add(jbtOk);
add(jbtExit);
j.add(jbtOk);
j.add(jbtExit);
return j;
}
Without this code, the JFrame looks fine, but when I add it, it adds a large amount of empty space under these two buttons. Why is this happening?
This replicates it:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class Test extends JFrame implements ActionListener, KeyListener {
JButton jbtOk, jbtExit;
JPanel p = new JPanel(new GridLayout(0,1));
JPanel gui = new JPanel(new BorderLayout(2,2));
public Test() {
super("t");
//setSize(300,300);
setVisible(true);
JPanel test = test();
JPanel testing = testing();
JPanel testing123 = testing123();
p.add(test);
p.add(testing);
p.add(testing123);
this.getContentPane().add(p);
pack();
}
private JPanel test() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel labelFields = new JPanel(new BorderLayout(2,2));
labelFields.setBorder(new TitledBorder("m"));
p.add(gui);
p.add(labelFields);
JPanel labels = new JPanel(new GridLayout(0,1,1,1));
labels.setBorder(new TitledBorder("a"));
JPanel fields = new JPanel(new GridLayout(0,1,1,1));
fields.setBorder(new TitledBorder("b"));
p.add(labels);
p.add(fields);
add(fields);
add(p);
return gui;
}
private JPanel testing() {
JPanel guiCenter = new JPanel(new FlowLayout(FlowLayout.CENTER));
guiCenter.setBorder(new TitledBorder("n"));
guiCenter.add(new JScrollPane(new JTextArea(5,30)));
gui.add(guiCenter, BorderLayout.CENTER);
return guiCenter;
}
private JPanel testing123() {
JPanel j = new JPanel(new FlowLayout());
jbtOk = new JButton("OK");
jbtOk.setMnemonic('K');
jbtExit = new JButton("Exit");
jbtExit.setMnemonic('x');
//add(jbtOk);
//add(jbtExit);
j.add(jbtOk);
j.add(jbtExit);
return j;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
"I want to get rid of the extra space under the OK and Exit buttons."
The problem is you are using the GridLayout that will make all the JPanel equal size. What you should do instead is wrap the first four JPanel in GridLayout, then keep the default BorderLayout of the JFrame, add the JPanel to BorderLayout.CENTER of the JFrame and add the buttons JPanel to the BorderLayout.PAGE_END. This should solve the problem
public Test() {
super("t");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel test = test();
JPanel testing = testing();
JPanel testing123 = testing123();
p.add(test);
p.add(testing);
add(p, BorderLayout.CENTER); <---
add(testing123, BorderLayout.PAGE_END); <---
pack();
setVisible(true);
}
Complete running code
import java.awt.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class Test extends JFrame {
JButton jbtOk, jbtExit;
JPanel p = new JPanel(new GridLayout(0, 1));
JPanel gui = new JPanel(new BorderLayout(2, 2));
public Test() {
super("t");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel test = test();
JPanel testing = testing();
JPanel testing123 = testing123();
p.add(test);
p.add(testing);
add(p, BorderLayout.CENTER);
add(testing123, BorderLayout.PAGE_END);
pack();
setVisible(true);
}
private JPanel test() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel labelFields = new JPanel(new BorderLayout(2, 2));
labelFields.setBorder(new TitledBorder("m"));
p.add(gui);
p.add(labelFields);
JPanel labels = new JPanel(new GridLayout(0, 1, 1, 1));
labels.setBorder(new TitledBorder("a"));
JPanel fields = new JPanel(new GridLayout(0, 1, 1, 1));
fields.setBorder(new TitledBorder("b"));
p.add(labels);
p.add(fields);
return gui;
}
private JPanel testing() {
JPanel guiCenter = new JPanel(new FlowLayout(FlowLayout.CENTER));
guiCenter.setBorder(new TitledBorder("n"));
guiCenter.add(new JScrollPane(new JTextArea(5, 30)));
gui.add(guiCenter, BorderLayout.CENTER);
return guiCenter;
}
private JPanel testing123() {
JPanel j = new JPanel(new FlowLayout());
jbtOk = new JButton("OK");
jbtOk.setMnemonic('K');
jbtExit = new JButton("Exit");
jbtExit.setMnemonic('x');
j.add(jbtOk);
j.add(jbtExit);
return j;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Test();
}
});
}
}
My application is in fullscreen exclusive mode, i want the JPanel mainPanel to be in LAST_LINE_START with some padding to the left and right. but when i run this program it only shows the mainPanel in center of the screen. I tried other positions also, but they did not work either.
private void mainWindow()
{
gls =(JPanel) mainUi.getGlassPane();
gls.setLayout(new GridBagLayout());
JPanel mainPanel = new JPanel(new GridLayout(4,1));
nwGame = new JButton("New Game");
nwGame.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
gls.setVisible(false);
startGame(0);
mainUi.repaint();
}
});
ldGame = new JButton("Load Game");
ldGame.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
}
});
changeProfile = new JButton("Change Profile");
changeProfile.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
}
});
qtGame = new JButton("Quit Game");
qtGame.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.ipadx = 10;
gbc.ipady = 10;
gbc.anchor = GridBagConstraints.LAST_LINE_START;
mainPanel.add(nwGame);
mainPanel.add(ldGame);
mainPanel.add(changeProfile);
mainPanel.add(qtGame);
gls.add(mainPanel,gbc);
gls.setVisible(true);
mainUi.add(gls);
if(!mainUi.isVisible())
mainUi.setVisible(true);
}
Whenever I see...
it only shows the mainPanel in center of the screen
...associated with GridBagLayout, I always look first to see how the user is implementing the weightx and weighty GridBagConstraint properties, and as expected, you aren't. Use them.
i.e.,
GridBagConstraints gbc = new GridBagConstraints();
gbc.ipadx = 10;
gbc.ipady = 10;
gbc.anchor = GridBagConstraints.LAST_LINE_START;
gbc.weightx = 1.0;
gbc.weighty = 1.0;