-1

I am making a quick password manager just to practice before I go back to school. I don't care that it uses strings to store passwords in plain text... that's not the point.

What I need some help with is in my second JFrame window I would like to display the password when the user clicks on a JButton, the "website name" (I'm using a map). However, I can't get any of my buttons to actually do anything in the second JFrame window.

Here's the code. This is just the view class. I don't believe the model or the controller are applicable here.

import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

import components.simplereader.SimpleReader;
 import components.simplereader.SimpleReader1L;

/**
 * View class.
 *
 * @author Redacted
 */
@SuppressWarnings("serial")
public final class PasswordManagerView1 extends JFrame
    implements PasswordManagerView {

//controller
private PasswordManagerController controller;

/**
 * GUI widgets that need to be in scope in actionPerformed method, and
 * related constants. (Each should have its own Javadoc comment, but these
 * are elided here to keep the code shorter.)
 */
private static final int ROWS_IN_BUTTON_PANEL_GRID = 1,
        COLUMNS_IN_BUTTON_PANEL_GRID = 2, KEY_LENGTH = 10,
        VALUE_LENGTH = 15;
// JLabels
private final JLabel keyText, valueText;

// JTextFields
private final JTextField key, value;

// JButtons
private final JButton resetButton, enterButton, recallButton, testButton;

//constructor
public PasswordManagerView1() {
    //JFrame title
    super("Password Manager");

    //widgets
    this.testButton = new JButton("Test Button");
    this.recallButton = new JButton("Recall");
    this.valueText = new JLabel("Enter password here",
            SwingConstants.CENTER);
    this.keyText = new JLabel("Enter store here", SwingConstants.CENTER);
    this.key = new JTextField(KEY_LENGTH);
    this.value = new JTextField(VALUE_LENGTH);
    this.resetButton = new JButton("Reset");
    this.enterButton = new JButton("Enter");

    //Button panel
    JPanel buttonPanel = new JPanel(new GridLayout(
            ROWS_IN_BUTTON_PANEL_GRID, COLUMNS_IN_BUTTON_PANEL_GRID));

    //Add to button panel
    buttonPanel.add(this.resetButton);
    buttonPanel.add(this.enterButton);

    //Grid layout
    this.setLayout(new GridLayout(0, 2, 5, 0));

    //Add to layout
    this.add(this.key);
    this.add(this.value);
    this.add(this.keyText);
    this.add(this.valueText);
    this.add(this.resetButton);
    this.add(this.enterButton);
    this.add(this.recallButton);
    this.add(this.testButton);

    //observers
    this.resetButton.addActionListener(this);
    this.enterButton.addActionListener(this);
    this.key.addActionListener(this);
    this.value.addActionListener(this);
    this.testButton.addActionListener(this);

    //Pack up
    this.pack();
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);
}

/**
 * Register argument as observer/listener of this.
 *
 * @param controller
 *            controller to register
 */
@Override
public void registerObserver(PasswordManagerController controller) {
    this.controller = controller;
}

/**
 * Updates key display based on String provided as argument.
 *
 * @param key
 *            new value of input display
 */
@Override
public void updateKeyDisplay(String key) {
    this.key.setText(key);
}

/**
 * Updates value display based on String provided as argument.
 *
 * @param value
 *            new value of output display
 */
@Override
public void updateValueDisplay(String value) {
    this.value.setText(value);
}

@Override
public void actionPerformed(ActionEvent event) {

    //Wait cursor
    this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

    //What button was pressed
    Object source = event.getSource();
    if (source == this.resetButton) {
        this.controller.processResetEvent();
    } else if (source == this.enterButton) {
        this.controller.processEnterEvent(this.key.getText(),
                this.value.getText());
    } else if (source == this.recallButton) {
        this.controller.processRecallEvent();
    } else if (source == this.testButton) {
        //Creates new JFrame window
        JFrame test = new JFrame();
        //Reads in store names
        SimpleReader in = new SimpleReader1L("data/store.txt");
        //Counts how many buttons to create
        int passwordCount = 0;
        while (!in.atEOS()) {
            System.out.println(in.nextLine());
            passwordCount++;
        }
        /*
         * Previous operation went to the end of the file. We have to read
         * in the file again.
         */
        SimpleReader in2 = new SimpleReader1L("data/store.txt");
        //Layout gets set.
        test.setLayout(new FlowLayout());
        //Creation of an array of JButtons
        JButton[] storeButtons = new JButton[passwordCount];
        for (int i = 0; i < passwordCount; i++) {
            storeButtons[i] = new JButton(in2.nextLine());
            storeButtons[i].addActionListener(this);
            test.add(storeButtons[i]);
        }
        //Creates an array of Strings for the passwords
        String[] passwordString = new String[passwordCount];
        SimpleReader in3 = new SimpleReader1L("data/password.txt");
        for (int i = 0; i < passwordCount; i++) {
            passwordString[i] = in3.nextLine();
        }

        Object sourceFrame = event.getSource();
        /*
         * I'm just trying to get this to work with one of my buttons. I
         * will use a for loop to cover all the buttons later.
         */
        if (sourceFrame.equals(passwordString[0])) {
            JOptionPane.showMessageDialog(test, "HEY");
        }
        test.pack();
        test.setVisible(true);
        in.close();
        in2.close();
        in3.close();
    }

    //Cursor normal again
    this.setCursor(Cursor.getDefaultCursor());
}

}
frillybob
  • 600
  • 2
  • 12
  • 26
  • `storeButtons[i].addActionListener(this);` `this` is the first frame, not the second frame, so will not work – Viet Aug 12 '16 at 02:14
  • What are the `JButton`s supposed to do? It seems like you are adding a `ActionListener` of `this` which doesn't do anything when the source is equal to any of the `storeButtons`. – Arthur Aug 12 '16 at 02:41
  • @Jerry06 If I try adding 'test' in front of 'storeButtons[i].addActionListener(this)' I get that storeButtons cannot be resolved to a class or field. If I try to replace this with 'test' I get The method addActionListener(ActionListener) in the type AbstractButton is not applicable for the arguments . – frillybob Aug 12 '16 at 02:55
  • @Arthur The JButtons are supposed to be read in from an array of strings. The buttons do show up and look as expected I just can't get any response from them. – frillybob Aug 12 '16 at 02:56
  • 1
    1) See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) 2) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). – Andrew Thompson Aug 12 '16 at 03:31
  • 1
    *"What I need some.."* ..question, given this is a Q&A site. What is your question? – Andrew Thompson Aug 12 '16 at 03:32
  • Issues: 1) Why are you re-reading the file? Why not simply read it once and be done with it? 2) Your GUI shouldn't be making multiple JFrames, but rather of one single main application (the JFrame) and sub windows or view (possibly JDialogs). 3) You're making a huge god-class here, and that's part of the reason your running into trouble. As has been suggested, refactor and subdivide this code into classes, each with its own main responsibility. – Hovercraft Full Of Eels Aug 12 '16 at 04:00

2 Answers2

1

All of the storeButtons have an ActionListener of this. So whenever they are clicked it will run actionPerformed(). But you have if statements to check that the source of the ActionEvent is either resetButton, enterButton, recallButton, and testButton. Meaning that when the source is one of the JButtons from storeButtons, it won't do anything.

Try adding an anonymous class to the storeButtons instead and see what happens.

storeButtons[i].addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Store button " + i + " was pressed.");
    }
});
Arthur
  • 1,246
  • 1
  • 15
  • 19
  • The i has a notice that `Cannot refer to the non-final local variable storeButtons defined in an enclosing scope` I don't want it to be final as it modifies each time through the loop. – frillybob Aug 12 '16 at 03:16
  • @frillybob [making a array final doesn't stop you from editing it](http://stackoverflow.com/questions/10339930/final-array-in-java). I also was only using the anonymous class as an example you can use `this` as long as you make the `storeButtons` referenceable from there. – Arthur Aug 12 '16 at 03:34
1

You should seperate your code into new class JFrame2 for readability and maintenance: The JFrame2 like this:

public JFrame2 extends JFrame implements ActionListener{

    String[] passwordString;
    JButton[] storeButtons;

    public JFrame2(){
          //Reads in store names
        SimpleReader in = new SimpleReader1L("data/store.txt");
        //Counts how many buttons to create
        int passwordCount = 0;
        while (!in.atEOS()) {
            System.out.println(in.nextLine());
            passwordCount++;
        }
        /*
         * Previous operation went to the end of the file. We have to read
         * in the file again.
         */
        SimpleReader in2 = new SimpleReader1L("data/store.txt");
        //Layout gets set.
        this.setLayout(new FlowLayout());
        //Creation of an array of JButtons
        storeButtons = new JButton[passwordCount];
        for (int i = 0; i < passwordCount; i++) {
            storeButtons[i] = new JButton(in2.nextLine());
            storeButtons[i].addActionListener(this);
            this.add(storeButtons[i]);
        }
        //Creates an array of Strings for the passwords
        passwordString = new String[passwordCount];
        SimpleReader in3 = new SimpleReader1L("data/password.txt");
        for (int i = 0; i < passwordCount; i++) {
            passwordString[i] = in3.nextLine();
        }


        this.pack();
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
          JButton button = (JButton)event.getSource();//the button you are clicking
        /*
         * I'm just trying to get this to work with one of my buttons. I
         * will use a for loop to cover all the buttons later.
         */
        if (button.getText().equals(passwordString[0])) {
            //JOptionPane.showMessageDialog(test, "HEY");
        }
    }
}
Viet
  • 3,349
  • 1
  • 16
  • 35