Adding and removing checkboxes dynamically - java

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.

Related

Modifying a double list with "move all" button

I am working on a GUI (that this community has been extremely helpful with so far) and I have reached another important step I need to achieve.
Currently my GUI consists of a JOptionsPane. Inside this pane is a panel that contains two lists and four buttons. Two of the buttons are arrows who's text is ">" and "<". (The buttons are in between both lists.)
Those buttons work correctly. A user can select one of the objects from the first list and then click the > and it will move to the second list and visa versa.
Next I need to add a feature where there is a ">>" button. This will move all the items in the first list to the second. I really have no idea how to handle this part. I am assuming it is some type of while loop although I'm not entirely sure.
First allow me to post the simple snipplet that shows the > button.
buttonin = new JButton(" > ");
buttonin.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
int[] fromindex = outputDetails.getSelectedIndices();
Object[] from = outputDetails.getSelectedValues();
for(int i=0; i< from.length; i++){
output.addElement(from[i]);
System.out.println(output);
}
for(int i = (fromindex.length-1); i>=0; i--){
input.remove(fromindex[i]);
}
}
});
Next I will post the full code in case that is needed to understand what I am trying to achieve. I hope this is enough information for someone to assist me if not I apologize, the actual program is very long and I couldn't think of an easy way to isolate this test case.
public static void displayGUI(){
int result = JOptionPane.showOptionDialog(null, getPanel(),"JOptionPane Example : ", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{"Confirm","Create Return"}, "default");
if(result == 1){
initialScreenDecisions="NONE";
MainWriter.finishedCounter=true;
System.out.println(MainWriter.finishedCounter);
while(MainWriter.entryDetails.size()>0){
MainWriter.entryDetails.remove(0);
}
while(output.size()>0){
output.remove(0);
}
}
}
private static JPanel getPanel(){
JPanel panel = new JPanel();
JPanel panelTop = new JPanel();
JPanel topButtons = new JPanel();
JPanel bottomButtons = new JPanel();
String text = "<html>"
+"Batch <font size=6 color=>"+MainWriter.batchHeaderCounter+"</font> of <font size=6>"+BatchCounter.BatchTotal+"</font>"
+"<br>Batch Header: <font size=5><font color=red>"+MainWriter.BatchHeader+"</font>"
+"</html>";
JLabel topLabel = new JLabel(text);
panelTop.add(topLabel);
input = new DefaultListModel();
output = new DefaultListModel();
String[] shoppingItems = new String[MainWriter.entryDetails.size()];
shoppingItems = MainWriter.entryDetails.toArray(shoppingItems);
for(int i = 0; i < shoppingItems.length; i++){
input.addElement(shoppingItems[i]);
}
outputDetails = new JList(input);
outputDetails.setVisibleRowCount(10);
outputDetails.setFixedCellHeight(20);
outputDetails.setFixedCellWidth(400);
outputDetails.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane list1 = new JScrollPane(outputDetails);
inputDetails = new JList(output);
inputDetails.setVisibleRowCount(10);
inputDetails.setFixedCellHeight(20);
inputDetails.setFixedCellWidth(400);
inputDetails.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
JScrollPane list2 = new JScrollPane(inputDetails);
JPanel buttonPanel = new JPanel();
buttonin = new JButton(" > ");
buttonin.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
int[] fromindex = outputDetails.getSelectedIndices();
Object[] from = outputDetails.getSelectedValues();
for(int i=0; i< from.length; i++){
output.addElement(from[i]);
System.out.println(output);
}
for(int i = (fromindex.length-1); i>=0; i--){
input.remove(fromindex[i]);
}
}
});
buttonPanel.add(buttonin);
buttonout = new JButton(" < ");
buttonout.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
Object[] to = inputDetails.getSelectedValues();
int[] toindex = inputDetails.getSelectedIndices();
for(int i = 0; i < to.length; i++){
input.addElement(to[i]);
}
for(int i = (toindex.length-1); i >=0; i--){
output.remove(toindex[i]);
}
}
});
buttonall = new JButton(" >> ");
buttonall.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(initialScreenDecisions.equals("DEFAULT")){
JOptionPane.showMessageDialog(null, "You have selected to add all entry details. Please " +
"\nclick okay on the next scren to confirm or click " +
"\n'>>' again to cancel the apply all option.");
initialScreenDecisions="ADDALL";
}else if(initialScreenDecisions.equals("ADDALL")){
JOptionPane.showMessageDialog(null, "You have canceled the apply all option.");
initialScreenDecisions="DEFAULT";
}else{
JOptionPane.showMessageDialog(null, "You must disable the '<<' option before you can use this.");
}
}
});
buttonnone = new JButton(" << ");
buttonnone.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
if(initialScreenDecisions.equals("DEFAULT")){
JOptionPane.showMessageDialog(null, "You have selected to skip the current batch and" +
"\nomit all of it's entries. Click okay on the next" +
"\nscreen to confirm or click '<<' again to" +
"\ncancel the option.");
initialScreenDecisions="NONE";
}else if(initialScreenDecisions.equals("NONE")){
JOptionPane.showMessageDialog(null, "You have canceled the omit all option.");
initialScreenDecisions="DEFAULT";
}else{
JOptionPane.showMessageDialog(null, "You must disable the '>>' option before you can use this.");
}
}
});
buttonhelp = new JButton("HELP");
buttonhelp.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
JOptionPane.showMessageDialog(null, "This screen allows you to determine the entry details from" +
"\nthe current batch that will be included in the final return." +
"\nSelect the details you wish to include and click the > arrow to" +
"\nmove them to the right side. Pressing the >> button will" +
"\ninclude all entry details for the current batch in the final" +
"\nreturn. Clicking the < button will move a detail back."+
"\nClick << to omit the entire batch. Use confirm to continue"+
"\nto the next step or 'create return' to finish the Nacha return"+
"\nwith all past additions.");
}
});
buttonPanel.setLayout(new BorderLayout());
topButtons.add(buttonin);
topButtons.add(buttonall);
topButtons.add(buttonnone);
topButtons.add(buttonout);
bottomButtons.add(buttonhelp);
buttonPanel.add(topButtons,BorderLayout.NORTH);
buttonPanel.add(buttonhelp,BorderLayout.SOUTH);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
bottomPanel.add(Box.createRigidArea(new Dimension(10,0)));
bottomPanel.add(list1);
bottomPanel.add(Box.createRigidArea(new Dimension(5,0)));
bottomPanel.add(buttonPanel);
bottomPanel.add(Box.createRigidArea(new Dimension(5,0)));
bottomPanel.add(list2);
bottomPanel.add(Box.createRigidArea(new Dimension(10,0)));
panel.setLayout(new BorderLayout());
panel.add(panelTop,BorderLayout.NORTH);
panel.add(bottomPanel,BorderLayout.CENTER);
panel.setOpaque(true);
return panel;
}
You can ignore the above >> button contents. Right now it will allow the user to select all of the items in the list it just doesn't visually show the selection. If I get the >> button to move all the items at once then I won't need the extra steps you can see I have implemented.
I'm not too sure what all your variable types are, but I think this should work in your ActionListener for >>.
for (int i = 0; i < input.getSize(); i++) {
output.addElement(input.get(i));
}
input.clear();

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

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
}

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

Java hangman game with gui, problems with incrementing/decrementing numbers

The following part of the code doesn't work, as the won/lost count keeps incrementing by more than 1 for each word, and sometimes I get a nullpointerexception with the string length. Moreover, although the player is supposed to get 7 tries(int no), sometimes he gets more, sometimes less. The Strings are taken from a text file "Hangeng.txt". The whole game is inside a keyboard keytyped listener that is inside a button listener. Any tips on how the layout of the game should generally be arranged so as to avoid errors are welcome, as I am only beginning to work with swing and gui stuff.
public class test{
static int won = 0;
static int lost = 0;
static String key = "";
static String word = null;
static int no = 0;
static StringBuffer toguess;
public static void main(String[] args) throws IOException{
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(3,1));
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
JButton button = new JButton();
JLabel label = new JLabel();
JLabel label2 = new JLabel();
panel1.add(label);
panel2.add(button);
panel3.add(label2);
frame.setSize(800,600);
frame.add(panel1);
frame.add(panel2);
frame.add(panel3);
frame.setVisible(true);
//the button that starts the game or gets a new word
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.requestFocus();
no = 0;
label2.setText("won " + won + ", lost " + lost);
button.setText("Next");
//get random word from file
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(
"hangeng.txt"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
int lineno = (int) (Math.random() * 100);
for (int i = 0; i < lineno; i++) {
try {
reader.readLine();
} catch (IOException e1) {
e1.printStackTrace();
}
}
try {
word = reader.readLine().replace(" ", "");
} catch (IOException e1) {
e1.printStackTrace();
}
String missing = "";
for (int u = 0; u < (word.length() - 2); u++) {
missing = missing + "*";
}
final String guess = word.charAt(0) + missing
+ word.charAt((word.length() - 1));
toguess = new StringBuffer(guess);
label.setText(toguess.toString());
final ArrayList<String> tried = new ArrayList<String>();
//keylistener that listens to key clicks by the user
frame.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent arg0) {
}
public void keyReleased(KeyEvent arg0) {
}
public void keyTyped(KeyEvent arg0) {
key = "" + arg0.getKeyChar();
String guessing = null;
boolean k = false;
if ((no < 6)) {
guessing = key;
System.out.println(guessing);
if (!(tried.contains(guessing))) {
tried.add(guessing);
for (int length = 1; length < (guess
.length() - 1); length++) {
if (guessing.equals(String.valueOf(word.charAt(length)))) {
toguess.replace(length,
(length + 1),
String.valueOf(word.charAt(length)));
k = true;
}
}
if (k == true) {
label.setText(toguess.toString());
} else {
no = no + 1;
}
k = false;
}
label.setText(toguess.toString());
if (toguess.toString().equals(word)) {
label.setText("Correct! The word was " + word);
no = 6;
won = won + 1;
}
}
else if ((no == 6)
&& (!(toguess.toString().equals(word)))) {
label.setText("Sorry, but the word was " + word);
lost = lost + 1;
}
}
});
}
});
}
}
+1 to all comments....
Adding to them:
Do not use KeyListener use a KeyAdapter however as you are using Swing and not AWT you should use KeyBindings for Swing see here for example.
Dont forget to create and manipulate Swing components on Event Dispatch Thread via SwingUtiltities.invokeLater(..) block see here for more.
Check class naming schemes they shuld start with capital letter, i.e test should be Test and every new word after that should be capitalized.
Do not call setSize on JFrame rather use appropriate LayoutManager and/or override getPreferredSize() of JPanel and return a size which fits its content and call pack() on JFrame instance after adding all components.
Also SSCCE should be compilable from copy and paste this is not.... i.e variables needed to be changed to final and I dont have a sample of Hangeng.txt so cant test
Lastly use the #Override annotation to ensure you are overriding the correct methods, i.e
#Override
public void actionPerformed(ActionEvent e) {
}

How to identify ID of Labels in Java

I have created 9 JLabels by array. And it has common Event Listener with method of mouseClicked(MouseEvent src){... }, here i am finding problem is, how can I identify which JLabel is clicked?
Say, if label[0] is clicked then I want to show "Label-0 is clicked",
if label[1] is clicked then I want to show "Label-1 is clicked"
Can I perform this? if yes then How?
NOTE :- I found some answer stating that add Custom 'id' Property, I would but first, I prefer if there is any default method exist.
Add Label
JPanel pnl = new JPanel(new FlowLayout());
dd.add(pnl);
addlistener();
for (int i = 0; i < 10; i++) {
pnl.add(lbl[i] = new JLabel("" + i));
lbl[i].addMouseListener(listern);
}
Listener
public void mouseEnter(MouseEvent me) {
System.err.println("Hi");
me.getComponent();
if(me.getSource() instanceof JLabel){
System.out.println("lable"+ ((JLabel)me.getSource()).getText());
}
}
You could loop the array comparing the source of the event to each element in the array...
for (int index = 0; index < myLabelArray.length; index++) {
if (myLabelArray[index].equals(src.getSource())) {
System.out.println("Label-" + index + " was clicked");
break;
}
}
Or you could "name" each label...
JLabel[] myLabelArray = new JLabel[9];
for (int index = 0; index < 9; index++) {
JLabel label = new JLabel("...");
label.setName(Integer.toString(index));
label.addMouseListener(commonMouseListener);
myLabelArray[index] = label;
}
Then in your mouse listener...
public void mouseClicked(MouseEvent evt) {
System.out.println("Label-" + ((JLabel)evt.getSource()).getName() + " was clicked");
}
Or you could use a Map instead of an array or a List...

Categories

Resources