简体   繁体   English

线程通信:如何发出信号,表明已单击某个键? java.lang.IllegalMonitorStateException

[英]Thread communication: How to signal that a key was clicked? java.lang.IllegalMonitorStateException

i have a simple JavaFX stage with a TextField. 我有一个带有TextField的简单JavaFX阶段。 What i want to do is: when user inserts letters into the TextField, i want to print "now" (just to look if it works). 我想做的是:当用户在TextField中插入字母时,我想打印“现在”(只是看它是否有效)。 Im using a Thread because later i want to scan a dictonary to see, if the letters the user entered are part of words from the dictionary. 我使用线程是因为稍后我想扫描字典,以查看用户输入的字母是否是词典中单词的一部分。

But i get: java.lang.IllegalMonitorStateException 但是我得到了:java.lang.IllegalMonitorStateException

Any ideas? 有任何想法吗? I don't seem to understand the whole concept of Condition.await and Multithreading.. 我似乎不太了解Condition.await和Multithreading的整个概念。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DictionaryThreading extends Application {


private static Lock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();

public static void main(String[] args) {
    launch();
}

private static class ScanWords implements Runnable{

    @Override
    public void run() {
        lock.lock();
        try{    
            while(true){
                this.wait();
                System.out.println("clicked");
            }
        } catch (Exception e){
            e.printStackTrace();
        } finally{
            lock.unlock();
        }   
    }

}

@Override
public void start(Stage primaryStage) throws Exception {
    StackPane pane = new StackPane();

    new ScanWords().run();
    TextField tf = new TextField("Please enter a word");
    tf.setOnKeyPressed(e -> {});
    pane.getChildren().add(tf);

    Scene scene = new Scene(pane);
    primaryStage.setScene(scene);
    primaryStage.show();

}

}

There is no need to create a thread that does nothing other than wait for user events. 无需创建一个除了等待用户事件外不执行其他操作的线程。 The JavaFX framework already provides this for you (it is one of the fundamental pieces of functionality of any UI toolkit). JavaFX框架已经为您提供了此功能(它是任何 UI工具箱的基本功能之一)。 All you need to do to respond to changes in the text in a text field is register a change listener with the text field's text property: 要响应文本字段中的文本更改,您需要做的就是在文本字段的text属性中注册一个更改侦听器:

public void start(Stage primaryStage) throws Exception {
    StackPane pane = new StackPane();

    TextField tf = new TextField("Please enter a word");
    tf.textProperty().addListener((obs, oldText, newText) -> {
        System.out.println("text changed");
    });
    pane.getChildren().add(tf);

    Scene scene = new Scene(pane);
    primaryStage.setScene(scene);
    primaryStage.show();

}

If the thing you need to do in response to the text changing takes a long time, then you should launch that process in a background thread in the listener on the text field. 如果需要花费很长时间来响应文本更改,那么您应该在文本字段的侦听器中的后台线程中启动该过程。 If you are searching something large, you probably want to cancel any existing search, so that you don't end up with a large number of searches all running concurrently. 如果要搜索的内容很大,则可能要取消任何现有的搜索,以免最终并没有同时运行大量搜索。 The JavaFX Service class provides the functionality you need for this: JavaFX Service提供了为此所需的功能:

public class SearchService extends Service<List<String>> {

    // modify and access only on FX Application Thread:
    private String searchString ;

    @Override
    protected Task<List<String>> createTask() {
        final String s = searchString ;
        return new Task<List<String>>() {
            @Override
            protected List<String> call() throws Exception {
                List<String> matches = new ArrayList<>();
                // do search for strings matching s
                // be sure to check isCancelled() regularly
                return matches ;
            }
        };
    }

    public String getSearchString() {
        checkThread();
        return searchString ;
    }

    public void setSearchString(String searchString) {
        checkThread();
        this.searchString = searchString ;
    }

    private void checkThread() {
        if (! Platform.isFxApplicationThread()) {
            throw new IllegalStateException("Not on FX Application Thread");
        }
    }
}

Then you can do 那你可以做

public void start(Stage primaryStage) throws Exception {
    StackPane pane = new StackPane();

    SearchService searchService = new SearchService();

    searchService.setOnSucceeded(e -> {
        List<String> matches = searchService.getValue();
        // do whatever you need with search results...
        // this is called on FX application thread
    });

    TextField tf = new TextField("Please enter a word");
    tf.textProperty().addListener((obs, oldText, newText) -> {
        searchService.cancel();
        searchService.setSearchText(newText);
        searchService.restart();
    });
    pane.getChildren().add(tf);

    Scene scene = new Scene(pane);
    primaryStage.setScene(scene);
    primaryStage.show();

}

I don't use JavaFX, but I think you need to use EventListener . 我不使用JavaFX,但我认为您需要使用EventListener Try to use TextListener or InputMethodListener . 尝试使用TextListenerInputMethodListener For example: 例如:

StackPane pane = new StackPane();

TextField tf = new TextField("Please enter a word");

tf.addTextListener(e -> System.out.println("Pushed"));

pane.getChildren().add(tf);

Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();

wait method should be executed within synchronized block: wait方法应在synchronized块内执行:

    try{    
        while(true){
            synchronized(this){
                this.wait();
                System.out.println("clicked");
            }
        }
    } catch (Exception e){
        e.printStackTrace();
    } finally{
        lock.unlock();
    }  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 线程“main”java.lang.IllegalMonitorStateException中的异常 - Exception in thread “main” java.lang.IllegalMonitorStateException 调用signal()时抛出java.lang.IllegalMonitorStateException - java.lang.IllegalMonitorStateException trhown when calling signal() 超时时发生java.lang.IllegalMonitorStateException - java.lang.IllegalMonitorStateException on timeout Android:java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定 - Android: java.lang.IllegalMonitorStateException: object not locked by thread before wait() java.lang.IllegalMonitorStateException: 当前线程不是锁的所有者 - java.lang.IllegalMonitorStateException: Current thread is not owner of the lock java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定 - java.lang.IllegalMonitorStateException: object not locked by thread before wait() Android java.lang.IllegalMonitorStateException:对象在wait()之前未被线程锁定 - Android java.lang.IllegalMonitorStateException: object not locked by thread before wait() java.lang.IllegalMonitorStateException:在等待()之前对象没有被线程锁定? - java.lang.IllegalMonitorStateException: object not locked by thread before wait()? 如何解决线程“ TimerQueue”中的异常之类的错误?Java中线程“ AWT-EventQueue-0”中的异常?java.lang.IllegalMonitorStateException? - How to solve error like Exception in thread “TimerQueue” Exception in thread “AWT-EventQueue-0” java.lang.IllegalMonitorStateException in java? java.lang.IllegalMonitorStateException (java selenium) - java.lang.IllegalMonitorStateException (java selenium)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM