swing - Can't get String from GUI thread to 'logic' thread in java -
i've been writing program searches through list of numbers find ones add other number. no problems there, algorhythm is, while not efficient, functional.
right list of numbers has taken text file, i've been trying make user can copy-paste list textarea, hit enter, , have program send string normal (non-gui) thread.
to followed this example (the top answer). i'm using key event instead of button press, , string instead of linked list, other that, pretty similar.
code create , run textdemo (yes, adapted tutorial program):
/*copy paste text in window */ public static string copypaste() throws exception{ string text = ""; final textdemo demo = new textdemo(); javax.swing.swingutilities.invokelater(new runnable() { public void run() { demo.createandshowgui(); } }); synchronized(demo.text){ while(demo.text.equals("")){ //if window unused demo.text.wait(); } text = demo.text; } return text; }
textdemo (minus disclaimer, please don't alert oracle :) ):
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class textdemo extends jpanel implements keylistener{ protected jtextarea textarea; private final static string newline = "\n"; public string text = ""; boolean used = false; public textdemo() { super(new gridbaglayout()); textarea = new jtextarea(100, 30); textarea.addkeylistener(this); textarea.seteditable(true); jscrollpane scrollpane = new jscrollpane(textarea); //add components panel. gridbagconstraints c = new gridbagconstraints(); c.gridwidth = gridbagconstraints.remainder; c.fill = gridbagconstraints.both; c.weightx = 1.0; c.weighty = 1.0; add(scrollpane, c); } public void keypressed(keyevent e) { // listen key pressed , check against "enter" // read out of our textarea control , print screen4 if (e.getkeycode() == e.vk_enter) { synchronized(text){ text = textarea.gettext(); system.out.println("text entered."); text.notify(); } } } public void keyreleased(keyevent e) { // listen key pressed , check against "enter" // read out of our textarea control , print screen4 if (e.getkeycode() == e.vk_enter) { //do nothing } } public void keytyped(keyevent e) { // listen key pressed , check against "enter" // read out of our textarea control , print screen4 if (e.getkeycode() == e.vk_enter) { //do nothing } } /** * create gui , show it. thread safety, * method should invoked * event dispatch thread. */ public static void createandshowgui() { //create , set window. jframe frame = new jframe("textdemo"); frame.setdefaultcloseoperation(jframe.exit_on_close); //add contents window. frame.add(new textdemo()); //display window. frame.pack(); frame.setvisible(true); } public static void main(string[] args) { //schedule job event dispatch thread: //creating , showing application's gui. javax.swing.swingutilities.invokelater(new runnable() { public void run() { createandshowgui(); } }); } }
when run code, seems work, until hit enter , program crashes. error code (i'm including first 5 lines, full version here: http://img.photobucket.com/albums/v242/chaosguide/illegalmonitorstateexception.png):
exception in thread "awt-eventque-0" java.lang.illegalmonitorstateexception @ java.lang.object.notify(native method) @ textdemo.keypressed(textdemo.java:72) @ java.awt.component.processkeyevent(component.java:6463) @ javax.swing.jcomponent.processkeyevent(jcomponent.java:2829) @ java.awt.component.processevent(component.java:6282)
this first time i've done touches on threading, don't understand i'm doing wrong.
any appreciated.
both threads use demo.text
lock, , call wait()
, notify()
on object communicate, inside synchronized block on demo.text
, correct. you're reassigning new value variable before calling notify()
. so, in effect, call notify()
on object don't own lock:
synchronized(text) { // block synchronized on empty string object text = textarea.gettext(); // assign string text system.out.println("text entered."); text.notify(); // call notify on other string object, don't own lock, because synchronized on empty string }
rule of thumb : when variable used lock, should final, avoid kind of bug. moreover, using empty string lock really, bad idea. you'd better create dedicated object that:
private final object lock = new object();
but best thing forget wait()
, notify()
, low-level, , use higher-level abstraction java.util.concurrent package semaphore example.
or better: instead of having main thread wait event dispatch thread, you'd better start background thread, or rather use swingworker, execute lengthy operation.
Comments
Post a Comment