0

I set JTextField "rfid" to setEnabled(false) in MainGUI class and created method setRfidEnabled to be able to enable textfield from another class called CardLayout. When I try to call it from CardLayout by button event listener it does nothing, I mean to textfield, because System.out.print("LOL"); works fine. MainGUI contains JFrame and by button calls another JFrame in CardLayout class.

When I initialize MainGUI class, it has Thread[Thread-2,6,main], but when I call CardLayout it becomes Thread[AWT-EventQueue-0,6,main], same as CardLayout itself. I tried to make "rfid" volatile, no success.

---Edited code---

MainGUI:

public class MainGUI {
    JTextField rfid;
    JButton button;
    final JFrame frame;
    final JPanel pane;
    LayoutChanger layout = new LayoutChanger();
    public MainGUI() {
        rfid = new JTextField("", 10);
        button = new JButton("CardLayoutSwitch");
        frame = new JFrame("Main GUI Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout(5,5));
        pane = new JPanel(new GridLayout(5, 5));
        frame.add(pane,BorderLayout.CENTER);
        pane.add(rfid);
        pane.add(button);
        rfid.setEnabled(false);
        button.setEnabled(true);
        frame.pack();
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed (ActionEvent e){
                layout.changeLayout(1);
            }
        });
    }
    public void setRfidEnabled() {
                System.out.println("LOL");
                rfid.setEnabled(true);
                button.setEnabled(false);
    }
}

LayoutChanger class:

public class LayoutChanger {
    public static void main(String[] args) {
    MainGUI gui = new MainGUI();
    }

    public void changeLayout(int i){
        if (i == 1) {
            CardLayout card = new CardLayout();
        }
    }
}

CardLayout class:

public class CardLayout {
    JFrame frame;
    JButton manual;
    final JPanel pane;
    MainGUI gui = new MainGUI();
  public CardLayout() {
            manual = new JButton("UID MANUAL");
            frame = new JFrame("Card Scan Panel");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.setLayout(new BorderLayout(5, 5));
            pane = new JPanel(new BorderLayout(5, 5));
            manual.setPreferredSize(new Dimension(50, 25));
            frame.add(pane, BorderLayout.CENTER);
            pane.add(manual);
            frame.pack();
            frame.setVisible(true);
            frame.setLocationRelativeTo(null);
            manual.addActionListener(new ActionListener() {
             @Override
                public void actionPerformed (ActionEvent e){
                    gui.setRfidEnabled();
              }
          });
        }
}
Stab Ones
  • 1
  • 2
  • 1
    Please provide a runnable example (aka [mcve]) so we can also reproduce your "wrong" behavior and debug your code. Please don't post your current code, rather try to create a small runnable example, that demonstrates your problem. As I see, you use threads to modify Swing widgets. It's a bad idea. All modifications must be performed in Swing-Thread. For more info please read about [concurrency in Swing](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html). – Sergiy Medvynskyy May 13 '19 at 13:42
  • @SergiyMedvynskyy edited to provide a runnable example. Here you are. – Stab Ones May 13 '19 at 14:04
  • 1
    Have you read about [concurrency in Swing](https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html)? When I see `Thread.sleep(2000)` in Swing code, I get the red alert. – Sergiy Medvynskyy May 13 '19 at 14:17
  • @SergiyMedvynskyy Im sorry, I removed it already, trying to do workerthread right now, still same, I can call it from main and it works, but if I try to call it from another JFrame it won't – Stab Ones May 13 '19 at 14:22
  • 1
    Why you use threads in your code? Are they necessary? When it's required to do something in a background thread, I use the `SwingWorker`. But in your case you IMHO don't need it. – Sergiy Medvynskyy May 13 '19 at 14:44
  • @SergiyMedvynskyy previous time, when I used ```null``` layout, I wasn't using threads, it still won't work, and I thought it might be because of threads. I tried ```SwingWorker```, same result – Stab Ones May 13 '19 at 14:52
  • 1
    Why do you use a separate thread to add an action listener? The action listeners should be added on the EDT. Also, when they get called because of an action event, that will happen on the EDT regardless of the thread you used to add the action listener. – matt May 13 '19 at 14:58
  • @SergiyMedvynskyy I wonder what is solution for this. Tried everything I found to cause one ```JFrame``` to affect another... – Stab Ones May 13 '19 at 14:59
  • 1
    `MainGUI gui = new MainGUI();` creates a new main gui, then when you call `gui.setRfidEnabled();` it is on the new one, not the existing one. – matt May 13 '19 at 14:59
  • 1
    You keep creating new objects instead of modifying the ones you have. – matt May 13 '19 at 15:01
  • @matt well, I see your idea, how to modify the ones I have? – Stab Ones May 13 '19 at 15:13

1 Answers1

1

As stated in the comments above by @matt

Every time you click on manual button, you're creating a new MainGUI().

You need to create a single instance, either in your constructor or in the ActionListener and ask if you already have an instance of it (i.e. a Singleton) and use it.

If you decide to use the first one, declare gui as a global variable:

MainGUI gui = new MainGUI();

And on your ActionListener have it changed as:

@Override
public void actionPerformed(ActionEvent e) {
    System.out.println(currentThread());
    gui.setRfidEnabled();
    //frame.dispose();
}

Then you have a single instance of it.

Also as stated by @Sergiy you don't really need all those threads

Here are some examples on how to use ActionListeners:

As you can see in all the above examples, none of them required another Thread to handle the actions, the one that uses a thread is only for performing the animation and not to react to user clicks.

Recommended tutorial: How to use Actions

Frakcool
  • 10,915
  • 9
  • 50
  • 89
  • If I declare ```MainGUI gui = new MainGUI()``` as global variable, I get ```Exception in thread "main" java.lang.StackOverflowError``` – Stab Ones May 13 '19 at 17:03
  • You need to create a new program, post it as an [mcve], removing all those threads and keep it as simple as possible, then we can provide better answers. Go and edit your question with that MCVE that demonstrates your issue. If you have questions, you can ask me here. But take as a basis all the examples in the links in this answer, those are MCVEs as you can copy-paste them into your IDE and see the same UI with same behavior without modifying anything. – Frakcool May 13 '19 at 17:23
  • You was right, that useless threads ruined everything, I posted MCVE, now main issue that ```manual``` button click brings new entire ```MainGUI``` window and the old one with enabled button remains, how can I just update existing ```MainGUI``` window? – Stab Ones May 13 '19 at 18:07
  • Read the first part of this answer. That's still not a [mcve] and please indent your code properly. And now you're able to call the second `JFrame`, then this question is solved. If you still need help post another question but be sure to have a MCVE ready, as I said I can guide you in specific question about how to create one, and I already explained what we need, 1 single class, new program, not your current one. – Frakcool May 13 '19 at 18:08