0

So I am writing a program which has several layers of menus using a JFrame with JButtons but once the user clicks a button that button ends up stuck as selected and I cannot update it. Any help please?

Code:

// Libraries
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class test extends JComponent implements ActionListener {
    // Globals
    static String buttonPressed = "";
    // Dimensions
    static final int WIDTH = 765;
    static final int HEIGHT = 765;
    static final int BUTTON_WIDTH = 220;
    static final int BUTTON_HEIGHT = 105;
    // General file path
    static final String filePath = "<General path for my images>";
    // GUI construction
    static JFrame mainFrame;
    static JButton tl;

    public static void main(String[] args) throws IOException {
        GUI menuCall = new GUI();
        menuCall.menu();
    }

    public void menu() throws IOException {
        // Main JFrame construction
        mainFrame = new JFrame("Racing Game");
        mainFrame.setSize(WIDTH, HEIGHT);
        mainFrame.setLayout(null);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.setResizable(false);

        // Sets background of main JFrame to menu background - calls ImagePanel class
        BufferedImage backBuff = ImageIO.read(new File((filePath + "\\Sprites\\Menu.png")));
        mainFrame.setContentPane(new ImagePanel(backBuff));

        // Menu JButton setup
        tl = new JButton("Free Drive");
        tl.setBounds(112, 112, BUTTON_WIDTH, BUTTON_HEIGHT);
        tl.setForeground(Color.white);
        tl.setBackground(Color.decode("0x04092E"));
        tl.setFocusPainted(false);
        tl.addActionListener(this);
        mainFrame.add(tl);

        //...

        // Makes the main JFrame visible
        mainFrame.setVisible(true);
    }
    public static void freeDrive() {
        try {
            Thread.sleep(1000000); // Just doing this to show that it stays selected, there is other code here
        } catch (Exception e) {}
    }
    // Overrides
    @Override
    public void actionPerformed(ActionEvent e) {
        freeDrive();
    }
}

I've tried removing the JButton, setting it as not selected and updating a variable to allow the override subroutine to end (this I thought would definitely work but for some reason the variable isn't saved when the code returns to the main subroutine - any advice on how to fix this would also be great).

5
  • 1
    You are calling Thread.sleep() on the Event Dispatch Thread (EDT). That's a no-no. Try using Swing timer instead.
    – Abra
    Commented Aug 20 at 2:17
  • 1
    Swing is single-threaded. Any long-running code, like your example sleep call, holds up that thread, preventing events from being processed, including all painting and all handling of user input. If you have a long-running operation, do it in a different thread, or use the SwingWorker class, so the event dispatch thread isn’t stuck waiting for that operation to finish.
    – VGR
    Commented Aug 20 at 4:00
  • 1
    many (most) Swing components have the following in their documentation: "Warning: Swing is not thread safe. For more information see Swing's Threading Policy." - Important to read, it states, for example: "As all events are delivered on the event dispatching thread, care must be taken in event processing. ... While the event dispatching thread is blocked the application is completely unresponsive to user input. ..."
    – user85421
    Commented Aug 20 at 6:31
  • @Abra, thanks for the comment on the "staging ground". I've never really understood the purpose or even understood how a question gets assigned to the staging ground. After all this question does attempt to include an MRE, so it is far better than many questions. And the code presented does give people enough information to state the cause of the problem and provide direction for a solution.
    – camickr
    Commented Aug 20 at 13:48
  • In addition to above comments read the Swing tutorial on Concurrency for more information. Use a Swing Worker may be a solution.
    – camickr
    Commented Aug 20 at 13:50

1 Answer 1

0

When an action is performed, freeDrive is being called, which will sleep for 1000000. In the meantime your UI is unresponsive. This is actually expected. If you want a long-lasting job to be executed, then create another thread for it and issue that other thread, so your UI will still be responsive. Read more about this here: http://www.cs.fsu.edu/~jtbauer/cis3931/tutorial/ui/swing/threads.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.