Im trying to build a tic tac toe game with swing. Using grid layout its coming out to weird numbers of rows and columns and cant seem to get it to 3x3. What am I doing wrong? Should I just use a float layout and set positions?
import java.awt.*;
import javax.swing.*;
public class main {
public static void main(String[] args) {
JFrame frame = new JFrame("Tic Tac Toe");
JPanel panel = new JPanel();
frame.add(panel);
GridLayout grid = new GridLayout(3,3);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
frame.setLayout(grid);
frame.setResizable(false);
JButton button1 = new JButton();
JButton button2 = new JButton();
JButton button3 = new JButton();
JButton button4 = new JButton();
JButton button5 = new JButton();
JButton button6 = new JButton();
JButton button7 = new JButton();
JButton button8 = new JButton();
JButton button9 = new JButton();
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.add(button5);
frame.add(button6);
frame.add(button7);
frame.add(button8);
frame.add(button9);
}
}
Although you have already accepted #JustinCoding answer, I feel obliged to also answer since that answer doesn't really explain why your code did not produce your desired result.
Your problem is that you are adding an empty JPanel to the JFrame as well as your JButtons. Just remove that part of the code. Here is your corrected code. I commented the lines that need to be removed.
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
//import javax.swing.JPanel;
public class main {
public static void main(String[] args) {
JFrame frame = new JFrame("Tic Tac Toe");
// JPanel panel = new JPanel();
// frame.add(panel);
GridLayout grid = new GridLayout(3, 3);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
frame.setLayout(grid);
frame.setResizable(false);
JButton button1 = new JButton();
JButton button2 = new JButton();
JButton button3 = new JButton();
JButton button4 = new JButton();
JButton button5 = new JButton();
JButton button6 = new JButton();
JButton button7 = new JButton();
JButton button8 = new JButton();
JButton button9 = new JButton();
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.add(button5);
frame.add(button6);
frame.add(button7);
frame.add(button8);
frame.add(button9);
}
}
This is how it looks when I run the code.
Explanation
Originally, in order to add components to a JFrame, you had to first call method getContentPane which returned a Container that you could add components to. JFrame is referred to as a top level container and its content pane is the container for all the components that you add to it. The default content pane is a JPanel whose layout manager is BorderLayout. Hence no need to add your components to a JPanel and add that JPanel to the JFrame. You can add components directly to the JFrame. Just be aware that when you are adding components directly to a JFrame, you are actually adding them to a JPanel with BorderLayout.
And since the content pane is a JPanel, you are free to also change its layout manager – as you have done in your code via this line:
frame.setLayout(grid);
Note that you only need to set one of the dimensions in the GridLayout constructor. Here is a quote from the javadoc of that constructor.
One, but not both, of rows and cols can be zero, which means that any number of objects can be placed in a row or in a column.
In other words, for your tic-tac-toe game, you need only set the columns to 3. That means that each row will contain no more than three columns so when you add nine buttons, GridLayout will ensure that they will be arranged in three rows of three columns each. Hence, for your tic-tac-toe board, you can use the following code.
GridLayout grid = new GridLayout(0, 3); // zero rows and three columns
First of all, Thanks to #Abra for pointing out that I had not added any explanation, because I was writing the answer in a bit hurry.
Follow these steps first:
Assign the layout to your panel like this: panel.setLayout(grid);
Then, add the panel to your frame like this: frame.add(panel);
Then, add all your widgets to the panel by replacing frame with panel where you're adding your Buttons.
And now, your JFrame bugged out a bit because you were also adding an empty JPanel to your Frame. I made you add the JPanel to the JFrame and assign the grid layout to the Panel just because I thought that a Tic-Tac-Toe game would include the showing of results of the game. So, you can simply use the remove() method to remove the JPanel and add the Results JPanel.
Related
Task: make the same window as in the screenshot below using JAVA swing:
What did I do:
Created a panel for the top block (BorderLayout), added two more panels to it (GridLayour), one for the left buttons(FR, FG, FB), the other for the right buttons (A, B,C), added it all to my JFrame window
Created a JScrollPane and added it to the JFrame too
Created a panel for the bottom block (BorderLayout), added two more panels to it (GridLayour), one for the left buttons(1,2,3,4...), the other for the JTextFiel text field, added it all to my JFrame window.
The result is below:
I tried using other layouts, but it still doesn't work. I attach the code.
import javax.swing.*;
import java.awt.*;
public class MyJFrame extends JFrame {
JPanel pan1 = new JPanel();
JPanel pan2 = new JPanel();
JPanel pan3 = new JPanel();
JPanel pan4 = new JPanel();
JPanel pan5 = new JPanel();
JPanel pan6 = new JPanel();
JButton jButton1 = new JButton("FR");
JButton jButton2 = new JButton("FG");
JButton jButton3 = new JButton("FB");
JButton jButton4 = new JButton("A");
JButton jButton5 = new JButton("B");
JButton jButton6 = new JButton("C");
public MyJFrame(){
super("Simple Swing App");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocation(650,300);
setLayout(new GridLayout(3,2));
setResizable(true);
JScrollPane scrollPane = new JScrollPane();
jButton1.setBackground(Color.red);
jButton2.setBackground(Color.green);
jButton3.setBackground(Color.blue);
pan1.setLayout(new GridLayout(1,3,2,2));
pan2.setLayout(new GridLayout(1,3,2,2));
pan3.setLayout(new BorderLayout());
pan4.setLayout(new GridLayout(3,3,2,2));
pan5.setLayout(new GridLayout(3,1,1,1));
pan6.setLayout(new BorderLayout());
pan1.add(jButton1);
pan1.add(jButton2);
pan1.add(jButton3);
pan2.add(jButton4);
pan2.add(jButton5);
pan2.add(jButton6);
pan3.add(pan1, BorderLayout.WEST);
pan3.add(pan2, BorderLayout.EAST);
for (int i=1; i<10; i++) {
JButton jButton = new JButton(i+"");
pan4.add(jButton);
}
for (int i=1; i<4; i++){
JTextField jTextField = new JTextField(" Pole tekstowe " + i + " typu jTextField ");
jTextField.setBackground(Color.WHITE);
jTextField.setBorder(BorderFactory.createLineBorder(Color.CYAN));
pan5.add(jTextField);
}
pan6.add(pan4, BorderLayout.WEST);
pan6.add(pan5, BorderLayout.EAST);
add(pan3);
add(scrollPane);
add(pan6);
setSize(700,450);
setVisible(true);
}
}
If the question is "How to make this GUI?" I would use this approach:
3 x BorderLayout (red) - one for the entire GUI, one each for the PAGE_START and PAGE_END constraints of the main GUI panel.
In the panel used in the PAGE_START, 2 x FlowLayout (green), one in the LINE_START, the other in the LINE_END. (1)
In the panel in the PAGE_END, 2 x GridLayout (blue), the first a 3 x 3, the other a single column.
If the components at the top (the groups of buttons on the left & right) need to be the exact same size, also use grid layouts for them.
I have JFrame that uses FlowLayout for buttons and BoxLayout for the JFrame and looks like this:
I need it to look like this:
For some reason the JPanel of the buttons (green) takes up too much space, while the labels on the red panel are all on the same row, instead of each on a different row.
My code is as follows:
import javax.swing.*;
import java.awt.*;
public class ButtonsTest extends JFrame {
private JButton button1 = new JButton("Button1");
private JButton button2 = new JButton("Button2");
private JButton button3 = new JButton("Button3");
private JButton button4 = new JButton("Button4");
private JPanel panel = new JPanel(new FlowLayout());
private JPanel otherPanel = new JPanel();
public ButtonsTest() {
setPreferredSize(new Dimension(200, 200));
setMinimumSize(new Dimension(200, 200));
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.setBackground(Color.GREEN);
add(panel);
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
otherPanel.add(new Label("1"));
otherPanel.add(new Label("2"));
otherPanel.add(new Label("3"));
otherPanel.setBackground(Color.RED);
add(otherPanel);
pack();
}
public static void main(String[] args) {
ButtonsTest test = new ButtonsTest();
}
}
What is my mistake?
For some reason the JPanel of the buttons (green) takes up too much space
When using a BoxLayout, the components will grow up to the maximum size when extra space is available. So extra space is allocated to both the red and green panels.
Don't set the layout of the content pane to use a BoxLayout.
while the labels on the red panel are all on the same row, instead of each on a different row.
By default a JPanel uses a Flow layout.
The solution is to use the default BorderLayout of the JFrame.
Then you add the green panel to the frame using:
add(panel, BorderLayout.PAGE_START);
Then for the "otherPanel" you can use the BoxLayout:
otherPanel.setLayout( new BoxLayout(otherPanel, BoxLayout.Y_AXIS) );
Then you add the "otherPanel" to the frame using:
add(otherPanel, BorderLayout.CENTER);
Also, components should be added to the frame BEFORE the frame is visible. So the setVisible(...) statement should be the last statement in the constructor.
I am creating a GUI using GridLayout to arrange multiple panels that are using FlowLayout. I am using pack to determine the size of the frame. If I have only a TextArea then it sizes correctly. If I have only other components it sizes correctly. But if I use both p1 and p2 in the code below the panel with the buttons does not size properly. The test code I am using is below. If I use only p1 or p2 it sizes properly, but not with both: Here is the image I am getting. I don't want all that extra space between the buttons and the textarea.
If I do textarea alone it sizes properly.:
public class GUIPractice extends JFrame
{
//declare GUI objects
JPanel panel;
JPanel p1, p2;
JButton btnAdd, btnShow;
JScrollPane js;
JTextArea taOutput;
//constructor
public GUIPractice()
{
//give frame a title
setTitle("GUI Practice");
panel =new JPanel(new GridLayout(0, 1));
btnAdd = new JButton("Add");
btnShow = new JButton("Show");
taOutput = new JTextArea(10, 20);
js = new JScrollPane(taOutput, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
p1 = new JPanel();
p1.add(btnAdd);
p1.add(btnShow);
p2 = new JPanel();
p2.add(js);
panel.add(p1);
panel.add(p2);
//add the panel to the frame
add(panel);
}
public static void main(String[] args)
{
GUIPractice frame = new GUIPractice();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
It sizes correctly. The GridLayout means that all cells will be the same size. Since the text area is bigger than the buttons, you see extra space in the panel containing the buttons.
I would suggest you just use the default BorderLayout of the frame.
There is no need for your "panel" using the GridLayout.
You just use:
add(p1, BorderLayout.PAGE_START);
add(p2, BorderLayout.CENTER);
Now the p1 and p2 will be the proper height.
Also, there really is no need for "p2". You can just add the scroll pane directly to the frame.
There are two things that I am trying to figure out. First thing, I want to figure out how to make a Jcomponent background transparent. When placing a JPanel into another JPanel that has a color set as the background, the JPanel that is set within the other JPanel has a white background that I can't seem to get rid of. I tried using the firstpanel.setOpache function and repaint but it doesn't do anything.
And second, I noticed that putting a JPanel within another JPanel thats within another JPanel compresses it size. The images below will show what I am trying to describe. I want to know what to do to avoid compressing the JPanel size and still able to put it within two levels of other JPanels . The code below is what I am practicing with.
import javax.swing.*;
import java.awt.*;
public class LearningFrame extends JFrame {
private JLabel userLabel;
private LearningFrame(){
JPanel backGroundPanel = new JPanel();
JPanel mainPanel = new JPanel();
JPanel firstPanel = new JPanel();
JPanel secondPanel = new JPanel();
userLabel = new JLabel("User");
userLabel.setFont(new Font("Arial",1 ,24));
backGroundPanel.setBackground(new Color(247,211,53));
// backGroundPanel.setLayout(new BoxLayout(backGroundPanel,BoxLayout.Y_AXIS));
setContentPane(backGroundPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1200,800);
setLocationRelativeTo(null);
//backGroundPanel.setLayout(null);
mainPanel.setLayout(new GridLayout(1,2));
firstPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
secondPanel.setLayout(new BoxLayout(secondPanel,BoxLayout.Y_AXIS));
// firstPanel.setBackground(new Color(211,43,185));
secondPanel.setBackground(new Color(34,233,44));
JButton button = new JButton("Click");
JButton button2 = new JButton("Click");
JButton button3 = new JButton("Click");
JButton button4 = new JButton("Click");
firstPanel.add(button);
firstPanel.add(button2);
firstPanel.add(userLabel);
secondPanel.add(button3);
secondPanel.add(button4);
mainPanel.add(firstPanel);
mainPanel.add(secondPanel);
backGroundPanel.add(mainPanel);
setVisible(true);
}
public JPanel logPanel() {
JPanel logInPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JTextField userTextField = new JTextField(14);
JTextField passTextField = new JTextField(14);
userLabel = new JLabel("Username: ");
JLabel passLabel = new JLabel("Password: ");
passLabel.setFont(new Font("Arial", Font.BOLD, 24));
userLabel.setFont(new Font("Arial", Font.BOLD, 24));
logInPanel.add(userLabel);
logInPanel.add(userTextField);
logInPanel.add(passLabel);
logInPanel.add(passTextField);
logInPanel.setOpaque(true);
logInPanel.repaint();
return logInPanel;
}
public static void main(String[] args){
LearningFrame x = new LearningFrame();
}
}
Just use
firstPanel.setOpaque(false);
This is will make the background of the component invisible, but you will still be able to see any components that are positioned inside it.
So I'm trying to create a gui, I've tinkered with gui's before in java but I'm still new to them. So my issued here is that my JLabels (butLabel & cbLabel) are filled with buttons and checkboxes. Sadly my JFrame will only show whichever is set to the BorderLayout.CENTER. NORTH & SOUTH don't ever show, even if I only set the butLabel to SOUTH and don't even use the cbLabel. What am I overlooking?? It's much appreciated, thanks!
public class mainWindow
{
JFrame frame = new JFrame("Main Window");
JLabel butLabel = new JLabel();
JLabel cbLabel = new JLabel();
JButton showBut = new JButton("Show");
JButton exitBut = new JButton("Exit");
JButton addBut = new JButton("Add");
JButton remBut = new JButton("Remove");
JCheckBox aCB = new JCheckBox("Airplane");
JCheckBox bCB = new JCheckBox("Boat");
JCheckBox cCB = new JCheckBox("Clock");
public mainWindow()
{
frame.setLayout(new BorderLayout()); //I know this is set by default to BorderLayout but I just did it when I was out of options to try.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(360, 480));
butLabel.setLayout(new GridLayout(1,4));
cbLabel.setLayout(new GridLayout(2, 2));
butLabel.add(showBut);
butLabel.add(exitBut);
butLabel.add(addBut);
butLabel.add(remBut);
cbLabel.add(aCB);
cbLabel.add(bCB);
cbLabel.add(cCB);
frame.add(butLabel, BorderLayout.CENTER);
frame.add(cbLabel, BorderLayout.NORTH);
}
public void setVisible()
{
butLabel.setVisible(true);//Didn't think I needed butLabel.setVisible or the cbLabel.setVisible but
cbLabel.setVisible(true);//again I was trying things that I thought might make sense.
frame.setVisible(true);
}
}
do not use Label for grouping elements, use JPanel instead
I have tried replace all
Label
with
Panel
it works