Issue with displaying information on a program using swing, JButtons,etc - java

I'm making a multiplication table using swing.Its basically made up of JButtons. The table is formed from input from the user. The user selects the size of the table by entering a number. The last thing i need to do with this is create a heading that displays the numbers of the table created. Here is my sample code, if you run it, you'll see that its done for the vertical numbers. How can i get the numbers above and properly formatted to represent each column. Thank you.
package lab7;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GUIMultiplicationTable{
JFrame theFrame;
int number = 0;
JPanel panel, answerPanel, topPanel, leftPanel;
JLabel answerLabel, topLabel, leftLabel;
private void createAndShowGui(){
String x;
do{
x = JOptionPane.showInputDialog(null, "Enter the number");
number = Integer.parseInt(x);
}while (number <= 0);
theFrame = new JFrame("Multiplication Table");
panel = new JPanel(new GridLayout(number, number));
answerPanel = new JPanel();
answerLabel = new JLabel();
topPanel = new JPanel();
topLabel = new JLabel();
leftPanel = new JPanel();
leftLabel = new JLabel();
for (int i = 0; i < number; i++){
JLabel blah = new JLabel(Integer.toString(i + 1));
panel.add(blah);//add center to label
for (int j = 0; j < number; j++){
JButton button = new JButton();
if (i == 0){
button.setText(String.valueOf(j + 1));
}
if (j == 0){
button.setText(String.valueOf(i + 1));
}
for (int k = 1; k < number; k++)
{
if (i == k)
{
button.setText(String.valueOf((j + 1) * (k + 1)));
}
}
button.addActionListener(new ButtonsTableActionListener(i, j));
panel.add(button);
}
}
answerPanel.add(answerLabel);
theFrame.add(answerPanel, BorderLayout.SOUTH);
topPanel.add(topLabel);
theFrame.add(topPanel, BorderLayout.NORTH);
theFrame.add(panel);
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theFrame.pack();
theFrame.setLocationRelativeTo(null);
theFrame.setVisible(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
GUIMultiplicationTable h = new GUIMultiplicationTable();
h.createAndShowGui();
}
});
}
private class ButtonsTableActionListener implements ActionListener{
private int theRow, theColumn;
public ButtonsTableActionListener(int row, int column){
theRow = row;
theColumn = column;
}
#Override
public void actionPerformed(ActionEvent e){
int value = (theRow + 1) * (theColumn + 1);
answerLabel.setText("The value is: " + value + ".\nI got that by multiplying \n" + (theRow + 1) + "x" + (theColumn + 1));
}
};
}

An easy way to do this is to store the position of the button in the ActionListener, you can accomplish this by making your own class extending ActionListener, instead of doing an anonymous class. This way the code executed by the button will already have the information it needs to accomplish whatever you want.
Also you don't need the array of buttons, just add a button in the panel at a time, and at the same time add the actionListener.
This is your code cleaned up and working properly. Now, instead of showing a dialog do whatever you want to do.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class GUIMultiplicationTable
{
JFrame theFrame;
int number = 0;
JPanel panel;
private void createAndShowGui()
{
String x;
do
{
x = JOptionPane.showInputDialog(null, "Enter the number");
number = Integer.parseInt(x);
} while (number <= 0);
theFrame = new JFrame("Multiplication Table");
panel = new JPanel(new GridLayout(number, number));
for (int i = 0; i < number; i++)
{
for (int j = 0; j < number; j++)
{
JButton button = new JButton();
if (i == 0)
{
button.setText(String.valueOf(j + 1));
}
if (j == 0)
{
button.setText(String.valueOf(i + 1));
}
for (int k = 1; k < number; k++)
{
if (i == k)
{
button.setText(String.valueOf((j + 1) * (k + 1)));
}
}
button.addActionListener(new ButtonsTableActionListener(i, j));
panel.add(button);
}
}
theFrame.add(panel);
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theFrame.pack();
theFrame.setLocationRelativeTo(null);
theFrame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
GUIMultiplicationTable h = new GUIMultiplicationTable();
h.createAndShowGui();
}
});
}
private class ButtonsTableActionListener implements ActionListener
{
private int _row, _column;
public ButtonsTableActionListener(int row, int column)
{
_row = row;
_column = column;
}
#Override
public void actionPerformed(ActionEvent e)
{
// /do something
int value = (_row + 1) * (_column + 1);
String message = "I'm the button in the position (" + _row + ", " + _column + ")\nMy value is " + value + " = " + (_row + 1) + "*" + (_column + 1);
JOptionPane.showMessageDialog(theFrame, message);
}
};
}

Everything you need to do is just putting a JLabel somewhere.
final JLabel resultLabel = new JLabel("Select a button!");
Note that it should be final to be able to use it in the ActionListener. In the ActionListener you already had the right way, just look at these few lines to make it happen:
ActionListener first = new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < number; i++){
for(int j = 0; j < number; j++){
if(buttons[i][j] == e.getSource()){
// write the equation to the label
resultLabel.setText(buttons[i][j].getText()
+ " = " + (i+1) + " * "
+ (j+1));
// since you found the button you can now break
break;
}
}
}
}
};
Note the i+1 and j+1. The buttons are indexed from 0 to number-1, so the button at (0,0) actually shows the result of 1*1.
This is also important for your next two lines of code:
// you used i=1 and j=1, but you have to start with 0 to make it work for all buttons
for(int i = 0; i < number; i++){
for(int j = 0; j < number; j++){
buttons[i][j].addActionListener(first);
}
}
At a last step you also have to show the the label. If you just add it to the frame, as you do with the panel, you will see that you will not see it.
theFrame.add(resultLabel);
theFrame.add(panel);
The problem is that theFrame doesn't have a layoutmanager yet. So use a new Layout here as well:
theFrame.setLayout(new GridLayout(2,1));
Of course there will be better choices or some nice tweeks to make the layout more beautiful.
So as in sum how to change your code from top to bottom:
set a Layout for theFrame
create a new JLabel for the result of the click, make it final
set the label's text in the actionPerformed() method
add the label to theFrame
You can also consider putting the Label into a new JPanel and add that Panel to theFrame.

The loop in your actionListener is not required, the source of the event is the button that triggered it, so you can simply do...
JButton source = (JButton) e.getSource();
JOptionPane.showMessageDialog(theFrame, source.getText());
Instead.
Now having said that, I would, personally, use some kind of Map to link the JButton to the value, removing the need to have to try and cast the text of the button back to a numeric value (which I believe would be your next step), or store other information you might need to work with for the button (such as the values required to produce the answer)...
private Map<JButton, int[]> answers = new HashMap<JButton, int[]>(25);
//...
for(int i = 0; i < number; i++){
for(int j = 0; j < number; j++){
buttons[i][j] = new JButton();
if(i == 0) {
buttons[i][j].setText(String.valueOf(j+1));
}
if(j == 0) {
buttons[i][j].setText(String.valueOf(i+1));
}
for(int k = 1; k < number; k++){
if(i == k){
buttons[i][j].setText(String.valueOf((j+1) * (k+1)));
}
}
panel.add(buttons[i][j]);
// Store the answer here...
answers.put(buttons[i][j], new int[]{i, j});
}
}
//...
public void actionPerformed(ActionEvent evt) {
JButton source = (JButton) e.getSource();
int[] answer = answers.get(source);
JPanel panel = new JPanel();
JTextField[] fields = new JTextField[]{
new JTextField(2),
new JTextField(2)
};
panel.add(fields[0]);
panel.add(new JLabel("x"));
panel.add(fields[1]);
panel.add(new JLabel(" = " + source.getText()));
JOptionPane.showMessageDialog(theFrame, panel);
// check the values of the fields against the
// values of the answer
}

Related

Adding and removing checkboxes dynamically

I want to make ToDoList App. After successfully adding task to do (which contains checkbox, JLabel and date, all putted in a box) i want to remove them dynamically. With adding it's not problem but when i try to remove (ater clicking checked in checkbox) it works only once. Then it either removes not once which are intended or not removing them at all. I am not sure why it's not working so I paste all code below.
JSpinner dateSpin;
Box eventBox, boxBox;
Box[] taskBox = new Box[1000];
JTextField eventName;
Date date;
Checkbox[] doneCheck = new Checkbox[1000];
JLabel taskLabel;
JPanel panel;
JScrollPane scrollPane;
SimpleDateFormat simpleDate;
int i = 0;
public static void main(String[] args) {
new Main();
}
private Main(){
this.setSize(400, 600);
this.setTitle("To-Do List");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
boxBox = Box.createVerticalBox();
scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
eventBox = Box.createHorizontalBox();
eventBox.setBorder(BorderFactory.createEtchedBorder());
JLabel plusSign = new JLabel("+");
plusSign.setFont(new Font("Serafi", PLAIN, 20));
plusSign.setMaximumSize(new Dimension(Integer.MAX_VALUE, plusSign.getMinimumSize().height));
eventBox.add(plusSign);
eventName = new JTextField(20);
eventName.setFont(new Font("Times", Font.ITALIC, 15));
eventName.setMaximumSize(new Dimension(Integer.MAX_VALUE, eventName.getMinimumSize().height));
eventName.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == eventName){
/* to do: saving every task in some file, figure out how to remove
those tasks (checkbox + jlabel) -> whole box from screen or how to send them to "done"
also "done" to do*/
simpleDate = new SimpleDateFormat("E-dd-MM-yyyy");
taskBox[i] = Box.createHorizontalBox();
taskBox[i].setBorder(BorderFactory.createTitledBorder(simpleDate.format(date)));
doneCheck[i] = new Checkbox();
doneCheck[i].addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
int k = 0;
for (int j = 0; j < doneCheck.length; j++) {
if(doneCheck[j].getState()){
//remove(doneCheck[k]);
//System.out.println("?" + i + "?" + k + " " + e.getSource().toString());
System.out.println("xxxxx" + doneCheck[j].getState());
break;
}
System.out.println("oooooo");
k++;
}
System.out.println(doneCheck.length + taskBox[k].toString());
//System.out.println("! " + k + " " + e.getSource().toString());
boxBox.remove(taskBox[k]);
//boxBox.removeAll();
boxBox.revalidate();
boxBox.repaint();
}
});
taskBox[i].add(doneCheck[i]);
String taskName = eventName.getText();
taskLabel = new JLabel(taskName);
taskLabel.setMinimumSize(new Dimension(500,10));
taskLabel.setPreferredSize(new Dimension(300, 10));
taskBox[i].add(taskLabel);
boxBox.add(taskBox[i]);
boxBox.setMaximumSize(new Dimension(Integer.MAX_VALUE, boxBox.getMinimumSize().height + 11));
panel.add(boxBox);
panel.revalidate();
panel.repaint();
i++;
}
}
});
eventBox.add(eventName);
date = new Date();
dateSpin = new JSpinner(new SpinnerDateModel(date, null, null, Calendar.DAY_OF_MONTH));
JSpinner.DateEditor dateEditor = new JSpinner.DateEditor(dateSpin, "dd/MM/yy");
dateSpin.setEditor(dateEditor);
dateSpin.setMaximumSize(new Dimension(Integer.MAX_VALUE, dateSpin.getMinimumSize().height));
dateSpin.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if(e.getSource() == dateSpin){
date = (Date) dateSpin.getValue();
}
}
});
eventBox.add(dateSpin);
panel.add(eventBox, new FlowLayout());
this.add(scrollPane);
this.setVisible(true);
}
You never remove elements from the taskBox and doneCheck arrays.
Now if you mark the first entry as done, your ItemListener will always find this first entry when looping over the doneCheck array.
Marking the entries as done in reverse order (always the last shown entry) will remove one entry after the other.
As to your software design: it's considered bad practice to manage your data in several parallel arrays.
Please consider creating a custom class for the todo items that manages all the elements of a single todo item.
Unless you are initializing doneCheck items somewhere, this:
Checkbox[] doneCheck = new Checkbox[1000];
And this:
int k = 0;
for (int j = 0; j < doneCheck.length; j++) {
if (doneCheck[j].getState()) {
--------^^^^^^^^^^^^
Is probably one the reason it fails: you probably got a NullPointerException somewhere, eg: when value of j > 0. The NPE will probably be catched by the EventDispatchThread which may or may not be kind enough to show it on stderr...
I fail to see why you are using this array, and you can shorten your code and avoid NPE like this:
Checkbox cb = new Checkbox();
cb.addItemListener(event -> {
if (cb.getState()) { // not null!
boxBox.remove(cb);
boxBox.revalidate();
boxBox.repaint();
}
});
doneCheck[i] = cb; // I still don't know why you need that.
My guess is that you have 2 variables global int i = 0 and local int k = 0 in here
public void itemStateChanged(ItemEvent e) {
// int k = 0;//<-------- LOCAL
for (int j = 0; j < doneCheck.length; j++) {
if(doneCheck[j].getState()){
//Either k = j;
boxBox.remove(taskBox[j]);
//remove(doneCheck[k]);
//System.out.println("?" + i + "?" + k + " " + e.getSource().toString());
System.out.println("xxxxx" + doneCheck[j].getState());
break;
}
System.out.println("oooooo");
//k++;//<-- ALWAYS == last j value before the break;
}
System.out.println(doneCheck.length + taskBox[k].toString());
//System.out.println("! " + k + " " + e.getSource().toString());
//boxBox.remove(taskBox[k]);//
//boxBox.removeAll();
boxBox.revalidate();
boxBox.repaint();
}
Every time you call for itemStateChanged int k = 0; will be initialized to 0 and you will be removing element[j] from array of taskBox. As you k++ statement will be equal to the last j value before the break; because it sits after the if(doneCheck[j].getState()){...
Try moving boxBox.remove(taskBox[j]); inside the for loop and using j instead of k.

Java Connect4 Game with GUI bug issues

http://imgur.com/a/V7LPP
Grid images are in the link
I have 2 main issues with my current connect4 code, sometimes the "AI" places 2 discs in one turn and the player can't fill the entire board without the "AI" entering an infinite loop. Any help is appreciated.
/**
* Auto Generated Java Class.
*/
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class EmptyFrame1 implements ActionListener
{
//Array of JButtons
static JButton [] mnuBtn = new JButton[2];
static JButton [] btnArray = new JButton[7];
static JLabel [][] board = new JLabel[6][7];
static int [][] numBoard = new int[6][7];
static int choice = 0;
static int playerColour = 1;
static int computerColour = 2;
static int computerTurn = 0;
static ImageIcon emptyGrid = new ImageIcon("EmptyGrid.png");
static ImageIcon yellowGrid = new ImageIcon("YellowGrid.png");
static ImageIcon redGrid = new ImageIcon("RedGrid.png");
static JPanel pnlBoard;
static boolean validTurn;
static int pieceCount = 42;
public EmptyFrame1()
{
JFrame game = new JFrame("Connect 4");
//mainFrame panel to hold all components
JPanel mainFrame = new JPanel();
pnlBoard = new JPanel();
pnlBoard.setLayout(new GridLayout(7,6));
//Change mainFrame layout to vertical BoxLayout
mainFrame.setLayout(new BoxLayout(mainFrame, BoxLayout.Y_AXIS));
//For every single button
//Set the button text to its index value, add an action listener and add it to the pnlButtons
for (int i = 0; i < btnArray.length; i++)
{
btnArray[i] = new JButton("place");
btnArray[i].addActionListener(this);
pnlBoard.add(btnArray[i]);
}//end for
for (int r = 0; r < board.length; r++)
{
for (int c = 0; c < board[r].length; c++)
{
board[r][c] = new JLabel(emptyGrid);
board[r][c].setPreferredSize(new Dimension(69, 69));
pnlBoard.add(board[r][c]);
}//end for
}//end for
//Add all the panels to the mainFrame panel
mainFrame.add(pnlBoard);
//add mainFrame to the JFrame
game.add(mainFrame);
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Added this for security
game.pack();
game.setVisible(true);
game.setResizable(false);
}
//*Action listener for all buttons*
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i < btnArray.length; i++)
{
//if the current button was triggered, set the choice to the button index
if (btnArray[i] == e.getSource())
{
choice = i;
colCheck(choice, 1);
//System.out.println("User turn used");
pieceCount--;
for (int j = 0; j < btnArray.length; j++)
{
if (numBoard[0][j] == 0) btnArray[j].setEnabled(true);
}
if (pieceCount > 0)
{
validTurn = false;
while(!validTurn)
{
computerTurn = (int) (Math.random() * 7);
System.out.print(computerTurn + " ");
validTurn = colCheck(computerTurn, 2);
//System.out.println("CPU tried to move");
}
}
System.out.println();
setGrid();
pieceCount--;
System.out.println(pieceCount);
validTurn = false;
}//end if
}//end for
pnlBoard.repaint();
}//end actionPerformed
public static boolean colCheck(int choice, int currentTurn)
{
int row = -1;
for (int r = 5; r >= 0; r--)
{
if (numBoard[r][choice] == 0)
{
row = r;
break;
}
}
//System.out.println("Row That CPU Chooses: " + row);
if (row > -1)
{
numBoard[row][choice] = currentTurn;
if (row == 0)
{
btnArray[choice].setEnabled(false);
return false;
}
return true;
}
return false;
}
public static void setGrid()
{
for (int r = 0; r < numBoard.length; r++)
{
for (int c = 0; c < numBoard[r].length; c++)
{
if (numBoard [r][c] == 0)
{
board[r][c].setIcon(emptyGrid);
}
else if (numBoard [r][c] == 1)
{
board[r][c].setIcon(redGrid);
}
else if (numBoard [r][c] == 2)
{
board[r][c].setIcon(yellowGrid);
}
}
}
}
/**
* Inner helper class that defines the graphics
*/
public static void main(String[] args)
{
new EmptyFrame1();
}
//end constructor
Some problems and suggestions:
Your colCheck method and the while (!validTurn) { loop in the actionPerformed method is where the problem is located.
This method should not set numBoard value or disable buttons. In other words, it should not have any "side effects".
Instead it should only check for validity and then return a boolean value, nothing more or less
You should have another method that is called first, one that checks if no valid columns are available, if the game is effectively over. This should be called before the while loop above and should prevent the while loop from entering. This will end your endless loop problem because it's looping because no valid columns can be found for the computer turn.
You should have another method for setting the numBoard state and for enabling and disabling JButtons.
Change your colCheck to this to see where the loop is coming from:
public static boolean colCheck(int choice, int currentTurn) {
int row = -1;
for (int r = 5; r >= 0; r--) {
if (numBoard[r][choice] == 0) {
row = r;
break;
}
}
// System.out.println("Row That CPU Chooses: " + row);
if (row > -1) {
numBoard[row][choice] = currentTurn;
if (row == 0) {
btnArray[choice].setEnabled(false);
System.out.printf("debug 1 row %d %n", row);
return false;
}
System.out.printf("debug 2 row %d %n", row);
return true;
}
System.out.printf("debug 3 row %d %n", row);
return false;
}
Other issues not directly related to your problem at hand, but which should be addressed
You're grossly over-using the static modifier, and in fact none of your fields should be static. All should be private instance fields.
You've got your program logic code, the model, mixed in the same class as the GUI, the view, making it hard to debug problems and enhance the program. Much better if you could make your model a completely separate class, one that is "view-agnostic" meaning that it is testable on its own and can work with any view, be it a command line or Swing or Android UI.
Your question depends on images, EmptyGrid.png, YellowGrid.png.... that we have no access to, preventing us from testing it.
You're using magic numbers, such as 0, 1, 2 for position values, and need to avoid doing this.
Instead use an enum for empty, user and computer
This is Java not Javascript. You'll want to be clear on the difference because they're two completely different languages.

How to fill JComboBox after user fills necessary text fields?

I want to add a JComboBox to my main panel and fill it with an ArrayList I made in a different method named rectSizeList (which right now prints the ArrayList to the console), this method gets its parameters from another static method named actionPerformed. I cant figure a way to take the filled array after user input to fill my ComboBox. Any help will be appreciated.
All comment is this format are to aid question:
/*
* Like so
*
*/
All other comments are to help whomever my want to compile and run, so that they might understand what is going on.
Main class
import javax.swing.*;
public class ductulatorApp
{
public static void main(String[] args)
{
JFrame frame = new DuctulatorFrame();
frame.setVisible(true);
}
}
Frame class
import javax.swing.*;
import java.awt.*;
public class DuctulatorFrame extends JFrame
{
private static final long serialVersionUID = 1L;
public DuctulatorFrame()
{
setTitle("Test Scores");
setSize(267, 200);
centerWindow(this);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new DuctulatorPanel();
this.add(panel);
}
private void centerWindow(Window w)
{
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
setLocation((d.width-w.getWidth())/2, (d.height-w.getHeight())/2);
}
}
Panel class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.ArrayList;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class DuctulatorPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private JTextField staticTextField,
cfmTextField,
rductTextField,
sqductTextField;
private JLabel staticLabel,
cfmLabel,
rductLabel,
sqductLabel;
private JButton calculateButton,
exitButton,
clearButton;
private JComboBox ductSizes; //JComboBox instance
private String[] ductList; //Array to fill JComboBox
double staticP; //static pressure entered by user
double cfm; //cfm entered by user
double deSQ;
double de; //round duct diameter
double pi = 3.14;
double ca; //round duct surface area
double radious;
double sqrA; //rectangular duct area
//two sides of rectangular duct
double a = 4;
double b = 4;
String squareduct;
public DuctulatorPanel()
{
// Creates main panel for labels and text fields
JPanel displayPanel = new JPanel();
displayPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
staticLabel = new JLabel("Static pressure:");
displayPanel.add(staticLabel);
staticTextField = new JTextField(10);
displayPanel.add(staticTextField);
cfmLabel = new JLabel(" CFM:");
displayPanel.add(cfmLabel);
cfmTextField = new JTextField(10);
displayPanel.add(cfmTextField);
rductLabel = new JLabel("Round Duct:");
displayPanel.add(rductLabel);
rductTextField = new JTextField(15);
rductTextField.setEditable(false);
rductTextField.setFocusable(false);
displayPanel.add(rductTextField);
sqductLabel = new JLabel("Square Duct:");
displayPanel.add(sqductLabel);
/*
* This is where I want to add my JComboBox problem is I want to populate ductList arr
* with the array inside rectSizeList(int number) BELOW
* right now this method only prints my array to the console
* this method takes its parameters from the value assigned to
* actionperformed(ActionEvent e)
* below is comboBox commented out
*/
//ductList = new String[list.size]; THIS IS ASSUMING I COULD SOME HOW TRANSFER
//ductList = list.toArray(ductList); ARRAYLIST UP HERE AND NAME IT LIST AND USE IT
//ductSizes = new JComboBox(ductList);
//ductSizes.setSelectedIndex(1);
//displayPanel.add(ductSizes);
sqductTextField = new JTextField(10);
sqductTextField.setEditable(false);
sqductTextField.setFocusable(false);
displayPanel.add(sqductTextField);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
calculateButton = new JButton("Calculate");
calculateButton.addActionListener(this);
buttonPanel.add(calculateButton);
clearButton = new JButton("Clear");
clearButton.addActionListener(this);
buttonPanel.add(clearButton);
exitButton = new JButton("Exit");
exitButton.addActionListener(this);
buttonPanel.add(exitButton);
this.setLayout(new BorderLayout());
this.add(displayPanel, BorderLayout.CENTER);
this.add(buttonPanel, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent e)
{
NumberFormat number = NumberFormat.getNumberInstance();
number.setMaximumFractionDigits(1);
Object source = e.getSource();
if(source == exitButton)System.exit(0);
else if(source == clearButton)
{
staticTextField.setText("");
cfmTextField.setText("");
rductTextField.setText("");
sqductTextField.setText("");
staticP = 0;
cfm = 0;
deSQ = 0;
}
else if(source == calculateButton)
{
try
{
staticP = Double.parseDouble(staticTextField.getText());
cfm = Double.parseDouble(cfmTextField.getText());
}
catch(NumberFormatException nfe)
{
staticTextField.setText("Invalid input");
staticP = 0;
cfm = 0;
deSQ = 0;
de = 0;
}
deSQ = staticP * (0.109136 * Math.pow(cfm, 1.9)); //Calculate round duct
de = Math.pow(deSQ, 0.199) * 2.5; //diameter
// Calculate round duct surface area
radious = de/2;
ca = (radious * radious) * pi;
ca = (int)ca;
rectSizeList((int)ca);
double i = 0;
for(i=0; i<ca; i++)
{
a = a + 0.5;
b = b + 0.5;
i = a * b; // convert round duct to rectangular duct
}
sqrA = i;
a = (int)a;
b = (int)b;
rductTextField.setText(number.format(de));
squareduct = (a + " x " + b);
sqductTextField.setText(squareduct);
}
}
public ArrayList<String> rectSizeList(int number)
{
if (number <= 0) throw new IllegalArgumentException("The number should be greater than 0.");
int i = 0;
int j = 0;
/*
* This is the array list I am hoping to use in order to fill array for
* comboBox
*/
ArrayList<String> rectangularDucts = new ArrayList<String>(); //Create array for rectangular duct
// Fill array for rectangular duct using nested for loop
/*
* If statement will ensure the result is with in range of surface
* area of duct
*/
for(i=4; i<=50; i++)
{
for(j=4; j<=50; j++)
{
if(number == i*j || (i*j)+1 == number || (i*j)-2 == number)
{
rectangularDucts.add(i + " x " + j);
}
}
if(number == i*j || (i*j)+1 == number || (i*j)-2 == number)
{
rectangularDucts.add(i + " x " + j);
}
}
System.out.println(rectangularDucts);
return rectangularDucts;
}
}
I think that your problem is easily solved with just a DefaultComboBoxModel object, or in your situation (I guess), a DefaultComboBoxModel<String> object. Give your class this field, create your JComboBox with this as its model, by passing it into the constructor, and then fill this model object as the need arises.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class ComboModelEg extends JPanel {
private DefaultComboBoxModel<String> comboModel = new DefaultComboBoxModel<>();
private JComboBox<String> comboBox = new JComboBox<>(comboModel);
private JTextField textField = new JTextField(5);
public ComboModelEg() {
// so combo box is wide enough
comboBox.setPrototypeDisplayValue(" ");
add(comboBox);
add(textField);
add(new JButton(new AddToComboAction("Add Text", KeyEvent.VK_A)));
}
// AbstractAction is like a *super* ActionListener
private class AddToComboAction extends AbstractAction {
public AddToComboAction(String name, int mnemonic) {
super(name); // button's text
putValue(MNEMONIC_KEY, mnemonic); // button's mnemonic key
}
#Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText(); //get text from text field
comboModel.addElement(text); // and put it into combo box's model
}
}
private static void createAndShowGui() {
ComboModelEg mainPanel = new ComboModelEg();
JFrame frame = new JFrame("ComboModelEg");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Translated to your code, it could look something like:
for (i = 4; i <= 50; i++) {
for (j = 4; j <= 50; j++) {
if (number == i * j || (i * j) + 1 == number
|| (i * j) - 2 == number) {
// rectangularDucts.add(i + " x " + j); //!!
comboModel.addElement(i + " x " + j); //!!
}
}
if (number == i * j || (i * j) + 1 == number || (i * j) - 2 == number) {
// rectangularDucts.add(i + " x " + j);
comboModel.addElement(i + " x " + j); //!!
}
}
this is how i do it
ArrayList<String> myList = new ArrayList<>();
//some code to populate the list
jComboBox.removeAllItems();
for(int i=0;i<myList.size();i++){
jComboBox.addItem(myList.get(i));
}

a simple GUI multiplication table

I'm supposed to create a simple multiplication table using GUI and for the most part, it's doing what it is supposed to do. But I just can't figure out the bottom portion of it where if you click on a specific button, a text will say what the two numbers are being multiplied and the answer.
No matter what button I click, it'll only tell me the numbers I input and multiply them together. Here is my code:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
public class MultiplicationTable {
int clickedCount;
int rowCount;
int colCount;
JFrame frame;
JPanel buttonPanel, countPanel;
JLabel countLabel;
private void createAndShowGui(){
rowCount = Integer.parseInt(JOptionPane
.showInputDialog("How many rows do you want your multiplication table to be? "));
colCount = Integer
.parseInt(JOptionPane
.showInputDialog("How many columns do you want your multiplication table to be? "));
frame = new JFrame ("Simple Multiplication Table");
frame.setLayout(new BorderLayout());
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(rowCount, colCount));
countPanel = new JPanel();
countLabel = new JLabel("? x ? = ?");
for(int rowCounter = 1; rowCounter <= rowCount; rowCounter++)
for(int colCounter = 1; colCounter <= colCount; colCounter++){
final JButton j = new JButton(Integer.toString(rowCounter * colCounter));
j.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event) {
for(int rc = 1; rc <= rowCount; rc++)
for(int cc = 1; cc <= colCount; cc++){
countLabel.setText(rc + " x " + cc + " = " + String.valueOf(rc * cc));
}
}
});
buttonPanel.add(j);
}
frame.add(buttonPanel, BorderLayout.NORTH);
countPanel.add(countLabel);
frame.add(countPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args){
MultiplicationTable c = new MultiplicationTable();
c.createAndShowGui();
}
}
Your current ActionListener has no context, it doesn't know what two values were used to generate the value you gave the button.
What you could do is create a ActionListener which takes the values used to produce the button's text, this would then be capable of updating the label accordingly. For example...
public class MultiplerActionListener implements ActionListener {
private int[] values;
private JLabel label;
public MultiplerActionListener(JLabel label, int... valuesToMultiple) {
values = valuesToMultiple;
this.label = label;
}
#Override
public void actionPerformed(ActionEvent event) {
int answer = 1;
StringBuilder sb = new StringBuilder(64);
for (int value : values) {
if (sb.length() > 0) {
sb.append(" x ");
}
sb.append(value);
answer *= value;
}
sb.append(" = ");
sb.append(answer);
label.setText(sb.toString());
}
}
Then you would simply need to apply it when you create the buttons
for(int rowCounter = 1; rowCounter <= rowCount; rowCounter++) {
for(int colCounter = 1; colCounter <= colCount; colCounter++){
final JButton j = new JButton(Integer.toString(rowCounter * colCounter));
j.addActionListener(new MultiplerActionListener(countLabel, rowCounter, colCounter));
buttonPanel.add(j);
}
}

for loop for array only processing one element in java?

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

Categories

Resources