sikuli-driver team mailing list archive
-
sikuli-driver team
-
Mailing list archive
-
Message #38171
Re: [Question #293847]: How to gracefully interrupt running script when using SwingWorker and JFrame?
Question #293847 on Sikuli changed:
https://answers.launchpad.net/sikuli/+question/293847
Description changed to:
*************** a revised version of the provided sample code by RaiMan
*************
*** comments:
- with such a solution it is not possible to kill the running SwingWorker thread (the python interpreter simply ignores the bgThread.cancel(True) request. (the problems with the wait() are fixed in the next 1.1.1 - see revised sample)
- to use a stop button, to end a script only works, if the script does not make continuous use of the mouse (you will not get a chance to click the button). a good alternative is a stop hotkey (see revised sample)
- to add a global kill option for the SwingWorker thread, you either have to run the script via subprocess module or implement something like that hack:
https://web.archive.org/web/20130503082442/http://mail.python.org/pipermail/python-list/2004-May/281943.html
- another option is to make the script aware of a stop request (as done in the revised sample below)
- the triggered script should not run into an infinite loop or wait, since this can only be stopped by aborting the wrapping script or even the IDE
- the script should be tested before adding it into such a wrapper, because most errors simply do not produce any helpful output (an option is to make the script run standalone and then use runScript() in the wrapper)
- print statements should only have one parameter, otherwise printouts from the different thread get mangled (use the Python string formatting ""%() to assure that - see sample)
from javax.swing import JButton, JFrame, JTextField, JPanel
from java.lang import Runnable, InterruptedException
from java.util.concurrent import ExecutionException
from javax.swing import SwingWorker, SwingUtilities
from java.lang import *
from java.awt.event import ActionListener, WindowAdapter
import threading
class BgTask(SwingWorker):
def __init__(self, gui):
self.gui = gui
SwingWorker.__init__(self)
self.stopRun = False
def shouldStop(self, event=None):
self.stopRun = True
def someInit(self):
print "**** started"
Env.addHotkey("x", KeyModifier.CTRL+KeyModifier.ALT, self.shouldStop)
def doInBackground(self):
self.someInit()
for i in range(10):
if self.stopRun: break
# for 1.1.x before 2016-05-21
#App.pause(1)
wait(1)
self.showState("%d ** running - State:" % (i))
def showState(self, msg):
if self.stopRun:
print "%s - shouldStop reveived" % (msg)
else:
print "%s - %s" % (msg, self.getState())
def done(self):
self.gui.hasEnded()
print "**** ended"
class Example:
def __init__(self):
frame = JFrame("Automated Testing")
frame.setSize(200, 150)
frame.addWindowListener(Adapter())
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
frame.setAlwaysOnTop(True)
pnl=JPanel()
frame.add(pnl)
self.startBtn = JButton('Start Automation',
actionPerformed=self.startRun)
self.stopBtn = JButton('Stop',
actionPerformed=self.stopRun)
pnl.add(self.startBtn)
pnl.add(self.stopBtn)
self.stopBtn.enabled = False
frame.pack()
frame.setVisible(True)
def startRun(self,event):
self._setButtonStates(True)
self.bgTask = BgTask(self)
self.bgTask.execute()
def stopRun(self, event):
#self.bgTask.cancel(True) # generally no effect
self.bgTask.shouldStop()
self.bgTask = None
def _setButtonStates(self, activated):
self.stopBtn.enabled = activated
self.startBtn.enabled = not activated
def hasEnded(self):
self._setButtonStates(False)
class Adapter(WindowAdapter):
def windowClosing(self, event):
endCondition.acquire()
endCondition.notifyAll()
endCondition.release()
class Runnable(Runnable):
def __init__(self, runFunction):
self._runFunction = runFunction
def run(self):
self._runFunction()
SwingUtilities.invokeLater(Runnable(Example))
endCondition = threading.Condition()
endCondition.acquire()
endCondition.wait()
endCondition.release()
----------------------------------------------- end of revised sample
--------------------------------------
Thanks to the help provided here I've created a JFrame to allow me more
advanced user interaction and a custom control GUI. I only have one
issue at this point, once the items runing in doInBackground (BgTask
SwingWorker), you can not gracefully stop stop the script. I get the
following error: java.lang.InterruptedException: sleep interrupted which
I assume happens due to me trying to interrupt the 'wait' command.
I tried to add a try/except to catch the exception, but it doesn't seem
to work. Also when I try to use the CTRL+ALT+c hot key it stops the
program and makes my JFrame and also the IDE unresponsive.
I'm using Windows 7 64bit, I'm using SikulixIDE 1.1.0
CODE:
from javax.swing import JButton, JFrame, JTextField, JPanel
from java.lang import Runnable, InterruptedException
from java.util.concurrent import ExecutionException
from javax.swing import SwingWorker, SwingUtilities
from java.lang import *
from java.awt.event import ActionListener, WindowAdapter
import threading
class BgTask(SwingWorker):
def __init__(self, gui):
self.gui = gui
SwingWorker.__init__(self)
def doInBackground(self):
try:
click("1463505602802.png") #Random icon on my desktop that is visible
wait(5)
click("1463514867811.png") #Random icon on my desktop that is visible
except InterruptedException:
print "***Automation Stuff Should End***"
def done(self):
try:
self.get()
except ExecutionException, e:
raise SystemExit, e.getCause()
# print e.getCause()
class Example:
def _setButtonStates(self, started):
self.stopBtn.enabled = started
self.startBtn.enabled = not started
def stopSomething(self, event):
self.bgTask.cancel(True)
self.bgTask = None
self._setButtonStates(started=False)
def doSomething(self,event):
self.bgTask = BgTask(self)
self.bgTask.execute()
self._setButtonStates(started=True)
def __init__(self):
frame = JFrame("Gamma Automated Testing")
frame.setSize(200, 150)
frame.addWindowListener(Adapter())
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
pnl=JPanel()
frame.add(pnl)
self.textfield1 = JTextField('', 15)
pnl.add(self.textfield1)
self.textfield2 = JTextField('', 15)
pnl.add(self.textfield2)
self.startBtn = JButton('Start Automation', actionPerformed=self.doSomething)
self.stopBtn = JButton('Stop', actionPerformed=self.stopSomething)
pnl.add(self.startBtn)
pnl.add(self.stopBtn)
self.stopBtn.enabled = False
frame.pack()
frame.setVisible(True)
endCondition = threading.Condition()
class Adapter(WindowAdapter):
def windowClosing(self, event):
endCondition.acquire()
endCondition.notifyAll()
endCondition.release()
class Runnable(Runnable):
def __init__(self, runFunction):
self._runFunction = runFunction
def run(self):
self._runFunction()
if __name__ == '__main__':
SwingUtilities.invokeLater(Runnable(Example))
endCondition.acquire()
# Example()
endCondition.wait()
endCondition.release()
--
You received this question notification because your team Sikuli Drivers
is an answer contact for Sikuli.