传递对象引用和并发/ JavaFX

时间:2018-02-28 16:53:14

标签: java javafx concurrency

我正在使用JavaFX创建一个窗口,使用面向对象的方法,允许使用相同的基本框架创建不同类型的窗口。这些窗口将显示html内容。

我在尝试添加观察者时遇到了并发问题。

窗口:

public Window(String linkName, String fName, String wName, int width, int height, GuiObserver o) throws IOException {
    wApp = new WindowApp();
    wApp.setObserver(o);

    new Thread(new Runnable() {
        public void run() {
            wApp.launch(WindowApp.class,linkName,fName,wName,""+width,""+height);
            /*try {
                wApp.launch(WindowApp.class,linkName,fName,wName,""+width,""+height);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/
        }
    }).start();
}

这将创建窗口并设置观察者,但将启动放入新线程。我可以确认添加了观察者,但无法通知观察者。这是WindowApp类:

/**
 * Instantiate the class with an html file
 * THIS MUST NOT TAKE ANY PARAMETERS
 */
public WindowApp() throws IOException {}

@Override
public void start(Stage s) throws Exception {

    this.stage = s;

    //get the parameters
    List<String> params = getParameters().getRaw();
    String linkName = params.get(0);
    updateHtmlFromFile(new File(params.get(1)));
    windowName = params.get(2);
    windowWidth = Integer.parseInt(params.get(3));
    windowHeight = Integer.parseInt(params.get(4));

    //create the window
    stage.setWidth(windowWidth);
    stage.setHeight(windowHeight);
    Scene scene = new Scene(new Group());


    browser = new WebView();
    webEngine = browser.getEngine();
    webEngine.setJavaScriptEnabled(true);

    //add the link which will bind Java and Javascript functionality
    Class jC = Class.forName(linkName);
    Constructor jCon = jC.getConstructor(browser.getClass(),webEngine.getClass(),stage.getClass());
    javascriptLink = (JavascriptLink) jCon.newInstance(browser,webEngine,stage);
    javascriptLink.setObserver(gObserver);

    //javascriptLink = new JavascriptLink(browser,webEngine,stage);

    ScrollPane scrollPane = new ScrollPane();
    scrollPane.setContent(browser);

    webEngine.getLoadWorker().stateProperty()
        .addListener(new ChangeListener<State>() {
          @Override
          public void changed(ObservableValue ov, State oldState, State newState) {

            if (newState == Worker.State.SUCCEEDED) {
              stage.setTitle(windowName);
            }

          }
        });
    webEngine.load(htmlUrl);

    scene.setRoot(scrollPane);

    stage.setScene(scene);
    stage.show();

}
    /**
     * Add an observer to the javascript Link
     * @param o
     */
    public void setObserver(GuiObserver o) {
        gObserver = o;
    }

此对象还有一个“Javascript链接”,它在启动后与HTML文档交互:

package gui;

import java.io.FileNotFoundException;

import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class MainWindowJSLink extends JavascriptLink {

    private GuiObserver gObserver;

    /**
     * This will be called by WindowApp when appropriate, and does not need to be called by a person
     * @param b
     * @param we
     * @param st
     * @throws FileNotFoundException
     */
    public MainWindowJSLink(WebView b, WebEngine we, Stage st) throws FileNotFoundException {
        super(b, we, st);
    }

    @Override
    public void eventTriggered(String eventName) {
        System.out.println("Event triggered -> "+eventName);

        switch (eventName) {
            case "codeEditorContentsChanged":
                handleCodeEditorContentsChanged();
                break;
        }

        //notify observers if necessary
        this.triggerObserver(eventName, null);
    }

    /**
     * Handle the event that the contents of the code editor have changed
     * This will probably setup a timer to wait a few seconds until the user has stopped typing,
     *      then send the contents to the syntax highlighter and get the result back  
     */
    private void handleCodeEditorContentsChanged() {
        //System.out.println(getJSCodeEditorContents());
    }

    /**
     * Get the raw contents of the code editor (unedited and not stripped of html entities)
     * @return
     */
    public String getJSCodeEditorContents() {
        String contents = (String) super.webEngine.executeScript("getCodeEditorContents()");

        return contents;
    }

    /**
     * Set the contents of the code editor
     * @param contents String
     * NOTE: 
     */
    public void setJSCodeEditorContents(String contents) {
        super.webEngine.executeScript("setCodeEditorContents(`"+contents+"`)");
    }

    //observer observable stuff
    @Override
    public void setObserver(GuiObserver o) {
        gObserver = o;
        gObserver.setJS(this);
        System.out.println("MainWindow -> observer set");
    }

    @Override
    public void triggerObserver(String s, Object o) {
        gObserver.trigger(s,o);
    }

    @Override
    /**
     * Handle information sent from the 
     */
    public void send(String s, Object o) {
        //handle information sent to this object
}
    }

不幸的是,gObserver.trigger没有执行。有趣的是,如果在调用触发器之前放入System.exit(0),程序将退出。但是,如果我在调用之后(或在相应的方法中)将它放入,则不是。

有人可以提供有关如何解决此并发问题的任何建议吗?如果您需要更多信息,请告诉我,我会提供。

0 个答案:

没有答案