I am trying to generate a user interface and while my creation worked fine as a JFrame, it is not displaying my line based graphics in it's JPanel incarnation. If someone could point out what I am doing wrong here it would be very appreciated.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.*;
public class Bowling_GUI_v9 extends JPanel {
public JLabel[] label1;
public JTextField[] text1;
public JComboBox[] combo1;
public JPanel displayPanel = new JPanel();
private int[] horz_coords = new int[] {8,60,580, 53,140,420,100,60,580,245,140,580,280,140,580,315,140,580,350,60,580,400,60,580};
private int[] vert_coords = new int[] {60,140,220,260,300,340,380,420,460,500,540,580};
public Bowling_GUI_v9() {
displayPanel.setLayout(null);
//displayPanel.setSize(800, 600);
displayPanel.setSize(new Dimension(800,600));
createUserInterface();
}
public void drawLines(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
//super.paintComponent(g);
int a = vert_coords.length;
for(int i=0; i<a; i++){
g2d.drawLine(1, vert_coords[i], 400, vert_coords[i]);
}
a = horz_coords.length;
for(int i=0; i<a; i=i+3){
g2d.drawLine(horz_coords[i],horz_coords[i+1],horz_coords[i],horz_coords[i+2]);
}
}
public void paint(Graphics g) {
//super.paint(g);
paint(g);
drawLines(g);
}
private void createUserInterface(){
//Container contentPane = getContentPane();
//contentPane.setLayout(null);
label1 = new JLabel[51];
text1 = new JTextField[17];
combo1 = new JComboBox[5];
int text1counter = 0;
int label1counter = 0;
int combo1counter = 0;
int popCounter = 0;
int counter = 2;
int h_pos =0;
int v_pos =1;
int flag = 0;
int wide = 30;
String[] populate = new String[] {"Team Name", "Ave", "HCP", "Name", "Game 1", "Game 2", "Game 3", "Total", "Won", "Scratch Total", "Lost", "Team HCP", "", "HCP Total Pin", "", "WINS"};
int[] identifier = new int[] {1,2,2,1,1,1,1,1,1,1,2,2,4,3,3,3,2,8,1,2,1,2,2,2,2,9};
label1[label1counter] = new JLabel();
label1[label1counter].setText(populate[popCounter]);
label1[label1counter].setBounds(8,60,80,10);
displayPanel.add(label1[label1counter]);
label1counter++;
popCounter++;
text1[text1counter] = new JTextField();
text1[text1counter].setText("Enter Team Name Here");
text1[text1counter].setBounds(101,60,200,20);
displayPanel.add(text1[text1counter]);
text1counter++;
text1[text1counter] = new JTextField();
text1[text1counter].setText("Lane");
text1[text1counter].setBounds(351,60,40,20);
displayPanel.add(text1[text1counter]);
text1counter++;
for(int a=0; a<10; a++){
for(int b=0; b<7; b++){
counter++;
switch(identifier[counter]){
case 1:
if (b == 2){ wide = 90; }
else if (b == 6 && a == 0){ wide = 55; }
else { wide = 30; }
label1[label1counter] = new JLabel();
label1[label1counter].setText(populate[popCounter]);
label1[label1counter].setBounds(horz_coords[h_pos],vert_coords[v_pos]- 20,wide,20);
displayPanel.add(label1[label1counter]);
h_pos = h_pos + 3;
label1counter++;
popCounter++;
break;
case 2:
label1[label1counter] = new JLabel();
label1[label1counter].setText("0");
label1[label1counter].setBounds(horz_coords[h_pos],vert_coords[v_pos] -20, 30, 20);
displayPanel.add(label1[label1counter]);
h_pos = h_pos + 3;
label1counter++;
break;
case 3:
text1[text1counter] = new JTextField();
text1[text1counter].setText("0");
text1[text1counter].setBounds(horz_coords[h_pos],vert_coords[v_pos] - 20,30,20);
displayPanel.add(text1[text1counter]);
text1counter++;
h_pos = h_pos + 3;
break;
case 4:
combo1[combo1counter] = new JComboBox();
combo1[combo1counter].setBounds(horz_coords[h_pos],vert_coords[v_pos] - 20,30,20);
displayPanel.add(combo1[combo1counter]);
combo1counter++;
h_pos = h_pos + 3;
break;
case 8:
b--;
flag++;
counter = 9;
break;
case 9:
b--;
flag++;
counter = 17;
break;
}
}
v_pos++;
h_pos=0;
if(flag == 4){
flag = 1;
counter ++;
}
}
label1[38].setText("");
label1[45].setText("");
}
}
Don't override paint(). Custom painting is done by overriding paintComponent(...) and then you invoke super.paintComponent(...) as the first statement.
You need to override getPreferredSize() to return the size of your panel so layout managers can do their job.
Don't use a null layout and don't use setSize(). Use an appropriate layout manager and the layout manager will determine the size/location of any component you add to the panel.
You don't show where you actually add the panel to a frame.
Read the section from the Swing tutorial on Custom Painting for more information and working examples. In other words, start with a small example and make sure you understand the entire process before doing complex painting.
The tutorial also has a section on Layout Managers that you should be reading to you use them properly.
Related
New programmer here, I have been working for a few days on this bit of code that is meant to create a UI where I input a basement's perimeter length (textfield integer), if a new pump is needed (combobox string), if there is an outlet nearby (combobox string), and how many hours It will take to prepare a site (textfield integer), and I calculate my costs to complete a job. I was able to set up a UI where I can enter the inputs and press a button to calculate but I'm having trouble connecting the button I made to the formula I made to generate a price. Here is my code:
package packagepackage;
import packagepackage.HintTextFieldUI;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CP_GUI implements ActionListener {
String[] sumpo = {"New sump pump","Existing sump pump"};
String[] electo = {"There is an outlet within 6 feet of sump pump","There is no outlet nearby, or I do not need a new one"};
Integer estimatex = 0;
String esto = String.valueOf(estimatex);
public volatile String estimatoof = "Estimated Cost: ${}".format(esto);
private JComboBox sump = new JComboBox(sumpo);
private JComboBox elec = new JComboBox(electo);
private JTextField linear = new JTextField();
private JTextField prep = new JTextField();
private JLabel title = new JLabel("Drain Tile Calculator");
private JButton calculate = new JButton("Calculate!");
public JLabel estimate = new JLabel(estimatoof);
private JFrame frame = new JFrame();
private JPanel panel = new JPanel();
public CP_GUI() {
linear.addActionListener(this);
calculate.addActionListener(this);
elec.addActionListener(this);
sump.addActionListener(this);
prep.addActionListener(this);
// the panel with the button and text
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(400, 400, 100, 100));
panel.setLayout(new GridLayout(0, 1));
panel.add(linear);
panel.add(sump);
panel.add(elec);
panel.add(prep);
frame.add(panel, BorderLayout.CENTER);
panel.add(title);
calculate.addActionListener(this);
panel.add(calculate);
// set up the frame and display it
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Drain Tile Calculator");
frame.pack();
frame.setVisible(true);
linear.setUI(new HintTextFieldUI("Perimeter length", true));
prep.setUI(new HintTextFieldUI("Hours of preptime", true));}
// create one Frame
public static void main(String[] args) {
new CP_GUI();
}
#Override
public void actionPerformed(ActionEvent e){
// TODO Auto-generated method stub
if(e.getSource()==linear) {String input = linear.getText();
Integer pars = Integer.parseInt(input);
Integer distVar = pars *= 13;
estimatex += distVar;
} else if (e.getSource()==sump) {String inputa = sump.getToolTipText();
int sumpa = 0;
if(inputa == "New sump pump" | inputa == "yes") {
sumpa += 260;}
estimatex += sumpa;
} else if (e.getSource()==elec) {String inputb =elec.getToolTipText();
int eleca = 0;
if("There is an outlet within 6 feet of the sump pump".equals(inputb)) {
eleca += 1;
}
eleca *= 280;
estimatex += eleca;
}
else if (e.getSource()==prep) {String inputc = prep.getText();
int parsa = Integer.parseInt(inputc);
int prepCost = parsa += 1;
prepCost *= 110;
estimatex += prepCost;
} else if (e.getSource()==linear) {
String disto = linear.getText();
int di = Integer.parseInt(disto);
di *= 13;
String pumpo = (String)sump.getSelectedItem();
int sumpo = 0;
if ("New sump pump".equals(pumpo)) {
sumpo += 260;
}
String ele = (String)elec.getSelectedItem();
int elc = Integer.parseInt(ele);
elc *= 280;
String clea = prep.getText();
int cla = Integer.parseInt(clea);
cla += 1;
cla *= 110;
int cali = 0;
cali += di;
cali += sumpo;
cali += elc;
cali += cla;
estimatex = cali;
}
}
}
Edit: Made the suggested edits made so far and now the UI opens and works, the only issue is that the estimated price does not show up. Am I connecting the action listener correctly?
Your "primary" problem is right here...
String disto = String.valueOf(linear);
where linear is a JTextField, so the above call will generate something like...
javax.swing.JTextField[,0,0,0x0,invalid,layout=javax.swing.plaf.basic.BasicTextUI$UpdateHandler,alignmentX=0.0,alignmentY=0.0,border=com.apple.laf.AquaTextFieldBorder#4e323305,flags=288,maximumSize=,minimumSize=,preferredSize=,caretColor=javax.swing.plaf.ColorUIResource[r=0,g=0,b=0],disabledTextColor=javax.swing.plaf.ColorUIResource[r=128,g=128,b=128],editable=true,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],selectedTextColor=com.apple.laf.AquaImageFactory$SystemColorProxy[r=0,g=0,b=0],selectionColor=com.apple.laf.AquaImageFactory$SystemColorProxy[r=165,g=205,b=255],columns=0,columnWidth=0,command=,horizontalAlignment=LEADING]
which is obviously not what you're looking for.
You should probably be just doing something like...
String disto = linear.getText();
pumpo == "New sump pump" is also not how you compare a String in Java, you should be using "New sump pump".equals(pumpo) ... but I suspect you're going to have the same issues as mentioned above.
I really recommend you take the time to read through Creating a GUI With Swing as well as taking the time to come to grips with the core basics of the language
Hello I'm trying to add dice images on the side of my craps program. However I keep running into the issue of all my JLabels, Jtextfeilds and JButtons disappearing.
Dice images:
Craps.java:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Craps extends JApplet implements ActionListener{
private static final long serialVersionUID = 1L;
//constant variables for the status of the game
final int WON = 0,LOST =1, CONTINUE = 2;
//other variables used in the program
boolean firstRoll = true;
int sumOfDice = 0;
int myPoint = 0;
int gameStatus = CONTINUE;
int numberHouseWins = 0;
int numberPlayerWins = 0;
String divider = "*******";
int die1,die2,workSum;
//die faces
Image dieFace1,dieFace2,dieFace3,dieFace4,dieFace5,dieFace6;
//graphical user interface components
JLabel dieLabel1, dieLabel2, sumLabel, rollLabel, pointLabel;
JLabel lblHouseWins, lblPlayerWins;
JLabel leftDivider, rightDivider;
JTextField firstDie, secondDie, sum, point;
JTextField txtHouseWins, txtPlayerWins;
JButton roll;
public void paint(Graphics g){
if(die1 == 1){
repaint();
g.drawImage(dieFace1, 0, 0, this);
}
else if( die1 == 2){
repaint();
g.drawImage(dieFace2, 0, 0, this);
}
else if( die1 == 3){
repaint();
g.drawImage(dieFace3, 0, 0, this);
}
else if( die1 == 4){
repaint();
g.drawImage(dieFace4, 0, 0, this);
}
else if( die1 == 5){
repaint();
g.drawImage(dieFace5, 0, 0, this);
}
else if( die1 == 6){
repaint();
g.drawImage(dieFace6, 0, 0, this);
}
if ( die2==1){
repaint();
g.drawImage(dieFace1, 0, 30, this);
}else if( die2 == 2){
repaint();
g.drawImage(dieFace2, 0, 30, this);
}
else if( die2 == 3){
repaint();
g.drawImage(dieFace3, 0, 30, this);
}
else if( die2 == 4){
repaint();
g.drawImage(dieFace4, 0, 30, this);
}
else if( die2 == 5){
repaint();
g.drawImage(dieFace5, 0, 30, this);
}
else if( die2 == 6){
repaint();
g.drawImage(dieFace6, 0, 30, this);
}
}
public void init()
{
//setup graphical user interface components
JPanel display = new JPanel();
display.setLayout(new GridLayout(8, 2, 10, 10));
//creating JLabel Die1 to the display
dieLabel1 = new JLabel("Die 1:",SwingConstants.RIGHT);
display.add(dieLabel1);
firstDie = new JTextField(3);
firstDie.setEditable(false);
display.add(firstDie);
//creating JLabel Die2 to the Display
dieLabel2 = new JLabel("Die 2:",SwingConstants.RIGHT);
display.add(dieLabel2);
secondDie = new JTextField(3);
secondDie.setEditable(false);
display.add(secondDie);
//creating JLabel sum die to the display
sumLabel = new JLabel("Their sum is:",SwingConstants.RIGHT);
display.add(sumLabel);
sum = new JTextField(4);
sum.setEditable(false);
display.add(sum);
//creating JLabel rollLabel to the display
rollLabel= new JLabel("Roll Again",SwingConstants.RIGHT);
display.add(rollLabel);
roll = new JButton("Roll Dice");
roll.addActionListener(this);
display.add(roll);
//creating JLabel pointLabel to the display
pointLabel = new JLabel("Point is:",SwingConstants.RIGHT);
display.add(pointLabel);
point = new JTextField(3);
point.setEditable(false);
display.add(point);
//creating JLabel leftDivider and rightDivider to the display
leftDivider = new JLabel(divider,SwingConstants.RIGHT);
display.add(leftDivider);
rightDivider = new JLabel(divider,SwingConstants.LEFT);
display.add(rightDivider);
//creating JLabel lblPlayerWins and JTextField txtPlayerWins to the display
lblPlayerWins = new JLabel("Player wins:",SwingConstants.RIGHT);
display.add(lblPlayerWins);
txtPlayerWins = new JTextField(4);
txtPlayerWins.setEnabled(false);
display.add(txtPlayerWins);
//creating JLabel lblHouseWins and JTextField txtHouseWins to the display
lblHouseWins = new JLabel("House wins:",SwingConstants.RIGHT);
display.add(lblHouseWins);
txtHouseWins = new JTextField(4);
txtHouseWins.setEnabled(false);
display.add(txtHouseWins);
setContentPane(display);
dieFace1=getImage(getDocumentBase(),"die1.jpg");
dieFace2=getImage(getDocumentBase(), "die2.jpg");
dieFace3=getImage(getDocumentBase(),"die3.jpg");
dieFace4=getImage(getDocumentBase(), "die4.jpg");
dieFace5=getImage(getDocumentBase(),"die5.jpg");
dieFace6=getImage(getDocumentBase(), "die6.jpg");
}
public void actionPerformed(ActionEvent e){
play();
}
public void play(){
if(firstRoll){
sumOfDice = rollDice();
switch (sumOfDice) {
//player wins on first roll
case 7: case 11:
gameStatus = WON;
point.setText("");
break;
//house wins player loses on first roll
case 2:case 3: case 12:
gameStatus = LOST;
point.setText("");
break;
default:
gameStatus = CONTINUE;
myPoint = sumOfDice;
point.setText(Integer.toString(myPoint));
firstRoll = false;
break;
}
}
else{
sumOfDice = rollDice();
if(sumOfDice==myPoint)
gameStatus = WON;
else
if(sumOfDice == 7)
gameStatus = LOST;
}
if(gameStatus == CONTINUE)
showStatus("Roll again");
else{
if(gameStatus == WON){
showStatus("Player wins."+"Click Roll Dice to play again");
numberPlayerWins++;
txtPlayerWins.setText(Integer.toString(numberPlayerWins));
}
else{
showStatus("House wins."+"Click Roll Dice to play again");
numberHouseWins++;
txtHouseWins.setText(Integer.toString(numberHouseWins));
}
firstRoll = true;
}
}
public int rollDice(){
die1 = 1+ (int)(Math.random()*6);
die2 = 1+ (int)(Math.random()*6);
workSum = die1 +die2;
firstDie.setText(Integer.toString(die1));
secondDie.setText(Integer.toString(die2));
sum.setText(Integer.toString(workSum));
return workSum;
}
}
I've edited your code and included comments to explain what I did and the reasoning for it. It was much easier to explain the code in the code, rather than write up a huge explanation and reference different pieces of the code.
I removed your paint method, as it was not needed and endlessly looped between paint and repaint calls.
Note: Sorry about the spacing between types and variables, my IDE is set up that way.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
public class Craps extends JApplet implements ActionListener {
private static final long serialVersionUID = 1L;
// constant variables for the status of the game
final int WON = 0, LOST = 1, CONTINUE = 2;
// other variables used in the program
boolean firstRoll = true;
int sumOfDice = 0;
int myPoint = 0;
int gameStatus = CONTINUE;
int numberHouseWins = 0;
int numberPlayerWins = 0;
String divider = "*******";
int die1, die2, workSum;
// graphical user interface components
JLabel dieLabel1, dieLabel2, sumLabel, rollLabel, pointLabel;
JLabel lblHouseWins, lblPlayerWins;
JLabel leftDivider, rightDivider;
JTextField firstDie, secondDie, sum, point;
JTextField txtHouseWins, txtPlayerWins;
JButton roll;
// added these two JLabels to display dice ImageIcons
JLabel dieImg1, dieImg2;
// die faces, changed to an array of ImageIcons
ImageIcon dieFaces[];
// moved these into their own function, init is pretty stuffed
public void createImageIcons() {
// create an array of ImageIcons, easier to set JLabels image using
// index rather than 6 if-else-if statements
dieFaces = new ImageIcon[6];
dieFaces[0] = new ImageIcon(getImage(getDocumentBase(), "die1.jpg"));
dieFaces[1] = new ImageIcon(getImage(getDocumentBase(), "die2.jpg"));
dieFaces[2] = new ImageIcon(getImage(getDocumentBase(), "die3.jpg"));
dieFaces[3] = new ImageIcon(getImage(getDocumentBase(), "die4.jpg"));
dieFaces[4] = new ImageIcon(getImage(getDocumentBase(), "die5.jpg"));
dieFaces[5] = new ImageIcon(getImage(getDocumentBase(), "die6.jpg"));
}
public JPanel createTxtImgContainer(JTextField txt, JLabel img) {
JPanel container = new JPanel();
container.setLayout(new GridLayout(1, 2, 10, 10));
txt.setEditable(false);
container.add(txt);
container.add(img);
return container;
}
#Override
public void init() {
// don't know if this is necessary, but it can't hurt
super.init();
// let's load the images first, no need to run a bunch of code and then
// error out on image loading also we can use the ImageIcons after this
createImageIcons();
// setup graphical user interface components
JPanel display = new JPanel();
display.setLayout(new GridLayout(8, 2, 10, 20));
// creating JLabel Die1 to the display
dieLabel1 = new JLabel("Die 1:", SwingConstants.RIGHT);
display.add(dieLabel1);
firstDie = new JTextField(3);
// created dieImg1 here also set the initial ImageIcon to "die6.jpg"
dieImg1 = new JLabel(dieFaces[5]);
// create a JPanel to house the JTextField and JLabel, and it to display
display.add(createTxtImgContainer(firstDie, dieImg1));
// creating JLabel Die2 to the Display
dieLabel2 = new JLabel("Die 2:", SwingConstants.RIGHT);
display.add(dieLabel2);
secondDie = new JTextField(3);
// created dieImg2 here also set the initial image to "die6.jpg"
dieImg2 = new JLabel(dieFaces[5]);
// create a JPanel to house the JTextField and JLabel, and it to display
display.add(createTxtImgContainer(secondDie, dieImg2));
// creating JLabel sum die to the display
sumLabel = new JLabel("Their sum is:", SwingConstants.RIGHT);
display.add(sumLabel);
sum = new JTextField(4);
sum.setEditable(false);
display.add(sum);
// creating JLabel rollLabel to the display
rollLabel = new JLabel("Roll Again", SwingConstants.RIGHT);
display.add(rollLabel);
roll = new JButton("Roll Dice");
roll.addActionListener(this);
display.add(roll);
// creating JLabel pointLabel to the display
pointLabel = new JLabel("Point is:", SwingConstants.RIGHT);
display.add(pointLabel);
point = new JTextField(3);
point.setEditable(false);
display.add(point);
// creating JLabel leftDivider and rightDivider to the display
leftDivider = new JLabel(divider, SwingConstants.RIGHT);
display.add(leftDivider);
rightDivider = new JLabel(divider, SwingConstants.LEFT);
display.add(rightDivider);
// creating JLabel lblPlayerWins and JTextField txtPlayerWins to the
// display
lblPlayerWins = new JLabel("Player wins:", SwingConstants.RIGHT);
display.add(lblPlayerWins);
txtPlayerWins = new JTextField(4);
txtPlayerWins.setEnabled(false);
display.add(txtPlayerWins);
// creating JLabel lblHouseWins and JTextField txtHouseWins to the
// display
lblHouseWins = new JLabel("House wins:", SwingConstants.RIGHT);
display.add(lblHouseWins);
txtHouseWins = new JTextField(4);
txtHouseWins.setEnabled(false);
display.add(txtHouseWins);
setContentPane(display);
}
#Override
public void actionPerformed(ActionEvent e) {
play();
}
public void play() {
if (firstRoll) {
sumOfDice = rollDice();
switch(sumOfDice) {
// player wins on first roll
case 7 :
case 11 :
gameStatus = WON;
point.setText("");
break;
// house wins player loses on first roll
case 2 :
case 3 :
case 12 :
gameStatus = LOST;
point.setText("");
break;
default:
gameStatus = CONTINUE;
myPoint = sumOfDice;
point.setText(Integer.toString(myPoint));
firstRoll = false;
break;
}
}
else {
sumOfDice = rollDice();
if (sumOfDice == myPoint) {
gameStatus = WON;
} else if (sumOfDice == 7) {
gameStatus = LOST;
}
}
if (gameStatus == CONTINUE) {
showStatus("Roll again");
} else {
if (gameStatus == WON) {
showStatus("Player wins." + "Click Roll Dice to play again");
numberPlayerWins++;
txtPlayerWins.setText(Integer.toString(numberPlayerWins));
} else {
showStatus("House wins." + "Click Roll Dice to play again");
numberHouseWins++;
txtHouseWins.setText(Integer.toString(numberHouseWins));
}
firstRoll = true;
}
}
public int rollDice() {
die1 = 1 + (int) (Math.random() * 6);
die2 = 1 + (int) (Math.random() * 6);
workSum = die1 + die2;
firstDie.setText(Integer.toString(die1));
secondDie.setText(Integer.toString(die2));
sum.setText(Integer.toString(workSum));
// set dieImgs to die values - 1, because the array starts at 0 not 1
dieImg1.setIcon(dieFaces[die1 - 1]);
dieImg2.setIcon(dieFaces[die2 - 1]);
return workSum;
}
}
Here's a screenshot of the applet running:
I am adding JLabel objects to a JPanel. Each label has a different tool tip text that I use to identify each label afterwards, the problem is that the tool tip is always showing on hover and I need it to always be hidden.
Each label has a different image icon that's why I can't use the label text.
I can't find any documentation on the label API for some function like .hidetooltip.
Edit
Each of many JLabel objects on a GridLayout holds an Image. I need to know the line and column of each image.
To hide the tool tip text to null
myComponent.setToolTipText(null);
This is described in the API for this method: "param - the string to display; if the text is null, the tool tip is turned off for this component"
EDIT: In response to your actual issue that you describe in one of your comments, there are a variety of ways association information with a JLabel. You could a) extend the class and keep instance variables defining the grid values b) use a Map key'd with the JLabel and value'd with the row/col c) use the Name of the JLabel
Each of many JLabel objects on a GridLayout holds an Image. I need to know the line and column of each image.
One way to achieve this is to store a BufferedImage[][] to check images against. E.G.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
public final class ImageArray {
int r = 8;
int c = 8;
// The images in the chess board, used to check which
// image was chosen for this place on the board.
final private BufferedImage[][] chessBoardImages = new BufferedImage[r][c];
private final int rowSprite = 2;
private final int colSprite = 6;
// Holds the tile sheet images
private final BufferedImage[] chessPieceImages =
new BufferedImage[colSprite * rowSprite];
private JComponent ui = null;
private final BufferedImage chessSpriteSheet;
ImageArray(BufferedImage chessSpriteSheet) {
this.chessSpriteSheet = chessSpriteSheet;
initUI();
}
private int getImageIndex(Image img) {
for (int i = 0; i < chessPieceImages.length; i++) {
if (chessPieceImages[i].equals(img)) {
return i;
}
}
return -1;
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
int w = chessSpriteSheet.getWidth();
int h = chessSpriteSheet.getHeight() / rowSprite;
int wStep = chessSpriteSheet.getWidth() / colSprite;
int hStep = chessSpriteSheet.getHeight() / rowSprite;
for (int x = 0; x < colSprite; x++) {
for (int y = 0; y < rowSprite; y++) {
chessPieceImages[x + (y * colSprite)]
= chessSpriteSheet.getSubimage(
x * wStep, y * hStep, wStep, h);
}
}
JPanel grid = new JPanel(new GridLayout(r, c));
ui.add(grid, BorderLayout.CENTER);
Random rand = new Random();
for (int x = 0; x < r; x++) {
boolean oddRow = x % 2 == 0;
for (int y = 0; y < c; y++) {
boolean oddCol = y % 2 == 0;
BufferedImage img = chessPieceImages[
rand.nextInt(colSprite * rowSprite)];
JLabel l = new JLabel(new ImageIcon(img));
chessBoardImages[x][y] = img;
l.setOpaque(true);
if ((oddRow && oddCol) || (!oddRow && !oddCol)) {
l.setBackground(Color.WHITE);
} else {
l.setBackground(Color.LIGHT_GRAY);
}
grid.add(l);
}
}
JLabel htmlLabel = new JLabel(getHtml());
htmlLabel.setHorizontalTextPosition(SwingConstants.CENTER);
htmlLabel.setVerticalTextPosition(SwingConstants.BOTTOM);
ui.add(htmlLabel,
BorderLayout.LINE_END);
}
private String getHtml() {
String style = "<style type='text/css'>"
+ "body {"
+ "font-size: 36px;"
+ "}"
+ ".white {"
+ "background-color: #FFFFFF;"
+ "}"
+ ".black {"
+ "background-color: #BBBBBB;"
+ "}"
+ "</style>";
String pre = "<html><head>%1s</head><body><table border=1 cellspacing=0>";
StringBuilder sb = new StringBuilder(String.format(pre, style));
for (int y = 0; y < r; y++) {
sb.append("<tr>");
for (int x = 0; x < c; x++) {
Image img = chessBoardImages[y][x];
final int index = getImageIndex(img);
// hack to convert index to unicode codepoint..
int unicodeOffset = ((index/colSprite)*colSprite)==0 ? colSprite : -colSprite;
int unicodeIndexOffset;
switch (index) {
case 3:
unicodeIndexOffset = 4;
break;
case 4:
unicodeIndexOffset = 3;
break;
case 9:
unicodeIndexOffset = 10;
break;
case 10:
unicodeIndexOffset = 9;
break;
default:
unicodeIndexOffset = index;
}
int unicode = 9812 + unicodeIndexOffset + unicodeOffset;
// end: hack to convert index to unicode index..
String cssClass;
boolean oddCol = x%2==1;
boolean oddRow = y%2==1;
if ((oddRow && oddCol) || (!oddRow && !oddCol)) {
cssClass = "white";
} else {
cssClass = "black";
}
sb.append(String.format(
"<td class='%1s'>&#%2s;</td>", cssClass, unicode));
}
sb.append("</tr>");
}
sb.append("</table></body></html>");
return sb.toString();
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) throws Exception {
String urlString = "http://i.stack.imgur.com/memI0.png";
final BufferedImage img = ImageIO.read(new URL(urlString));
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ImageArray o = new ImageArray(img);
JFrame f = new JFrame("Image Array");
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 should consider storing the information elsewhere. One way would be to make a class deriving from JLabel with the purpose of storing the line and column information. Then use instances of this subclass rather than use JLabel instances. They will render as a regular JLabel would, but you can retrieve the line and column information in a way that does not pop up that information in a tooltip.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
There is something odd going on in my code. I'm making a Connect Four game, but making it to where you can have up to eight teams with four players each. There are three separate GUI class files, each with their own layout, etc. But I cannot pass a variable from the SettingsGUI file to the TeamSettingsGUI file, despite my best efforts. What is weird, is how I can initialize the variable, or have the getXXX method return a certain number and it works fine. But I am unable to pass the value of the variable, for some reason.
The two variables I am dealing with right now are numTeams and playersPerTeam. IF I could understand how to get one of them to work, I think I could get the rest of them to work as well. I'm sure it's something simple, but I'm stumped.
Here's the int ital GUI, SettingsGUI:
package connectfouradvanced;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SettingsGUI extends JPanel implements ActionListener {
JLabel saveLabel = new JLabel("Saved. Please exit this GUI.");
JButton save = new JButton("Save");
JLabel numTeamsLabel = new JLabel("Chose the number of teams.");
Choice numTeamsChoice = new Choice();
JLabel boardDimensionsLabel = new JLabel("Chose the board dimensions.");
Choice boardDimensionsChoice = new Choice();
JLabel numPlayersPerTeamLabel = new JLabel("Chose the number of players per team.");
Choice numPlayersPerTeamChoice = new Choice();
JLabel powerupsLabel = new JLabel("Powerups On/Off?");
JCheckBox powerups = new JCheckBox();
JLabel standardLabel = new JLabel("Standard Setup?");
JCheckBox standardSettings = new JCheckBox();
int numTeams, boardRows, boardColumns, playersPerTeam;
//if you were to put numTeams = 4, then 4 would be passed to TeamSettingsGUI
boolean powerupsSelected = false, standardSelected;
public SettingsGUI() {
add(saveLabel);
saveLabel.setVisible(false);
add(save);
save.addActionListener(this);
add(numTeamsLabel);
add(numTeamsChoice);
numTeamsChoice.add("2");
numTeamsChoice.add("3");
numTeamsChoice.add("4");
numTeamsChoice.add("5");
numTeamsChoice.add("6");
numTeamsChoice.add("7");
numTeamsChoice.add("8");
add(boardDimensionsLabel);
add(boardDimensionsChoice);
boardDimensionsChoice.add("7x6");
boardDimensionsChoice.add("14x12");
boardDimensionsChoice.add("21x18");
boardDimensionsChoice.add("28x24");
boardDimensionsChoice.add("35x30");
boardDimensionsChoice.add("42x36");
boardDimensionsChoice.add("49x42");
boardDimensionsChoice.add("56x48");
boardDimensionsChoice.add("63x54");
boardDimensionsChoice.add("70x60");
add(numPlayersPerTeamLabel);
add(numPlayersPerTeamChoice);
numPlayersPerTeamChoice.add("1");
numPlayersPerTeamChoice.add("2");
numPlayersPerTeamChoice.add("3");
numPlayersPerTeamChoice.add("4");
add(powerupsLabel);
add(powerups);
powerups.setSelected(true);
add(standardLabel);
add(standardSettings);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
saveLabel.setLocation(150, 100);
save.setLocation(315, 90);
numTeamsLabel.setLocation(0, 0);
numTeamsChoice.setLocation(170, 0);
numTeamsChoice.setSize(40, 15);
boardDimensionsLabel.setLocation(0, 25);
boardDimensionsChoice.setLocation(170, 25);
boardDimensionsChoice.setSize(80, 15);
numPlayersPerTeamLabel.setLocation(0, 50);
numPlayersPerTeamChoice.setLocation(225, 50);
numPlayersPerTeamChoice.setSize(40, 15);
powerupsLabel.setLocation(0, 75);
powerups.setLocation(110, 75);
standardLabel.setLocation(0, 100);
standardSettings.setLocation(110, 100);
}
public void saveSettings() {
switch(numTeamsChoice.getSelectedIndex()) {
case 0: numTeams = 2; break;
case 1: numTeams = 3; break;
case 2: numTeams = 4; break;
case 3: numTeams = 5; break;
case 4: numTeams = 6; break;
case 5: numTeams = 7; break;
case 6: numTeams = 8; break;
}
switch(boardDimensionsChoice.getSelectedIndex()) {
case 0: boardColumns = 7; boardRows = 6; break;
case 1: boardColumns = 14; boardRows = 12; break;
case 2: boardColumns = 21; boardRows = 18; break;
case 3: boardColumns = 28; boardRows = 24; break;
case 4: boardColumns = 35; boardRows = 30; break;
case 5: boardColumns = 42; boardRows = 36; break;
case 6: boardColumns = 49; boardRows = 42; break;
case 7: boardColumns = 56; boardRows = 48; break;
case 8: boardColumns = 63; boardRows = 54; break;
case 9: boardColumns = 70; boardRows = 60; break;
}
switch(numPlayersPerTeamChoice.getSelectedIndex()) {
case 0: playersPerTeam = 1; break;
case 1: playersPerTeam = 2; break;
case 2: playersPerTeam = 3; break;
case 3: playersPerTeam = 4; break;
}
if(powerups.isSelected() == true) {
powerupsSelected = true;
}
if(standardSettings.isSelected() == true) {
standardSelected = true;
powerupsSelected = false;
numTeams = 2;
boardColumns = 7;
boardRows = 6;
playersPerTeam = 1;
}
saveLabel.setVisible(true);
System.out.println("Using standard settings? " + standardSelected);
System.out.println("Powerups enabled? " + powerupsSelected);
System.out.println(numTeams + " " + boardColumns + " " + boardRows + " " + playersPerTeam);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(save)) {
saveSettings();
}
}
public int getBoardColumns() {
return boardColumns;
}
public int getBoardRows() {
return boardRows;
}
public int getNumTeams() {
return numTeams;
//again, put return 4; here and it will return 4 to TeamSettingsGUI
}
public int getPlayersPerTeam(){
return playersPerTeam;
}
public boolean getPowerupsEnabled() {
return powerupsSelected;
}
public boolean getStandardEnabled() {
return standardSelected;
}
}
Now remember, where I initialize numTeams and playersPerTeam, it can pass through to TeamSettingsGUI perfectly. I have a feeling that in saveSettings() it's not saving the variable, it's only temporary. If it is, then I don't know how to fix it. I've tried stuff like this.numPlayers in the switch case and everything.
Here is the TeamSettingsGUI:
package connectfouradvanced;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class TeamSettingsGUI extends JPanel implements ActionListener {
SettingsGUI settings = new SettingsGUI();
int numTeams = settings.getNumTeams();
int playersPerTeam = settings.getPlayersPerTeam();
JButton saveTeam = new JButton();
Color[] teamColors = new Color[numTeams];
String[][] playerNames = new String[numTeams][playersPerTeam];
char[][] playerSymbols = new char[numTeams][playersPerTeam];
Choice[] colors = new Choice[numTeams];
String[] colorList = {"Red", "Yellow", "Orange", "Green", "Black", "Blue", "Cyan", "Magenta"};
JCheckBox[] ready = new JCheckBox[numTeams];
JLabel[] teamNumbers = new JLabel[numTeams];
JTextField[][] playerNamesInput = new JTextField[numTeams][playersPerTeam];
JTextField[][] playerSymbolsInput = new JTextField[numTeams][playersPerTeam];
public TeamSettingsGUI() {
add(saveTeam);
saveTeam.addActionListener(this);
for(int i = 0; i < teamNumbers.length; i++) {
teamNumbers[i] = new JLabel();
teamNumbers[i].setText("Team " + (i + 1));
add(teamNumbers[i]);
}
for(int i = 0; i < colors.length; i++) {
colors[i] = new Choice();
colors[i].add("Red");
colors[i].add("Yellow");
colors[i].add("Orange");
colors[i].add("Green");
colors[i].add("Black");
colors[i].add("Blue");
colors[i].add("Cyan");
colors[i].add("Magenta");
colors[i].select(colorList[i]);
add(colors[i]);
}
for(int i = 0; i < playerNamesInput.length; i++) {
for(int k = 0; k < playerNamesInput[i].length; k++) {
playerNamesInput[i][k] = new JTextField();
playerNamesInput[i][k].setText("Team " + (i+1) + " player " + (k+1) + " name: ");
add(playerNamesInput[i][k]);
}
}
for(int i = 0; i < playerSymbolsInput.length; i++) {
for(int k = 0; k < playerSymbolsInput[i].length; k++) {
playerSymbolsInput[i][k] = new JTextField();
playerSymbolsInput[i][k].setText("Team " + (i+1) + " player " + (k+1) + " symbol: ");
add(playerSymbolsInput[i][k]);
}
}
for(int i = 0; i < ready.length; i++) {
ready[i] = new JCheckBox();
ready[i].setText("Ready?");
add(ready[i]);
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(saveTeam)) {
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println(numTeams + " " + playersPerTeam);
}
Note, TeamSettingsGUI is NOT complete. I can't continue on with aligning things and whatnot until I fix this.
Sorry if my code is dirty or anything, but I just cant figure out what's going on.
Forgot to include the main executable class, there is another missing BoardGUI class that is empty for now.
package connectfouradvanced;
import javax.swing.*;
public class ConnectFourAdvanced {
public static void main(String[] args) {
SettingsGUI s = new SettingsGUI();
BoardGUI b = new BoardGUI();
TeamSettingsGUI t = new TeamSettingsGUI();
JFrame fs = new JFrame();
JFrame fb = new JFrame();
JFrame ft = new JFrame();
fs.add(s);
fb.add(b);
ft.add(t);
fs.setVisible(true);
fs.setResizable(false);
fs.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
fs.setLocationRelativeTo(null);
fs.setSize(400, 150);
fs.setTitle("Settings");
while(fs.isVisible() == true) {
ft.setVisible(false);
}
ft.setVisible(true);
ft.setResizable(false);
ft.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
ft.setLocationRelativeTo(null);
ft.setSize(1200, 500);
ft.setTitle("Team Settings");
while(ft.isVisible() == true || fs.isVisible() == true) {
fb.setVisible(false);
}
fb.setVisible(true);
fb.setResizable(false);
fb.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fb.setLocation(100, 100);
fb.setSize(1000, 1000);
fb.setTitle("Connect Four");
}
}
I would like to add that I am only 16, and while I'm not that bad at java, GUIs and objects are still pretty new to me. So if my code is clunky or cluttered, or I'm doing some pretty dumb things that seem simple to others, it's because I'm new to this. This is my first big GUI project that I started on my own.
The reason you are having issues is that in TeamSettings, you are creating a new instance of SettingsGUI.
Think of it like buying a new car. If you had a car and then put all of your stuff in it, then bought another car which is exactly the same, would the new car have all of your stuff in it? No, At least I hope not, if it does let me know, we could make some money together... :)
Here is the line in question:
SettingsGUI settings = new SettingsGUI();
I would suggest that you use a Singleton pattern for the work you are doing. Put your settings in there and then you can reference them anywhere. There are more complex alternatives, but for the level of work you are doing, I would think a singleton would be your best bet.
I can't figure out why whenever I cycle through my array using the for-loop it only produces one element (the first) to console? I'm pretty sure it's a rookie-mistake I'm looking over, so any tips and suggestions would help.
I'm making a program for fun that compares two strings typed in a text field and if they don't exist in the array it produces a JOPtionPane message on the contrary. It's for a battle-hack I may produce in the future for vBulletin forum, but I'm messing around with algorithms before I move to that step. Thanks, guys!
package battleoptionspart1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.lang.*;
import javax.swing.border.*;
public class BattleOptionsPart1 extends JFrame{
JButton newthread, previewpost;
JRadioButton battle1;
JTextField postcount, oppA, oppB;
JLabel battle2, max;
JPanel panel;
String [] array = {"Bill","Tom","Wendy", "Paula"};
public BattleOptionsPart1 () {
panel = new JPanel();
Toolkit tool = Toolkit.getDefaultToolkit();
Dimension dim = tool.getScreenSize();
this.setSize(500, 500);
this.setTitle("Battle Options");
GridLayout grid = new GridLayout(0,1,2,2);
this.setLayout(grid);
newthread = new JButton("Post New Thread");
previewpost = new JButton("Preview Post");
postcount = new JTextField("", 4);
oppA = new JTextField("",10);
oppB = new JTextField("",10);
battle1 = new JRadioButton();
battle2 = new JLabel("Would you like to start a recorded battle?");
max = new JLabel("Enter max post count user must have to vote");
ListenForButton listen = new ListenForButton();
newthread.addActionListener(listen);
previewpost.addActionListener(listen);
JPanel opponents = new JPanel();
Border oppBorder = BorderFactory.createTitledBorder("Battlers");
opponents.setBorder(oppBorder);
opponents.add(oppA);
opponents.add(oppB);
JPanel battle = new JPanel();
Border battleBorder = BorderFactory.createTitledBorder("Start Battle");
battle.setBorder(battleBorder);
battle.add(battle1);
battle.add(battle2);
JPanel buttons = new JPanel();
Border buttonBorder = BorderFactory.createTitledBorder("Create Thread");
buttons.setBorder(buttonBorder);
buttons.add(newthread);
buttons.add(previewpost);
JPanel restriction = new JPanel();
Border resBorder = BorderFactory.createTitledBorder("Restrictions");
restriction.setBorder(buttonBorder);
restriction.add(postcount);
restriction.add(max);
this.add(opponents);
this.add(battle);
this.add(restriction);
this.add(buttons);
this.add(panel);
int xPos = (dim.width / 2) - (this.getWidth() / 2);
int yPos = (dim.height / 2) - (this.getHeight() / 2);
this.setLocation(xPos,yPos); //places form in the middle
this.setVisible(true); // users can see form
this.setResizable(false); //users can't resize the form
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private class ListenForButton implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String compareA = oppA.getText();
String compareB = oppB.getText();
if (e.getSource() == newthread)
{
System.out.println(compareA + "\n" + compareB);
for(int j = 0; j < array.length; j++)
{
System.out.println(array[j]);
if(!compareA.equals(array[j]))
{
JOptionPane.showMessageDialog(null, compareA + " doesn't exist!", "Error Message", JOptionPane.ERROR_MESSAGE);
oppA.requestFocus();
break;
}
if (!compareB.equals(array[j]))
{
JOptionPane.showMessageDialog(null, compareB + " doesn't exist!", "Error Message", JOptionPane.ERROR_MESSAGE);
oppB.requestFocus();
break;
}
else
{
JOptionPane.showMessageDialog(null, "New thread created successfully!", "Success", JOptionPane.INFORMATION_MESSAGE);
break;
}
}
}
else if (e.getSource() == previewpost)
{
System.exit(0);
}
}
}
public static void main(String[] args) {
BattleOptionsPart1 battle = new BattleOptionsPart1();
}
}
In each of the possible options in your loop, you use break, which leaves the loop immediately. If you remove those statements, you'll process each object in the array.
If you want to check if there's a match, you need to go through every element and do your processing after going through the whole array. Here is an example for an array of type int:
boolean contains = false;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == searchKey)
{
contains = true;
break;
}
}
You're breaking out of the loop. with the break; command after the first array element