1

I want a JFrame application with 2 buttons (eventually more) that I can use to switch between multiple repeating actions, ofr simplicity I'm just using a console print for now, though it will probably be calling a method instead later. Here is the framework for the JFrame:

public class DayNight extends JFrame implements ActionListener{

    //JFrame entities
    private JPanel animationPanel;
    private JButton button;
    private JButton button2;


    public static void main(String[] args) {
        DayNight frame = new DayNight();
        frame.setSize(2000, 1300);
        frame.setLocation(1000,350);
        frame.createGUI();
        frame.setVisible(true);
        frame.setTitle("Day/Night Cycle, Rogier");
    }

   private void createGUI() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container window = getContentPane();
    window.setLayout(new FlowLayout() );
    animationPanel = new JPanel();
    animationPanel.setPreferredSize(new Dimension(2000, 900));
    animationPanel.setBackground(Color.black);
    window.add(animationPanel);

    button = new JButton("choice1");
    button.setFont(new Font("Arial", Font.PLAIN, 50));
    window.add(button);
    button.setActionCommand("choice1");
    button.addActionListener(this);

    button2 = new JButton("choice2");
    button2.setFont(new Font("Arial", Font.PLAIN, 50));
    window.add(button2);
    button2.setActionCommand("choice2");
    button2.addActionListener(this);
   }
}

I've tried the following:

public void actionPerformed(ActionEvent event) {
    String command = event.getActionCommand();
    while ("Stop"!=(command)){
        command = event.getActionCommand();
        try{
            Thread.sleep(500);
            if ("choice1".equals(command)){
                System.out.println("choice1");
            }
            else if("choice2".equals(command)){
                System.out.println("choice2");
            }
            else{
                System.out.println("no choice");
            }
        }   
        catch(InterruptedException ex){
            Thread.currentThread().interrupt();
        }

    }
}

But after I click a button it keeps stuck on that print and I can't even interact with the buttons anymore. Am I missing something or do I need a completely different structure? I've examined a lot of different programs but they are too complicated for me to understand, reading the concurrency in swing also didn't clear it up for me.

Edit: There is no "stop" command yet because I don't need it for now.

RnRoger
  • 682
  • 1
  • 9
  • 33

1 Answers1

1

There are many things wrong with your code.

It starts with wrong comparison of strings ( see here ).

But your actual problem: you are sleeping the event dispatcher thread ( see there )

So your idea of sleeping with an event listener is simply the wrong approach. You can't do it this way. You have to re-think your approach there.

And the real answer here is: you are lacking basic knowledge of Java. Consider learning such basic things first before further overburdening yourself if Swing UI coding.

Your requirement seems to be: after that button was hit - and a certain amount of time passed you want to print something on the console. You can do that like:

public void actionPerformed(ActionEvent event) {
   String command = event.getActionCommand();
   command = event.getActionCommand();
   Runnable printChoice = new Runnable() {
     @Override
     public void run() {
      try{
        Thread.sleep(500);
        if ("choice1".equals(command)){
            System.out.println("choice1");
        }
        else if("choice2".equals(command)){
            System.out.println("choice2");
        }
        else{
            System.out.println("no choice");
        }
      }   
      catch(InterruptedException ex){
        Thread.currentThread().interrupt();
      }
    });
    new Thread(printChoice).start();
}

The above:

  • creates a Runnable that simply waits to then print something
  • uses a new Thread (not the event dispatcher thread) to do that

I didn't run this through the compiler - it is meant as "pseudo code" to give you some ideas how to solve your problem.

But further thinking about this - I think this is going in the wrong direction. You don't want that anything is waiting when you develop a reasonable UI application.

In other words: you think of:

  • button A is clicked - some code starts "looping"
  • when the user makes another choice, that "looping" code notices that and does something

Wrong approach. Instead work along these lines:

  • user clicks a button, and maybe that enables other UI components
  • user does something with those other UI components - triggering other actions

Example: changing radiobuttons causes events to be fired. You should not have a loop that regularly keeps checking those buttons. Instead you define a clear flow of actions/events the user has to follow in order to trigger a certain action.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Read the section from the Swing tutorial on [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) to understand why you don't want to invoke Thread.sleep() from code invoked within a listener. The tutorial has all Swing basics. – camickr Sep 13 '17 at 14:55
  • I'll continue to work on my basic Java, but I have to meet my assignment deadlines too. Do you have an example of a program or the name of an approach that fits my goal, which I can inspect and rewrite my program with? – RnRoger Sep 13 '17 at 15:00
  • Start with the link that @camickr gave in his comment - respectively by reading the links I gave to you. – GhostCat Sep 13 '17 at 15:02
  • I read all the links and the concurrency in swing, and I understand more about how the EDT and etc work, I just don't have an idea of how to get started. – RnRoger Sep 14 '17 at 11:20
  • "Your requirement seems to be: after that button was hit - and a certain amount of time passed you want to print something on the console." I want to keep printing the matching word *until* I press the other button, at which' point it will repeatedly print the other word. Is this what you mean and wrote in pseudo or does this only print it once? (before I remake my code with a misunderstanding) In short: Does it run once after the button was clicked or does it repeatedly keep checking the current command? – RnRoger Sep 14 '17 at 11:47
  • There is no loop in my code - I wasnt exactly sure how to do that. You would need to **access** the corresponding UI component from within that potential loop. – GhostCat Sep 14 '17 at 12:21
  • I was already able to just print something when pressing a button. I need to to enable a process. I don't exactly get what you mean by "You would need to access the corresponding UI component from within that potential loop". How can I have a loop running while still having a responsive GUI? – RnRoger Sep 14 '17 at 12:30
  • We have to be careful to not get into more-questions in comments bingo. So - see my latest updates. If you then have a *new* question, please consider writing a really new answer for that. This site is not meant as free tutor service were people spend considerable time *working* with you to solve your problem. (in that sense: my normal consulting fee is like 1 upvote for 5 minutes, and I think I almost spend half an hour thinking about your stuff ;-) – GhostCat Sep 14 '17 at 13:48