Results 1 to 7 of 7
  1. #1
    ScottVal is offline Member
    Join Date
    Jan 2009
    Posts
    44
    Rep Power
    0

    Default Using a Thread to process KeyEvents and MouseEvents

    Hello-
    I had the idea of using a Thread to process KeyEvents or MouseEvents. I can start the thread, and it runs, but for some reason the while() loop in the thread just keeps going even after I interrupt the thread.

    I doubt that you want to look at all of my code, here I am showing my run() method in the thread:

    public void run()
    {
    center = person.getPanelCenter();
    boolean running = true;

    while(running) {
    processEvent();
    try {
    sleep(1000);
    } catch(Exception e) {
    running = false;
    }
    }
    }

    In case you're wondering, the getPanelCenter method at the top is simply getting a Point2D which is the center of a JPanel. Also, the sleep(1000) may look like a large value (a full second), and initially I had it set smaller (200), but I increased it the 1000 to try to get a better idea of what was going on. The funny thing here is that the thread does not seem to "sleep" at all, and just keeps running, too fast, even after interrupted.

    The processEvent method processes the Event, which just consists of doing some drawing on the JPanel based on the Event, which can be a KeyEvent or a MouseEvent. I synchronized all methods which are contained in a different thread.

    You may be wondering where the Event comes from. The idea here is that the thread is constructed after a key press or mouse press, and the Event does not change. After a key release or mouse release, the thread is interrupted. Another key press or mouse press results in another thread being constructed, and the first thread should be garbage collected, since it is no longer referenced. But it is not garbage collected and just hangs around.

    -Scott

  2. #2
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Using a Thread to process KeyEvents and MouseEvents

    You need to provide a complete, compilable, executable, but short example that demonstrates the problem you are having. I had
    to modify the above code and it works as you wish. So something else must be going on.

    One possibility is that the java optimizer is hoisting the boolean out of the while loop. Unlikely since the boolean is referenced within the
    loop itself. But when using variables in this way where their state may be used in another thread, it is usually best to declare them
    volatile to "tell" the compiler that the value might change elsewhere. So change

    Java Code:
    boolean running = true;
    //  to
    volatile boolean running = true;

    Regards,
    Jim
    Last edited by jim829; 04-02-2017 at 04:03 PM.
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  3. #3
    ScottVal is offline Member
    Join Date
    Jan 2009
    Posts
    44
    Rep Power
    0

    Default Re: Using a Thread to process KeyEvents and MouseEvents

    You may have noticed that my code above had all leading whitespace removed. What is the proper way to insert code into a reply?

  4. #4
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,001
    Rep Power
    33

    Default Re: Using a Thread to process KeyEvents and MouseEvents

    Wrap your code with code tags:

    [code]
    **YOUR CODE GOES HERE**
    [/code]

    to get highlighting and preserve formatting.
    If you don't understand my response, don't ignore it, ask a question.

  5. #5
    ScottVal is offline Member
    Join Date
    Jan 2009
    Posts
    44
    Rep Power
    0

    Default Re: Using a Thread to process KeyEvents and MouseEvents

    Thanks for the responses.

    I have created a complete class which demonstrates the issue, as simply as possible.

    Java Code:
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    
    
    public class ThreadTestForumPost extends JFrame {
    
        ThreadTestForumPost() {
            super("ThreadTestForumPost");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            Dimension size = new Dimension(1800, 1000);
            setSize(size);
    
            Insets i = getInsets();
            MyKeyListener k = new MyKeyListener(size.width - i.left - i.right, size.height - i.top - i.bottom);
            setContentPane(k);
    
            addKeyListener(k);
            setVisible(true);
            repaint();
        }
        
        public static void main(String[] args) {
            new ThreadTestForumPost();
        }
    }
    
    class MyKeyListener extends JPanel implements KeyListener {
        volatile int x = 500;
        volatile int y = 500;
        
        MyThread thread;
        
        MyKeyListener(int width, int height)
        {
            super();
            setSize(width, height);
            setVisible(true);
        }
        
        public void paint(Graphics graphics)
        {
            super.paint(graphics);
            Graphics2D g = (Graphics2D) graphics;
            g.setPaint(Color.BLACK);
            Rectangle2D r = new Rectangle2D.Double(x, y, 30, 30);
            g.fill(r);
        }
        
        public void keyPressed(KeyEvent e) {
            thread = new MyThread(this);
            thread.start();
        }
        
        public void keyReleased(KeyEvent e) {
            thread.interrupt();
        }
        
        public void keyTyped(KeyEvent e) {
        }
    }
    
    class MyThread extends Thread
    {
        MyKeyListener panel;
        
        MyThread(MyKeyListener k) {
            panel = k;
        }
        
        public void run()
        {
            while(true) {
                panel.x++;
                panel.repaint();
                try {
                    sleep(500);
                } catch(Exception e) {
                    return;
                }
            }
        }
    }
    The idea is that a small black rectangle is shown in the JFrame. If a key is pressed, a thread is started which starts moving the rectangle toward the right (by incrementing x). If the key is released, the thread is interrupted, so the rectangle should stop moving.

    I see the following behavior, which puzzles me:
    1. The thread does not really sleep for 500 milliseconds. The rectangle moves quickly across the screen, indicating that the time between increments of "x" is much less than 500 milliseconds.
    2. The thread does not really stop when I return from the run() method. The thread just keeps running, and the rectangle just keeps scooting along, even though I attempted to return from run().

  6. #6
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,001
    Rep Power
    33

    Default Re: Using a Thread to process KeyEvents and MouseEvents

    Try doing some debugging to see what the code is doing. Add some print statements to show where the execution is going. For example:
    in the keyPressed method
    in the run() method
    in the catch block
    If you don't understand my response, don't ignore it, ask a question.

  7. #7
    ScottVal is offline Member
    Join Date
    Jan 2009
    Posts
    44
    Rep Power
    0

    Default Re: Using a Thread to process KeyEvents and MouseEvents

    Hey, I figured it out. As it turns out, I was assuming that KeyListener.keyPressed() would be invoked just one time when a key was pressed. However, I was mistaken! You know what happens when you assume.

    In fact the keyPressed() method is invoked over and over again when the user is holding down a key! Like bullets out of a machine gun mounted on the latest tactical aircraft. Look out!

    So each time one of these bullets was fired at me, what did I do? I started a new thread. We're talking threads galore! Massive amounts of threads. Obviously it wasn't pretty.

    So I'm using a Boolean flag to keep track of the KeyListener state, and simply starting one thread when the keyPresses start coming in, and I reset the flag when I get a keyReleased().

    Thanks for your help.

Similar Threads

  1. JScrollPane keyevents
    By Alkor in forum AWT / Swing
    Replies: 4
    Last Post: 03-27-2012, 03:09 AM
  2. Thread supposed to block keyevents
    By Fecoooo in forum Threads and Synchronization
    Replies: 6
    Last Post: 03-11-2012, 03:51 PM
  3. i m so confuse in mutex process and thread..
    By vivek6569 in forum New To Java
    Replies: 1
    Last Post: 05-03-2011, 07:51 AM
  4. Thread, determine process status
    By newbiejava in forum New To Java
    Replies: 10
    Last Post: 08-22-2010, 04:51 PM
  5. Which thread do the process first if we use multithreading ?
    By cinjojose in forum Threads and Synchronization
    Replies: 4
    Last Post: 10-12-2009, 11:23 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •