I am creating a simple Tic Tac Toe Application in Swing using setBounds (null Layout).
My problem is that whichever component i add in the end, is not visible in the frame, or distorts the complete GUI.
My code would better explain this
import java.awt.*;
import javax.swing.*;
class ZeroKata
{
ButtonGroup p1group,p2group;
Font f;
JButton begin,b1,b2,b3,b4,b5,b6,b7,b8,b9;
JCheckBox p1K,p2K,p1Z,p2Z;
JFrame frame;
JLabel player1,player2,p1Name,p2Name,p1Symbol,p2Symbol,status,dummy; // dummy label for my problem
JPanel buttons;
JTextField name1,name2;
private void addComponents(Container parent,JComponent...c)
{
for(JComponent C:c)
parent.add(C);
}
public ZeroKata()
{
frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
frame.setSize(900,650);
frame.setResizable(true);
frame.setVisible(true);
buttons = new JPanel();
buttons.setLayout(new GridLayout(3,3,10,10));
begin = new JButton("START GAME");
b1 = new JButton(" ");
b2 = new JButton(" ");
b3 = new JButton(" ");
b4 = new JButton(" ");
b5 = new JButton(" ");
b6 = new JButton(" ");
b7 = new JButton(" ");
b8 = new JButton(" ");
b9 = new JButton(" ");
p1K = new JCheckBox("X");
p1Z = new JCheckBox("O");
p2K = new JCheckBox("X");
p2Z = new JCheckBox("O");
p1group = new ButtonGroup();
p2group = new ButtonGroup();
p1group.add(p1K);
p1group.add(p1Z);
p2group.add(p2K);
p2group.add(p2Z);
name1 = new JTextField(30);
name2 = new JTextField(30);
f = new Font("Georgia",Font.PLAIN,38);
player1 = new JLabel (" << PLAYER 1 >>");
p1Name = new JLabel ("NAME : ");
p1Symbol = new JLabel ("SYMBOL : ");
player2 = new JLabel ("<< PLAYER 2 >>");
p2Name = new JLabel ("NAME : ");
p2Symbol = new JLabel ("SYMBOL : ");
status = new JLabel ("GAME STATUS -->> ");
dummy = new JLabel (" ");
addComponents(buttons,b1,b2,b3,b4,b5,b6,b7,b8,b9);
player1.setBounds(100,100,100,30);
p1Name.setBounds(120,150,100,30);
p1Symbol.setBounds(120,200,60,30);
player2.setBounds(100,250,100,30);
p2Name.setBounds(120,300,100,30);
p2Symbol.setBounds(120,350,50,30);
name1.setBounds(200,150,150,30);
p1K.setBounds(200,200,50,30);
p1Z.setBounds(250,200,50,30);
name2.setBounds(200,300,150,30);
p2K.setBounds(200,350,50,30);
p2Z.setBounds(250,350,50,30);
buttons.setBounds(500,100,250,250);
dummy.setBounds(20,20,30,30);
begin.setBounds(200,500,150,30);
frame.add(player1);
frame.add(p1Name);
frame.add(p1Symbol);
frame.add(player2);
frame.add(p2Name);
frame.add(p2Symbol);
frame.add(name1);
frame.add(name2);
frame.add(begin);
frame.add(buttons);
frame.add(p1K);
frame.add(p1Z);
frame.add(p2K);
frame.add(p2Z);
/* u need to add a dummy label also to let GUI work correctly, dont know whyx !
frame.add(dummy); */
}
public static void main(String...args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ZeroKata();
}
});
}
}
It is a simple code, I just don't know where I am going wrong .
Thanks in advance !
The default layout manager is a BorderLayout (see JFrame overview), set it to null to allow for absolute positioning:
frame.setLayout(null);
My problem is that whichever component i add in the end, is not
visible in the frame, or distorts the complete GUI. My code would
better explain this
you added JComponents to the already visible JFrame,
move frame.setVisible(true); as last code line, after all JComponents are added
Swing GUI should be started on Initial Threads
Related
I'm hoping this is an easy question. I have a JComboBox with the choices of 0, 1, 2, 3,...10. Depending on what number is selected in the JComboBox, I want my GUI to add a JLabel and a JTextField. So if the number 3 is chosen, the GUI should add 3 JLabels and 3 JTextFields. and so forth.
I'm using an array of JLabels and JTextFields to accomplish this, but I am getting a null pointer exception at runtime, and no labels or fields are being added.
Code:
private void createComponents()
{
//Create Action Listeners
ActionListener comboListener = new ComboListener();
//Create Components of the GUI
parseButton = new JButton("Parse Files");
parseButton.addActionListener(comboListener);
numberLabel = new JLabel("Number of Files to Parse: ");
String[] comboStrings = { "","1", "2","3","4","5","6","7","8","9","10" };
inputBox = new JComboBox(comboStrings);
inputBox.setSelectedIndex(0);
fieldPanel = new JPanel();
fieldPanel.setLayout(new GridLayout(2,10));
centerPanel = new JPanel();
centerPanel.add(numberLabel);
centerPanel.add(inputBox);
totalGUI = new JPanel();
totalGUI.setLayout(new BorderLayout());
totalGUI.add(parseButton, BorderLayout.SOUTH);
totalGUI.add(centerPanel, BorderLayout.CENTER);
add(totalGUI);
}
ActionListener Code:
public void actionPerformed(ActionEvent e)
{
JTextField[] fileField = new JTextField[inputBox.getSelectedIndex()];
JLabel[] fieldLabel = new JLabel[inputBox.getSelectedIndex()];
for(int i = 0; i < fileField.length; i++)
{
fieldLabel[i].setText("File "+i+":"); //NULL POINTER EXCEPTION HERE
fieldPanel.add(fieldLabel[i]); //NULL POINTER EXCEPTION HERE
fieldPanel.add(fileField[i]);
}
centerPanel.add(fieldPanel);
repaint();
revalidate();
}
Thanks to MadProgrammer's comment, this question has been answered.
Editing the loop to:
for(int i = 0; i < fileField.length; i++)
{
fieldLabel[i] = new JLabel();
fileField[i] = new JTextField();
fieldLabel[i].setText("File "+i+":");
fieldPanel.add(fieldLabel[i]);
fieldPanel.add(fileField[i]);
}
resolved the issue.
I am trying to create a simple menu interface with 4 rows of various buttons and labels using GridLayout with FlowLayout inside each grid for organising the elements. However the space for the buttons and labels which should only take 1 line takes up a huge amount of space.
This is what my interface looks like minimized:
This is what it looks like maximized:
I am looking to set the maximum size of the labels panels/grid so that it only takes a small amount of space.
I am trying to make all the elements visible without anything being hidden with as small a window size as possible like this:
This is my code:
public class Window extends JFrame{
public Window() {
super("TastyThai Menu Ordering");
}
public static void main(String[] args) {
Window w = new Window();
w.setSize(500, 500);
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel title = new JLabel("TastyThai Menu Order", SwingConstants.CENTER);
title.setFont(title.getFont().deriveFont(32f));
//generate page title
Container titlePanel = new JPanel(); // used as a container
titlePanel.setBackground(Color.WHITE);
FlowLayout flow = new FlowLayout(); // Create a layout manager
titlePanel.setLayout(flow);// assign flow layout to panel
titlePanel.add(title); // add label to panel
w.getContentPane().add(BorderLayout.NORTH,titlePanel);
//generate row containers
Container r1 = new JPanel(new FlowLayout());
Container r2 = new JPanel(new FlowLayout());
Container r3 = new JPanel(new FlowLayout());
Container r4 = new JPanel(new FlowLayout());
//generate mains radio buttons
Container mains = new JPanel(new GridLayout(7, 0));
mains.setBackground(Color.RED);
JLabel mainsHeader = new JLabel("Mains");
mains.add(mainsHeader);
String[] mainsChoices = {"Vegetarian", "Chicken", "Beef", "Pork", "Duck", "Seafood Mix"};
JRadioButton[] mainsRadioButton = new JRadioButton[6];
ButtonGroup mainsButtons = new ButtonGroup();
for(int i = 0; i < mainsChoices.length; i++) {
mainsRadioButton[i] = new JRadioButton(mainsChoices[i]);
mains.add(mainsRadioButton[i]);
mainsButtons.add(mainsRadioButton[i]);
}
//generate noodles radio buttons
Container noodles = new JPanel(new GridLayout(7, 0));
noodles.setBackground(Color.GREEN);
JLabel noodlesHeader = new JLabel("Noodles");
noodlesHeader.setFont(noodlesHeader.getFont().deriveFont(24f));
noodles.add(noodlesHeader);
String[] noodlesChoices = {"Pad Thai", "Pad Siew", "Ba Mee"};
JRadioButton[] noodlesRadioButton = new JRadioButton[3];
ButtonGroup noodlesButtons = new ButtonGroup();
for(int i = 0; i < noodlesChoices.length; i++) {
noodlesRadioButton[i] = new JRadioButton(noodlesChoices[i]);
noodles.add(noodlesRadioButton[i]);
noodlesButtons.add(noodlesRadioButton[i]);
}
//generate sauces radio buttons
Container sauces = new JPanel(new GridLayout(7, 0));
sauces.setBackground(Color.BLUE);
JLabel saucesHeader = new JLabel("Sauce");
saucesHeader.setFont(saucesHeader.getFont().deriveFont(24f));
sauces.add(saucesHeader);
String[] saucesChoices = {"Soy Sauce", "Tamarind Sauce"};
JRadioButton[] saucesRadioButton = new JRadioButton[2];
ButtonGroup saucesButtons = new ButtonGroup();
for(int i = 0; i < saucesChoices.length; i++) {
saucesRadioButton[i] = new JRadioButton(saucesChoices[i]);
sauces.add(saucesRadioButton[i]);
saucesButtons.add(saucesRadioButton[i]);
}
//generate extras check boxes
Container extras = new JPanel(new GridLayout(7, 0));
extras.setBackground(Color.YELLOW);
JLabel extrasHeader = new JLabel("Extra");
extrasHeader.setFont(extrasHeader.getFont().deriveFont(24f));
extras.add(extrasHeader);
String[] extrasChoices = {"Mushroom", "Egg", "Broccoli", "Beansrpout", "Tofu"};
JCheckBox[] extrasBoxes = new JCheckBox[5];
for(int i = 0; i < extrasChoices.length; i++) {
extrasBoxes[i] = new JCheckBox(extrasChoices[i]);
extras.add(extrasBoxes[i]);
}
JLabel selectionPrice = new JLabel("Selection Price: $ ");
JLabel selectionPriceVal = new JLabel("_______________");
JButton addToOrder = new JButton("Add to Order");
JLabel totalPrice = new JLabel("Total Price: $ ");
JLabel totalPriceVal = new JLabel("_______________");
JButton clearOrder = new JButton("Clear Order");
JRadioButton pickUp = new JRadioButton("Pick Up");
JRadioButton delivery = new JRadioButton("Delivery");
ButtonGroup pickupDelivery = new ButtonGroup();
pickupDelivery.add(pickUp);
pickupDelivery.add(delivery);
JButton completeOrder = new JButton("Complete Order");
Container menuSelection = new JPanel(new GridLayout(4,0));
menuSelection.add(r1);
r1.add(mains);
r1.add(noodles);
r1.add(sauces);
r1.add(extras);
menuSelection.add(r2);
r2.add(selectionPrice);
r2.add(selectionPriceVal);
r2.add(addToOrder);
menuSelection.add(r3);
r3.add(totalPrice);
r3.add(totalPriceVal);
r3.add(clearOrder);
menuSelection.add(r4);
r4.add(pickUp);
r4.add(delivery);
r4.add(completeOrder);
w.getContentPane().add(BorderLayout.CENTER, menuSelection);
w.setVisible(true);
}
}
GridLayout does not support that. All rectangles have the same size.
Take a look at the GridBagLayout, which supports dynamic resizing and much more.
I have a problem.I created a program that will add two random numbers. I'm trying to put a Math.random() in a JTextField but it won't appear. Here's my code by the way:
public class RandomMathGame extends JFrame {
public RandomMathGame(){
super("Random Math Game");
int random2;
JButton lvl1 = new JButton("LEVEL 1");
JButton lvl2 = new JButton("LEVEL 2");
JButton lvl3 = new JButton("LEVEL 3");
JLabel line1 = new JLabel("Line 1: ");
final JTextField jtf1 = new JTextField(10);
JLabel line2 = new JLabel("Line 2: ");
final JTextField jtf2 = new JTextField(10);
JLabel result = new JLabel("Result: ");
final JTextField jtf3 = new JTextField(10);
JButton ans = new JButton("Answer");
JLabel score = new JLabel("Score: ");
JTextField jtf4 = new JTextField(3);
JLabel itm = new JLabel("Number of Items: ");
JTextField items = new JTextField(3);
FlowLayout flo = new FlowLayout();
setLayout(flo);
add(lvl1);
add(lvl2);
add(lvl3);
add(line1);
add(jtf1);
add(line2);
add(jtf2);
add(result);
add(jtf3);
add(ans);
add(score);
add(jtf4);
add(itm);
add(items);
setSize(140,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
lvl1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
int i, j = 10;
int i1 = Integer.valueOf(jtf1.getText());
int i2 = Integer.valueOf(jtf2.getText());
int i3 = i1 + i2;
final int random1 = (int)(Math.random() * 10 + 1);
for (i = 0; i <= j + 1; i++){
try{
jtf1.setText(String.valueOf(random1));
jtf2.setText(String.valueOf(random1));
jtf3.setText(String.valueOf(i3));
}catch(Exception ex){
ex.printStackTrace();
}
}
}
});
}
Never mind the lvl2 and lvl3 because it's the same in lvl1. And also, I want to loop them 10 times. I'm having difficulties on putting up those codes. Can someone help me? Thanks for your help. :)
Updating text fields in a loop won't produce the animated display that you likely want; only the last update will be seen. Instead, use a javax.swing.Timer to periodically update the fields. Related examples may be found here, here and here.
I have one tab that needs to update using one of two methods in it's class while the program is running, for that reason I'm adding components inside the methods, and I cannot get any of them to display. As far as I can tell it's because they are outside the constructor, I used to declare them all inside the methods but moved it to try and fix the problem. Any help would be greatly appreciated.
I apologise it's a bit messy, I've been trying to fix the problem, a bit blindly.
Also the code compiles fine, and println outputs in code display as expected.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package assgui;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.io.*;
/**
*
* #author Hugh
*/
public class ResultPanel extends JPanel {
static String[][] activityString = new String[31][2];
static String[][] foodString = new String[36][2];
String weighstr, foodstr, servstr, kjstr, actstr, hourstr, minstr, metstr;
JLabel uw = new JLabel ("User Weight: ");
JLabel weigh = new JLabel (weighstr);
JLabel kg = new JLabel(" kg");
JLabel sel1 = new JLabel("Food: ");
JLabel sel2 = new JLabel(foodstr);
JLabel sel3 = new JLabel(" - kj ");
JLabel sel4 = new JLabel(kjstr);
JLabel sel5 = new JLabel(" , Servings: ");
JLabel sel6 = new JLabel(servstr);
JLabel sel7 = new JLabel("Activity for comparison: ");
JLabel sel8 = new JLabel(actstr);
JLabel sel9 = new JLabel(" Time required to balance: ");
JLabel sel10 = new JLabel(hourstr);
JLabel sel11 = new JLabel(" hours");
JLabel sel12 = new JLabel(minstr);
JLabel sel13 = new JLabel(" minutes");
JLabel smlspace = new JLabel(" ");
JLabel medspace = new JLabel(" ");
JLabel lrgspace = new JLabel(" ");
JLabel auw = new JLabel("User Weight: ");
JLabel aweigh = new JLabel(weighstr);
JLabel akg = new JLabel(" kg");
JLabel asel1 = new JLabel("Activity: ");
JLabel asel2 = new JLabel(actstr);
JLabel asel3 = new JLabel(" - MET ");
JLabel asel4 = new JLabel(metstr);
JLabel asel5 = new JLabel(" , Duration: ");
JLabel asel6 = new JLabel(hourstr);
JLabel asel7 = new JLabel(" hour ");
JLabel asel8 = new JLabel(minstr);
JLabel asel9 = new JLabel(" minutes ");
JLabel asel10 = new JLabel("Food for comparison: ");
JLabel asel11 = new JLabel(foodstr);
JLabel asel12 = new JLabel(" Servings to balance: ");
JLabel asel13 = new JLabel(servstr);
JLabel asmlspace = new JLabel(" ");
JLabel amedspace = new JLabel(" ");
JLabel alrgspace = new JLabel(" ");
Public ResultPanel() {
setBackground(Color.GREEN);
setPreferredSize(new Dimension(650, 600));
{
public void activityPaint (String[][] actstring, String[][] foodstring, double weight, int activity, int hour, int min, int food, double servings) {
System.out.println("act1");
weighstr = Double.toString(weight);
actstr = activityString[activity][0];
hourstr = Integer.toString(hour);
minstr = Integer.toString(min);
metstr = activityString[activity][1];
foodstr = foodString[food][0];
servstr = Double.toString(servings);
add(lrgspace);
add(uw);
add(weigh);
add(kg);
add(medspace);
add(sel1);
add(sel2);
add(sel3);
add(sel4);
add(sel5);
add(sel6);
add(sel7);
add(sel8);
add(sel9);
add(sel10);
add(sel11);
add(sel12);
add(sel13);
}
public void foodPaint(String[][] foodstring, String[][] actstring, double weight, int food, int servings, int activity, int hour, int min) {
System.out.println("food1");
weighstr = Double.toString(weight);
foodstr = foodString[food][0];
servstr = Integer.toString(servings);
kjstr = foodString[food][1];
actstr = activityString[activity][0];
hourstr = Integer.toString(hour);
minstr = Integer.toString(min);
add(lrgspace);
add(uw);
add(weigh);
add(kg);
add(medspace);
add(sel1);
add(sel2);
add(sel3);
add(sel4);
add(sel5);
add(sel6);
add(sel7);
add(sel8);
add(sel9);
add(sel10);
add(sel11);
add(sel12);
add(sel13);
}
}
Does your main method (or whatever method) that creates this JPanel also call the activityPaint(...) and foodPaint(...) methods? If those methods are not called then they will never be added to the panel it seems. If you want everything to be added when you create the JPanel then you must have your constructor call activityPaint() and foodPaint().
If the values of your JLables can't be set until something else occurs (like user input), then you can add the components when the JPanel is created and then later call the setText(...) method. Just be sure if you do that to also set the size since changing the text will effect that. I prefer to use nameofjpanel.setSize(nameofjpanel.getPreferredSize()).
Hope this helps you and I didn't completely miss what you're going for here.
Basically I am trying to attach two panels onto my frame,
my frame uses BorderLayout and the two panels will be placed North and south.
I am done with the top panel but for the bottom one I cannot get it right.
I used GridLayout for the bottom one and it's supposed to look like this.
http://i47.tinypic.com/wa0lsz.png
So here is the code for the gridlayout
public class WeaponComp extends JPanel{
protected JPanel first = new JPanel();
public WeaponComp(){
setLayout(new GridBagLayout());
setPreferredSize(new Dimension(800,550));
GridBagConstraints c = new GridBagConstraints();
JLabel ntg = new JLabel("");
JLabel oldweap = new JLabel("OLD WEAPON");
JLabel newweap = new JLabel("NEW WEAPON");
JLabel onetwohand = new JLabel ("1H / 2H");
JLabel offhand = new JLabel ("Off Hand");
JLabel dps = new JLabel ("DPS :");
JLabel str = new JLabel ("Str :");
JLabel dex = new JLabel ("Dex :");
JLabel vit = new JLabel ("Vit :");
JLabel intel = new JLabel ("Int :");
JLabel manareg = new JLabel ("Mana Regen :");
JLabel aspd = new JLabel ("Attack Speed:");
JLabel critch = new JLabel ("Crit chance:");
JLabel critdmg = new JLabel ("Crit damage:");
JTextField dpstf = new JTextField(12);
JTextField strtf = new JTextField(5);
JTextField dextf = new JTextField(5);
JTextField vittf = new JTextField(5);
JTextField inteltf = new JTextField(5);
JTextField manaregtf = new JTextField(3);
JTextField aspdtf = new JTextField(3);
JTextField critchtf = new JTextField(3);
JTextField critdmgtf = new JTextField(3);
JTextField offdpstf = new JTextField(12);
JTextField offstrtf = new JTextField(5);
JTextField offdextf = new JTextField(5);
JTextField offvittf = new JTextField(5);
JTextField offinteltf = new JTextField(5);
JTextField offmanaregtf = new JTextField(3);
JTextField offaspdtf = new JTextField(3);
JTextField offcritchtf = new JTextField(3);
JTextField offcritdmgtf = new JTextField(3);
first.setLayout(new GridLayout(3,4));
first.setPreferredSize(new Dimension(750,150));
first.add(oldweap); first.add(ntg); first.add(newweap); first.add(ntg);
first.add(onetwohand); first.add(ntg); first.add(offhand); first.add(ntg);
first.add(dps); first.add(dpstf); first.add(dps); first.add(offdpstf);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0; c.gridy = 0;
add (first,c);
}
}
Here is the current result of my program
http://i50.tinypic.com/107p9uu.png
Thank you in advance for your time and answers
PS : and in case you're wondering, yes, it has something to do with diablo 3
But I am not that ambitious, this is for learning purpose and won't have many functionality.
GridLayout is a poor choice, because all cells automatically have the same size. I suggest using MigLayout instead: http://miglayout.com
The layout code would look like this:
first.setLayout(new MigLayout("wrap 2, fill"));
first.add(oldweap);
first.add(newweap);
first.add(onetwohand);
first.add(offhand);
first.add(dps);
first.add(dpstf);
first.add(dps);
first.add(offdpstf);
You might use GroupLayout1 or a nested layout2 for the bottom panels.
See How to Use GroupLayout for details. E.G.
E.G.