I want to stop my recursive timer. Using tick as the argument to after_cancel doesn't work. Using "after#2" does, if I happen to press Return at the right time.
What am I missing here please?
from Tkinter import *
root = Tk()
root.title("Tick")
root.geometry("320x400")
def tick():
print ("tick!")
print root.after(1000, tick)
def key_pressed(event):
if event.keysym == "Return":
root.after_cancel(tick)
root.bind("<Key>", key_pressed)
root.after(1000, tick)
mainloop()
You need to pass the after reference. Here's a quick edit to show that.
from tkinter import *
root = Tk()
root.title("Tick")
root.geometry("320x400")
AFTER = None
def tick():
print ("tick!")
global AFTER
AFTER = root.after(1000, tick)
def key_pressed(event):
if event.keysym == "Return":
root.after_cancel(AFTER)
root.bind("<Key>", key_pressed)
root.after(1000, tick)
mainloop()
Related
I am trying to create a tkinter page that shows the time and it should be constantly updated. I have tried:
from tkinter.font import *
import time
def SetTime():
global time_date
time_date = time.strftime("%H:%M")
InfoTime.set(time_date)
Main = Tk()
Main.geometry("1600x1200")
Main.title("Time")
FontStyle = Font(family = "Times New Roman", size = 48)
InfoTime = StringVar()
TitleText = Label(Main,textvariable = InfoTime,font = FontStyle).pack()
while True:
SetTime()
However, running the
While True: line and running
SetTime()
constantly is for some reason preventing the tkinter page (Main) from opening. This has been a problem for a lot of my tkinter projects.
Please note, I am running python 3.7.2 in IDLE.
Thanks.
This should do it:
from tkinter import *
from tkinter.font import *
import time
Main = Tk()
Main.geometry("1600x1200")
Main.title("Time")
FontStyle = Font(family = "Times New Roman", size = 48)
TitleText = Label(Main, font = FontStyle)
TitleText.pack()
time_date1 = ''
def SetTime():
global time_date1
global TitleText
# Gets current time
time_date2 = time.strftime("%H:%M")
# If time has changed, update it
if time_date2 != time_date1:
time_date1 = time_date2
TitleText.config(text=time_date2)
# Repeats function every 200 milliseconds
TitleText.after(200, SetTime)
SetTime()
Main.mainloop()
The comments pretty much explain everything. I also cleaned up and reformatted your code to make it look nicer.
I'm trying to get the variable that's entered in an entry widget on the Return key pressed event, but struggling a bit. What I have tried has always produced a blank result.
This code may look messy and hap-hazard, but it's only going to be a template that I'll be using on a current project!
I've tried that many things to get it to work, I can't remember what I have tried!
from collections import OrderedDict
try:
import tkinter as tk
except:
import Tkinter as tk
root = tk.Tk()
labelLIST = OrderedDict([
('Temp ID', 'tempID'),
('PO Number', "poNumber"),
('Reference', "reference"),
('Cut/Sample Date', "csDate"),
('Cut Number', "cut")
])
i = 0
e_loops = len(labelLIST)
print (e_loops)
def bval1(event=None):
for i in range(e_loops):
print (entries[i].get())
entries[0].delete(0, tk.END)
entries[0].insert(0, 'DISABLED')
entries[0].configure(state='disabled')
def bval2():
entries[0].configure(state='normal')
for i in range(e_loops):
entries[i].delete(0, tk.END)
entries[0].focus()
def onClick(event):
ent = event.widget # event.widget is the widget that called the event
print(ent.cget("text")) # Print the text for the selected button
event.widget.tk_focusNext().focus()
def enterEV(event):
# print(entries[].get())
event.widget.tk_focusNext().focus()
entries = []
for key, value in labelLIST.items():
label = tk.Label(root, text=key)
label.grid(row=i, column=0, sticky="ew", padx=1, pady=1)
entry = tk.Entry(root, width=10)
entry.grid(row=i, column=1, sticky="ew", padx=5, pady=5)
if value == "cut":
entry.bind('<Return>', bval1)
else:
# entry.bind('<Return>', enterEV)
entry.bind('<Return>', onClick)
entries.append(entry)
i = i+1
button = tk.Button(root, text="Submit", command=bval1)
button.grid(row=0, column=2, columnspan=9, sticky="ew")
button = tk.Button(root, text="Clear", command=bval2)
button.grid(row=1, column=2, columnspan=9, sticky="ew")
entries[0].focus()
tk.mainloop()
When enter/return is pressed, I want the value that is the entry box to be printed to terminal via the onClick event. But the output is always empty.
def onClick(event):
ent = event.widget # event.widget is the widget that called the event
print(ent.cget("text")) # Print the text for the selected button
event.widget.tk_focusNext().focus()
You don't use the text attribute to get the value in an Entry widget. Using cget("text") returns the value for the textvariable attribute. Since you haven't set that attribute, it will always be the empty string.
Instead, you need to call the get method:
print(ent.get())
I am using "Inotify" to logs event when a file or folder is created in a directory ( tmp here) . The example here does the job in as serial process. Meaning, All file creation are treated one after the other, in a sequential way.
import logging
import inotify.adapters
_DEFAULT_LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
_LOGGER = logging.getLogger(__name__)
def _configure_logging():
_LOGGER.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
formatter = logging.Formatter(_DEFAULT_LOG_FORMAT)
ch.setFormatter(formatter)
_LOGGER.addHandler(ch)
def _main():
i = inotify.adapters.Inotify()
i.add_watch(b'/tmp')
try:
for event in i.event_gen():
if event is not None:
(header, type_names, watch_path, filename) = event
_LOGGER.info("WD=(%d) MASK=(%d) COOKIE=(%d) LEN=(%d) MASK->NAMES=%s "
"WATCH-PATH=[%s] FILENAME=[%s]",
header.wd, header.mask, header.cookie, header.len, type_names,
watch_path.decode('utf-8'), filename.decode('utf-8'))
finally:
i.remove_watch(b'/tmp')
if __name__ == '__main__':
_configure_logging()
_main()
I would like to introduce parallelization of the events notification in case of several files are uploaded by importing threading, should I add a threading as loop ?
Second concern, I am not sure where it would make sens to put the thread function.
The below scripts handles multiples events in case of multiples sessions. So in my case, this is enough. I Added the multiprocessing option instead of threading. I found multiprocessing faster than threading.
import logging
import threading
import inotify.adapters
import multiprocessing
_DEFAULT_LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
_LOGGER = logging.getLogger(__name__)
def _configure_logging():
_LOGGER.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
formatter = logging.Formatter(_DEFAULT_LOG_FORMAT)
ch.setFormatter(formatter)
_LOGGER.addHandler(ch)
def PopUpMessage (event):
if event is not None:
(header, type_names, watch_path, filename) = event
_LOGGER.info("WD=(%d) MASK=(%d) COOKIE=(%d) LEN=(%d) MASK->NAMES=%s "
"WATCH-PATH=[%s] FILENAME=[%s]",
header.wd, header.mask, header.cookie, header.len, type_names,
watch_path.decode('utf-8'), filename.decode('utf-8'))
def My_main(count):
i = inotify.adapters.Inotify()
DirWatcher=i.add_watch(b'/PARA')
try:
while True:
for event in i.event_gen():
m = multiprocessing.Process(target=PopUpMessage, args=(event,))
m.start()
finally:
i.remove_watch(b'/PARA')
if __name__ == '__main__':
_configure_logging()
N = multiprocessing.Process(target=My_main)
N.start()
I am wondering where are output functions of NAO behavior boxes usually defined.
I simply failed to find any related documentation in API. There are some you can find indeed, but not for output functions.
Take Speech Reco box for example, I can find definition of function "WordRecognized" on online API, but not the "wordRecognized" (case sensitive) and the "onNothing". Intuition is that they define them as helpers in the script of the box (which you can get by double-clicking on the box), but I just failed to find any relevant implementation of those either in the script.
Anyone had this before and know the solution? I really appreciate any feedback since I want to inspect how they are defined.
Code for Speech Reco is as below, and this situation happens for some other boxes too:
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self, False)
try:
self.asr = ALProxy("ALSpeechRecognition")
except Exception as e:
self.asr = None
self.logger.error(e)
self.memory = ALProxy("ALMemory")
def onLoad(self):
from threading import Lock
self.bIsRunning = False
self.mutex = Lock()
self.hasPushed = False
self.hasSubscribed = False
self.BIND_PYTHON(self.getName(), "onWordRecognized")
def onUnload(self):
from threading import Lock
self.mutex.acquire()
try:
if (self.bIsRunning):
if (self.hasSubscribed):
self.memory.unsubscribeToEvent("WordRecognized", self.getName())
if (self.hasPushed and self.asr):
self.asr.popContexts()
except RuntimeError, e:
self.mutex.release()
raise e
self.bIsRunning = False;
self.mutex.release()
def onInput_onStart(self):
from threading import Lock
self.mutex.acquire()
if(self.bIsRunning):
self.mutex.release()
return
self.bIsRunning = True
try:
if self.asr:
self.asr.setVisualExpression(self.getParameter("Visual expression"))
self.asr.pushContexts()
self.hasPushed = True
if self.asr:
self.asr.setVocabulary( self.getParameter("Word list").split(';'), self.getParameter("Enable word spotting") )
self.memory.subscribeToEvent("WordRecognized", self.getName(), "onWordRecognized")
self.hasSubscribed = True
except RuntimeError, e:
self.mutex.release()
self.onUnload()
raise e
self.mutex.release()
def onInput_onStop(self):
if( self.bIsRunning ):
self.onUnload()
self.onStopped()
def onWordRecognized(self, key, value, message):
if(len(value) > 1 and value[1] >= self.getParameter("Confidence threshold (%)")/100.):
self.wordRecognized(value[0]) #~ activate output of the box
else:
self.onNothing()
Those methods are defined when you create or edit a box input or output. See this piece of documentation.
If you give the input the name "onMyTruc", then the method onInput_onMyTruc(self) will be called when the input is triggered.
If you give the name "output_value" to some output, it will create a callable method name: self.output_value()
In your example, wordRecognized and onNothing are the name of the output of the SpeechReco box.
I am simply trying to move an image from left to right using the keyboard keys. I tried making a class called movableImage that inherits from Image. I think this is where I did something wrong, specifically the init function. When I run the code below I am getting AttributeError: 'function' object has no attribute 'widget' on line 16. What am I doing wrong here?
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.input.motionevent import MotionEvent
from kivy.core.window import Window
class character(Widget):
pass
class moveableImage(Image):
def __init__(self, **kwargs):
super(moveableImage, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard
if self._keyboard.widget:
# If it exists, this widget is a VKeyboard object which you can use
# to change the keyboard layout.
pass
self._keyboard.bind(on_key_down=self._on_keyboard_down)
def on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == 'left':
print keycode #move littleguy to the left
elif keycode[1] == 'right':
print keycode #move littleguy to the right
return True
littleguy = moveableImage(source='selectionscreen/littleguy.zip', anim_available=True, anim_delay=.15)
class gameApp(App):
def build(self):
m = character()
m.add_widget(littleguy)
return m
if __name__ == '__main__':
gameApp().run()
I should also add that I HAVE read the Kivy keyboardlistener example and I am still stuck.
Here's a working example of what you're trying to do, just run it and use the right / left arrow keys to move it right / left:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.core.window import Window
class character(Widget):
pass
class MoveableImage(Image):
def __init__(self, **kwargs):
super(MoveableImage, self).__init__(**kwargs)
self._keyboard = Window.request_keyboard(None, self)
if not self._keyboard:
return
self._keyboard.bind(on_key_down=self.on_keyboard_down)
def on_keyboard_down(self, keyboard, keycode, text, modifiers):
if keycode[1] == 'left':
self.x -= 10
elif keycode[1] == 'right':
self.x += 10
else:
return False
return True
class gameApp(App):
def build(self):
wimg = MoveableImage(source='tools/theming/defaulttheme/slider_cursor.png')
m = character()
m.add_widget(wimg)
return m
if __name__ == '__main__':
gameApp().run()
The problem you ran into, is that request_keyboard is a function, and needs to be called that way. You can also remove the if self._keyboard.widget: part.