Adding a JLabel in relative position to buttons - java

OK, this is the relative code I have so far.
for (int i = gameLines - 1; i > 0; i--)
{
for (int j = 0; j < i; j++)
{
JButton jButton = new JButton();
jButton.setSize(buttonWidth, buttonHeight);
jButton.setText("" + line[i].charAt(j));
int x = ((buttonWidth / 2 * gameLines + 1) - (buttonWidth / 2 * i) + (buttonWidth * j));
int y = (gameLines - (i + 1)) * buttonHeight;
jButton.setLocation(x, y);
panel.add(jButton);
button[i][j] = jButton;
button[i][j].setActionCommand(Integer.toString(i) + "." + Integer.toString(j));
button[i][j].addActionListener(this);
}
}
The code creates and places all my buttons where I want them to be. This took me a while to figure out. I'm originally an AppleSoft BASIC programmer, I'm sorry about the i & j variable names.
Now for the fun. To the right of the bottom 3 rows of buttons, I want to place a jLabel. The right edge of the jLabel is to align with the right edge of the rightmost button in the top row. The text in each will be right justified, ending with a : and an up-to 4 digit number.
I'm thinking I can simply calculate the position like I did the button positions. The text, I was going to add based on a switch/case.
I'm having an trouble understanding JLabels, so I'd appreciate ANY help I can get.
My current thoughts are: to be inserted after the j loop
if (i < 4)
{
JLabel jLable = new JLabel();
JLabel.setSize(???, buttonHeight);
Calculate value of X;
int y = (gameLines - (i +1)) * buttonHeight;
jLabel.setLocation(x,y);
switch (i)
{
case 3:
jLabel.setText("Buttons Clicked: " + buttonsClicked);
break;
case 2:
etc.
}
panel.add(jLabel);
}
HELP please

For a bag of reasons, I would avoid absolute layouts. The moment you run it on some other PC, the whole thing begins to fall apart, instead, you should rely on the layout manager API available in Swing.
The following example uses a compound layout approach. Each row is it's own container (JPanel) and each row is then added to the main panel.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ButtonPyramid {
public static void main(String[] args) {
new ButtonPyramid();
}
public ButtonPyramid() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private String[] lines;
public TestPane() {
lines = new String[]{
"AAFITQPNXBE",
"?AXOPKMSUR",
"TGKFREUDI",
"DFEAAEOY",
"ZDE?VIF",
"G#RMLC",
"YUJGO",
"NSCP",
"KO#",
"MI",
"Y",
"B",
};
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.gridy = 1;
gbc.gridx = 0;
for (String line : lines) {
JPanel panel = new JPanel(new GridBagLayout());
for (char ch : line.toCharArray()) {
JButton btn = new JButton(Character.toString(ch));
btn.setMargin(new Insets(10, 10, 10, 10));
panel.add(btn);
}
add(panel, gbc);
gbc.gridy++;
}
JLabel label = new JLabel(":1234");
gbc.gridy -= 3;
gbc.gridx++;
gbc.anchor = GridBagConstraints.NORTH;
add(label, gbc);
}
}
}
If you would prefer the text not to take up another column, there is a little trick you can try, change the label layout constraints to look like the following instead...
JLabel label = new JLabel(":1234");
gbc.gridy -= 3;
gbc.anchor = GridBagConstraints.NORTHEAST;
add(label, gbc);
Check out Laying out Components within a Container for ideas and details
lines = new char[][]{...};
for (int outter = 0; outter < lines.length; outter++) {
JPanel panel = new JPanel(new GridBagLayout());
for (int inner = 0; inner < lines[outter].length) {
char ch = lines[outter][inner];
JButton btn = new JButton(Character.toString(ch));
btn.setMargin(new Insets(10, 10, 10, 10));
panel.add(btn);
}
add(panel, gbc);
gbc.gridy++;
}

Related

Is there a way to place JButtons with different spaces in the begining at the GridBagLayout?

I'm trying to do something like this:
But I can't leave spaces before the buttons. I have tried to add invisible buttons, but nothing has changed.
for (int i = 0; i < gameSize; i++ ){
c.gridwidth = (i+1)*2;
c.gridx = 0;
c.gridy = 4*i;
JRadioButton temp = new JRadioButton();
temp.setVisible(false);
board.add(temp,c);
for(int j = 0; j < gameSize; j++){
c.gridwidth = 4;
c.gridx = 2+(4*j);
c.gridy = 2+(4*i);
cells[i][j] = new JButton();
cells[i][j].setBackground(Color.white);
board.add(cells[i][j],c);
}
}
It's look like [this:
when I made them visible. I didn't get why width of them is still 4 even though I'm assigning it to (i+1)*2.
I'm new to Java and very very new to Java GUI. So, maybe I didn't figure out the most basic thing. Thanks for advices!
I created the following GUI.
In order to do this, I had to use a combination of Swing layouts.
The buttons on each row are created in a JPanel with a GridLayout. The row is created with a row JPanel with a FlowLayout, using a dummy JLabel and the button row JPanel.
The main JPanel uses a GridLayout of (0, 1) to create the staggered effect. The dummy JLabel in each row gets bigger by half the size of the JButtons.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GridBagLayoutStaggeredGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new GridBagLayoutStaggeredGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("Staggered Layout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
int gameSize = 8;
int buttonSize = 50;
int inset = 2;
JButton[][] cells = new JButton[gameSize][gameSize];
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
for (int i = 0; i < gameSize; i++) {
JPanel innerPanel = new JPanel(
new FlowLayout(FlowLayout.LEADING, 0, 0));
JLabel label = new JLabel();
label.setPreferredSize(new Dimension(inset, buttonSize));
innerPanel.add(label);
innerPanel.add(createRowPanel(cells[i], buttonSize));
panel.add(innerPanel);
inset += buttonSize / 2;
}
return panel;
}
private JPanel createRowPanel(JButton[] cells, int buttonSize) {
JPanel panel = new JPanel(new GridLayout(0, cells.length, 0, 0));
for (int i = 0; i < cells.length; i++) {
cells[i] = new JButton();
cells[i].setBackground(Color.white);
cells[i].setPreferredSize(new Dimension(buttonSize, buttonSize));
panel.add(cells[i]);
}
return panel;
}
}
The GridBagLayout can only calculate the width of a column if there is a component added to the column with a "gridwidth" of 1.
In your example you have 6 button each with a "gridwidth" of 2, implying you really want 12 columns. But what should the width of each column be?
The example below shows how to allocate a minimum width for each column. Now each of the 12 columns will have a minimum width based on the value specified.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
public class GridBagLayoutMRE extends JPanel
{
public GridBagLayoutMRE()
{
int gameSize = 6;
int columnsNeeded = (gameSize * 3);
int cellSize = 30;
Dimension buttonSize = new Dimension(cellSize * 2, cellSize);
GridBagLayout gbl = new GridBagLayout();
setLayout( gbl );
int[] columnWidths = new int[columnsNeeded];
Arrays.fill(columnWidths, cellSize);
gbl.columnWidths = columnWidths;
GridBagConstraints gbc = new GridBagConstraints();
for (int i = 0; i < gameSize; i++)
{
gbc.gridx = 0;
gbc.gridy = i;
gbc.gridwidth = 1;
JRadioButton rb = new JRadioButton();
rb.setPreferredSize( new Dimension(60, cellSize) );
add(rb, gbc);
gbc.gridx = i + 1;
gbc.gridwidth = 2;
for (int j = 0; j < gameSize; j++)
{
JButton button = new JButton();
button.setPreferredSize( buttonSize );
add(button, gbc);
gbc.gridx = gbc.gridx + gbc.gridwidth;
}
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("GridBagLayoutMRE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout( new GridBagLayout() );
frame.add(new GridBagLayoutMRE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}

Adding multiple sets of JLabel and JTextBox to the same line in Java

I'm building an equation solver that allows the user to enter a system of equations and then get the answer. So, I need to build a GUI that allows the user to enter the set of equations. I decided to go about doing this from scratch. Here's what my code looks like:
private JFrame frame;
private JTextField[][] text;
private JLabel label;
private JLabel equalLabel;
private JLabel plusLabel;
private JTextField answerText;
private void displayGetEquations(int total)
{
frame = new JFrame("Enter Equations");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
equalLabel = new JLabel();
equalLabel.setText(" = ");
plusLabel = new JLabel();
plusLabel.setText(" + ");
answerText = new JTextField();
answerText.setColumns(2);
frame.setLayout(new GridLayout(0,10));
text = new JTextField[3][3];
for(int i = 0 ; i < 3 ; i++)
{
panel = new JPanel();
panel.setLayout(new FlowLayout());
for(int j = 0 ; j < 3 ; j++)
{
text[i][j] = new JTextField();
text[i][j].setColumns(2);
label = new JLabel();
Font font = label.getFont();
Font boldFont = new Font(font.getFontName(), Font.BOLD, font.getSize());
label.setFont(boldFont);
label.setText("x");
panel.add(text[i][j]);
panel.add(label);
panel.add(plusLabel);
}
panel.add(equalLabel);
panel.add(answerText);
frame.add(panel);
frame.revalidate();
frame.repaint();
}
frame.pack();
frame.setVisible(true);
}
This is what I get when I run the above code:
But I am not getting the desired output, which, I would like to be something like this:
This was made using the drag and drop feature of NetBeansWhat am I doing wrong? Is what I want even possible?
Any help would be appreciated.
Thanks !
(This was made using the drag and drop feature of NetBeans)
Your code is a little bit confusing and the one posted here isn't a MCVE, as it lacks a main method and imports and a variable panel, as well as it's giving me a different output than the one you posted:
From your example-output images I made 2 approaches, one which uses multiple JPanel with a FlowLayout inside another one with BoxLayout and another one which uses a single JPanel with a GridLayout. Another approach could be using GridBagLayout
I used x, y and z variable names because I thought you were using an equation solving program or something like that.
Here's the code that produces the above outputs:
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MultipleComponentsInRow {
public static final int ROWS = 3;
public static final int COLS = 4;
private JFrame frame;
private JPanel flowLayoutPanel;
private JPanel gridLayoutPanel;
private JTextField[][] flowFields;
private JTextField[][] gridFields;
private void createAndShowGui() {
frame = new JFrame("Multiple Components In Row");
flowFields = new JTextField[ROWS][COLS];
gridFields = new JTextField[ROWS][COLS];
flowLayoutPanel = new JPanel();
flowLayoutPanel.setLayout(new BoxLayout(flowLayoutPanel, BoxLayout.PAGE_AXIS));
gridLayoutPanel = new JPanel();
gridLayoutPanel.setLayout(new GridLayout(ROWS, 7));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
flowFields[i][j] = new JTextField(2);
gridFields[i][j] = new JTextField(2);
}
}
//FlowLayout approach
for (int i = 0; i < ROWS; i++) {
JPanel pane = new JPanel();
pane.setLayout(new FlowLayout());
for (int j = 0; j < COLS; j++) {
pane.add(flowFields[i][j]);
switch (j) {
case 0:
pane.add(new JLabel(" x + "));
break;
case 1:
pane.add(new JLabel(" y + "));
break;
case 2:
pane.add(new JLabel(" z = "));
break;
default:
break;
}
}
flowLayoutPanel.add(pane);
}
//GridLayout approach
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
gridLayoutPanel.add(gridFields[i][j]);
switch (j) {
case 0:
gridLayoutPanel.add(new JLabel(" x + "));
break;
case 1:
gridLayoutPanel.add(new JLabel(" y + "));
break;
case 2:
gridLayoutPanel.add(new JLabel(" z = "));
break;
default:
break;
}
}
}
frame.setLayout(new GridLayout(1, 2, 5, 5));
flowLayoutPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLACK), "Flow Layout"));
gridLayoutPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.RED), "Grid Layout"));
frame.add(flowLayoutPanel);
frame.add(gridLayoutPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new MultipleComponentsInRow().createAndShowGui();
}
}
Think about the theory here. Big picture view: You have a frame with a panel right? Why not have a frame with 3 panels? The frame layout will be a vertical stackpane and the each panel will be a horizontal layout with the 4 textfields. You may want consider using JavaFX where you could do something like:
...
HBox hBox1 = new Hbox();
hBox1.getChildern.addAll(new Textfield(), new Textfield(), new Textfield());
... //repeat 2 more times
Vbox vbox = new VBox(hBox1, hBox2, hBox3);
...
Then you have 3x horizontal layouts contained in 1 vertical layout.

Java GridBagLayout - Equal column width in different containers

I've been having a problem with the GridBagLayout for a few hours but I don't get to solve it. I have two JPanels (which contain JTextFields) in a JFrame. The first (upper) JPanel has a grid of 3 rows and 2 columns. The second (lower) JPanel has a grid of 3 rows and 3 columns. I need them to be aligned as in the next figure (white column in the upper JPanel means space; the numbers indicate the relative width) and the proportions to be consistent as the size of the window changes.
The code that I have is the next:
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
public class FrameWithTwoPanels {
private GridBagConstraints constraints;
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FrameWithTwoPanels window = new FrameWithTwoPanels();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public FrameWithTwoPanels() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Populate the frame with two Panels
frame.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridy = 0;
// PANEL 1: 3 rows and 2 columns
frame.add(this.createPanel(3, 2), c);
// PANEL 2: 3 rows and 3 columns
c.gridy = 1;
frame.add(this.createPanel(3, 3), c);
frame.pack();
frame.setLocationRelativeTo(null);
}
private JPanel createPanel(int numrows, int numcols){
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
constraints = new GridBagConstraints();
//constraints.fill = GridBagConstraints.BOTH;
for(int row=0; row<numrows; row++){
for(int col =0; col<numcols; col++){
JTextField component = new JTextField(row + "-" + col);
if(col == 0){
constraints.weightx = 0.5;
}else if(col == 1){
constraints.weightx = 0.4;
}else if(col == 2){
constraints.weightx = 0.1;
}
constraints.gridy = row;
constraints.gridx = col;
panel.add(component, constraints);
if(numcols == 2 && col == 1){
// Add auxiliar panel
constraints.weightx = 0.1;
constraints.gridx = col + 1;
panel.add(new JLabel());
}
}
}
panel.setBorder(new TitledBorder("Number of columns: " + numcols));
return panel;
}
}
The code gives the form shown in the screenshot:
This is a circumstance where you're actually better off using plain GridLayout. I think the following code does what you want:
private JPanel createPanel(int numrows, int numcols) {
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(numrows, 3));
for (int row = 0; row < numrows; row++) {
for (int col = 0; col < numcols; col++) {
JTextField component = new JTextField(row + "-" + col);
panel.add(component);
if (numcols == 2 && col == 1) {
JPanel spacer = new JPanel();
panel.add(spacer);
}
}
}
panel.setBorder(new TitledBorder("Number of columns: " + numcols));
return panel;
}

JPanel component placement

I am trying to get a basic GUI program. It doesnt have to do much but the buttons at the bottom have to work. I am having trouble placing the components (The text, combobox, etc) in the proper spot. Using the GridBag I am able to change the location with the c.gridx and c.gridy but in a very weird way. If I put the gridy values 0-7 with x being 0 everything is on top of eachother. I try putting the combo box next to the text by changing the gridx value and everything gets messed up. The alignment is off on the components after the one I was trying to move over. How do I fix this? I tried the BorderLayout.DIRECTION with no luck. The actual change doesn't take effect at all (moving then to the bottom). How do I fix this? Thanks
/*
* 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);
}
}
I would not try and force the buttons into the same layout as the other components. They are independant and should be free floating evenly spaced.
The button panel should be in a panel set with flowlayout. Then this panel should be added to the frame with borderlayout at SOUTH.
The rest of the components should go into a panel with gridbaglayout and added to the frame at CENTER.
The gridbaglayout panel then should have all its components set at the coordinates listed in the picture. If the component covers more than two cells (ie combo) then set the gridWidth property to 2.
I'd do it by having an outer BorderLayout. In the CENTER would be a GroupLayout for the label/control pairs. In the PAGE_END would be a FlowLayout for the buttons.
This uses a TitledBorder instead of the JLabel to show LIBSYS Search. If it really needs a label, put it in the PAGE_START of the border layout.
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);
}
}
The problem is that you need to understand GridBagLayout. You need to layout your components onto a proper grid:
So you should have 5 rows and 12 columns to layout the way you described in your picture. Don't mind the padding (I tried to add that to make it more illustrative). Your first three rows should each have elements of gridwidth = 6 and the first should be at gridx = 0 and the second at gridx = 6. Then your "yes" and "no" buttons should each have gridwidth = 3 at gridx = 6 and gridx = 9, respectively. Finally your last row, the buttons, should each have gridwidth = 2 and gridx = 1, gridx = 5, and gridx = 9, respectively. Instead of using padding, I would just use gbc.anchor = GridBagConstraints.CENTER (for all of the components) so that the components are centered inside of their grid.
I would suggest using gbc.fill = GridBagConstraints.HORIZONTAL for the text field and combo boxes so that they line up "nice and pretty" but don't forget to set that back to gbc.fill = GridBagConstraints.NONE for the radio buttons and regular buttons (unless you want them to stretch as well).
I very haphazardly changed your code (which appeared to be in no logical order):
// 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);
Which produced the following layout:
i would probably do it like this:
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();
}
}

JTable splitting cells. How to

I'm new to Swing and I want to create a table having this form:
So How to split a cell like the table shows?
Have you any useful links or tutorials or an idea?
This looks like a bowling score card to me. Based on that assumption, the number of columns is fixed, and the number of entries tends to be 6 or less. Since you likely won't need scrolling, I would recommend a fixed grid of components instead of a JTable.
This could easily be acheived using GridBagLayout. For the name, I'd use a JTextArea. For the 2 scoring cells for each frame, I'd use JTextFields. For the bottom 2-column-span component that holds the frame's score I'd probably use a JLabel.
Put all of this on a JPanel, and recreate the panel for each bowler.
EDIT:
Here's a quick mock-up just to show the concept. Not necessarily visually pretty, but I'll leave that as an exercise for the reader:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class BowlingScoreCard implements Runnable
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new BowlingScoreCard());
}
public void run()
{
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(createScorecard(4), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JPanel createScorecard(int numPlayers)
{
JPanel p = new JPanel(new GridBagLayout());
p.add(new JLabel("Player"), gbc(0, 0, 1, 1));
for (int x = 1; x <= 10; x++)
{
p.add(new JLabel(Integer.toString(x)), gbc(x, 0, 1, 1));
}
for (int y = 1; y <= numPlayers; y++)
{
JTextArea textArea = new JTextArea(2, 10);
p.add(textArea, gbc(0, y, 1, 1));
for (int i = 1; i <= 9; i++)
{
p.add(createFrame(2), gbc(i, y, 1, 1));
}
p.add(createFrame(3), gbc(10, y, 1, 1));
}
return p;
}
private JPanel createFrame(int entries)
{
JLabel label = new JLabel(" ");
label.setBackground(Color.GRAY);
JPanel p = new JPanel(new GridBagLayout());
p.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
for (int i = 0; i < entries; i++)
{
p.add(new JTextField(3), gbc(i, 0, 1, 1));
}
p.add(label, gbc(0, 1, 2, 1));
return p;
}
private GridBagConstraints gbc(int x, int y, int colspan, int rowspan)
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = colspan;
gbc.gridheight = rowspan;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.NONE;
return gbc;
}
}

Categories