Smooth output from root.bind key - python

If you use Root.bind to get a key input and add a function it will execute, it will execute it, make a small pause, and then keep rapidly executing it but how to do it without it making a pause, might work if there is a way to detect if it was clicked (not released) and then start executing it and when the button is lifted it will stop executing it? (not using another import, it dont work idk why)
from tkinter import *
A = 0
def fun(event):
global A
if event.keysym == 'space':
A += 1
print(A)
root = Tk()
root.bind("<Key>", fun)
root.mainloop()

I think I understand the question. You want to press and hold the space bar and have something executing while the bar is held down and stop once you release the key.
The <Key> binding detects key down and then key down for every repeat.
The <KeyRelease> binding detects a key release for each key repeat and when the key is actually released.
In the code below fun_on executes after each Key event and fun_off after each KeyRelease event. The on_after function in fun_off is cancelled if fun_on runs before the time expires.
import tkinter as tk
A = 0
cycle = False
def fun_off( event ):
global timer
def on_after():
""" This executes 1 ms after it's triggered.
If a <Key> event is detected during the millisecond it's cancelled.
See fun_on """
global A, cycle
A = 0
cycle = False
timer = root.after( 1, on_after ) # More milliseconds may be
# needed for some hardware
def do_cycle(): # This executes as long as cycle is True
global A
if cycle:
A += 1
print( A )
root.after( 10, do_cycle ) # Set ms delay as required.
def fun_on(event):
""" Cancels the after ID from fun_off.
My auto repeat executes key down 0.1 ms after key up.
This will cancel the after function unless the key is actually released"""
global cycle
root.after_cancel( timer )
if not cycle:
cycle = True
do_cycle()
root = tk.Tk()
timer = root.after( 0, lambda: None ) # Makes timer a validafter id.
root.bind( "<KeyRelease-space>", fun_off )
root.bind( "<Key-space>", fun_on )
root.mainloop()

Related

Stop button for breaking while loop within Ipywidgets ecosystem

Let's assume the following problem: we have an Ipywidget button and a progress bar. On clicking the button, a function work() is executed, which merely fills the progress bar until completing it, then reverses the process and empties it out. As it stands, such a function runs continuously. The following code snippet provides the corresponding MWE:
# importing packages.
from IPython.display import display
import ipywidgets as widgets
import time
import functools
# setting 'progress', 'start_button' and 'Hbox' variables.
progress = widgets.FloatProgress(value=0.0, min=0.0, max=1.0)
start_button = widgets.Button(description="start fill")
Hbox = widgets.HBox(children=[start_button, progress])
# defining 'on_button_clicked_start()' function; executes 'work()' function.
def on_button_clicked_start(b, start_button, progress):
work(progress)
# call to 'on_button_clicked_start()' function when clicking the button.
start_button.on_click(functools.partial(on_button_clicked_start, start_button=start_button, progress=progress))
# defining 'work()' function.
def work(progress):
total = 100
i = 0
# while roop for continuous run.
while True:
# while loop for filling the progress bar.
while progress.value < 1.0:
time.sleep(0.01)
i += 1
progress.value = float(i)/total
# while loop for emptying the progress bar.
while progress.value > 0.0:
time.sleep(0.01)
i -= 1
progress.value = float(i)/total
# display statement.
display(Hbox)
The aim is to include "Stop" and "Resume" buttons, so that the while loops are broken whenever the first is clicked, and the execution is resumed when pressing the second one. Can this be done without employing threading, multiprocessing or asynchronicity?
Here's an answer I derived by means of the threading package and based on the background-working-widget example given in https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html. It's certainly not optimized, and probably not good-practice-compliant. Anybody coming up with a better answer is welcomed to provide it.
# importing packages.
import threading
from IPython.display import display
import ipywidgets as widgets
import time
# defining progress bar 'progress', start, stop and resume buttons
# 'start_button', 'stop_button' and 'resume_button', and horizontal
# box 'Hbox'.
progress = widgets.FloatProgress(value=0.0, min=0.0, max=1.0)
start_button = widgets.Button(description="start fill")
stop_button = widgets.Button(description="stop fill/empty")
resume_button = widgets.Button(description="resume fill/empty")
Hbox = widgets.HBox(children=[start_button, stop_button, resume_button, progress])
# defining boolean flags 'pause' and 'resume'.
pause = False
restart = False
# defining 'on_button_clicked_start()' function.
def on_button_clicked_start(b):
# setting global variables.
global pause
global thread
global restart
# conditinoal for checking whether the thread is alive;
# if it isn't, then start it.
if not thread.is_alive():
thread.start()
# else, pause and set 'restart' to True for setting
# progress bar values to 0.
else:
pause = True
restart = True
time.sleep(0.1)
restart = False
# conditional for changing boolean flag 'pause'.
if pause:
pause = not pause
# defining 'on_button_clicked_stop()' function.
def on_button_clicked_stop(b):
# defining global variables.
global pause
# conditional for changing boolean flag 'pause'.
if not pause:
pause = not pause
# defining 'on_button_clicked_resume()' function.
def on_button_clicked_resume(b):
# defining global variables.
global pause
global restart
# conditional for changing boolean flags 'pause' and 'restart'
# if necessary.
if pause:
if restart:
restart = False
pause = not pause
# call to 'on_button_clicked_start()' function when clicking the button.
start_button.on_click(on_button_clicked_start)
# call to 'on_button_clicked_stop()' function when clicking the button.
stop_button.on_click(on_button_clicked_stop)
# call to 'on_button_clicked_resume()' function when clicking the button.
resume_button.on_click(on_button_clicked_resume)
# defining the 'work()' function.
def work(progress):
# setting global variables.
global pause
i = 0
i_m1 = 0
# setting 'total' variable.
total = 100
# infinite loop.
while True:
# stop/resume conditional.
if not pause:
# filling the progress bar.
if (i == 0) or i > i_m1 and not pause:
time.sleep(0.1)
if i == i_m1:
pass
else:
i_m1 = i
i += 1
progress.value = float(i)/total
# emptying the progress bar.
if (i == 101) or i < i_m1 and not pause:
time.sleep(0.1)
if i == i_m1:
pass
else:
i_m1 = i
i -= 1
progress.value = float(i)/total
else:
if restart:
i = 0
i_m1 = 0
# setting the thread.
thread = threading.Thread(target=work, args=(progress,))
# displaying statement.
display(Hbox)
After trying using asynchronous, I run into too many problems. Much better approach is to use generator approach, also mentioned in documentation https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html
Here is the code I came up with
from functools import wraps
from IPython.core.display import display
import ipywidgets as widgets
def yield_for_change(widget, attribute):
def f(iterator):
#wraps(iterator)
def inner():
i = iterator()
def next_i(change):
try:
print([w.description for w in widget])
i.send(change)
except StopIteration as e:
for w in widget:
w.unobserve(next_i, attribute)
for w in widget:
w.on_click(next_i)
w.observe(next_i, attribute)
# start the generator
next(i)
return inner
return f
btn_true = widgets.Button(description="True",style={'button_color':'green'} )
btn_false = widgets.Button(description="False",style={'button_color':'red'})
btn_list = [btn_true, btn_false]
buttons = widgets.HBox(btn_list)
value_loop = widgets.Label()
out = widgets.Output()
#yield_for_change(btn_list, 'description')
def f():
for i in range(10):
print('did work %s'%i)
x = yield
print('generator function continued with value %s'%x)
f()
display(widgets.VBox([buttons, out]))

Python Code that returns true while key is pressed down false if release?

I need a code in python that returns an if statement to be true if a key is pressed and held down and false if it is released. I would like this code to be able to be executed whenever the key is pressed and held down.
On some systems keyboard can repeate sending key event when it is pressed so with pynput you would need only this (for key 'a')
from pynput.keyboard import Listener, KeyCode
def get_pressed(event):
#print('pressed:', event)
if event == KeyCode.from_char('a'):
print("hold pressed: a")
with Listener(on_press=get_pressed) as listener:
listener.join()
But sometimes repeating doesn't work or it need long time to repeate key and they you can use global variable for key to keep True/False
from pynput.keyboard import Listener, KeyCode
import time
# --- functions ---
def get_pressed(event):
global key_a # inform function to use external/global variable instead of local one
if event == KeyCode.from_char('a'):
key_a = True
def get_released(event):
global key_a
if event == KeyCode.from_char('a'):
key_a = False
# --- main --
key_a = False # default value at start
listener = Listener(on_press=get_pressed, on_release=get_released)
listener.start() # start thread with listener
while True:
if key_a:
print('hold pressed: a')
time.sleep(.1) # slow down loop to use less CPU
listener.stop() # stop thread with listener
listener.join() # wait till thread ends work

Python Tkinter While Thread

Well i am a bit of newb at python, and i am getting hard to make a thread in Tkinter , as you all know using while in Tkinter makes it Not Responding and the script still running.
def scheduler():
def wait():
schedule.run_pending()
time.sleep(1)
return
Hours = ScheduleTest()
if len(Hours) == 0:
print("You need to write Hours, Example: 13:30,20:07")
if len(Hours) > 0:
print("Scheduled: ", str(Hours))
if len(Hours) == 1:
schedule.every().day.at(Hours[0]).do(Jumper)
print("Will jump 1 time")
elif len(Hours) == 2:
schedule.every().day.at(Hours[0]).do(Jumper)
schedule.every().day.at(Hours[1]).do(Jumper)
print("Will jump 2 times")
elif len(Hours) == 3:
schedule.every().day.at(Hours[0]).do(Jumper)
schedule.every().day.at(Hours[1]).do(Jumper)
schedule.every().day.at(Hours[2]).do(Jumper)
print("Will jump 3 times")
while True:
t = threading.Thread(target=wait)
t.start()
return
scheduler()
i have tried to do something like this but it still makes tkinter not responding
Thanks in advance.
When to use the after method; faking while without threading
As mentioned in a comment, In far most cases, you do not need threading to run a "fake" while loop. You can use the after() method to schedule your actions, using tkinter's mainloop as a "coat rack" to schedule things, pretty much exactly like you would in a while loop.
This works in all situations where you can simply throw out commands with e.g. subprocess.Popen(), update widgets, show messages etc.
It does not work when the scheduled process takes a lot of time, running inside the mainloop. Therefore time.sleep() is a bummer; it will simply hold the mainloop.
How it works
Within that limitation however, you can run complicated tasks, schedule actions even set break (-equivalent) conditions.
Simply create a function, initiate it with window.after(0, <function>). Inside the function, (re-) schedule the function with window.after(<time_in_milliseconds>, <function>).
To apply a break- like condition, simply rout the process (inside the function) not to be scheduled again.
An example
This is best illustrated with a simplified example:
from tkinter import *
import time
class TestWhile:
def __init__(self):
self.window = Tk()
shape = Canvas(width=200, height=0).grid(column=0, row=0)
self.showtext = Label(text="Wait and see...")
self.showtext.grid(column=0, row=1)
fakebutton = Button(
text="Useless button"
)
fakebutton.grid(column=0, row=2)
# initiate fake while
self.window.after(0, self.fakewhile)
self.cycles = 0
self.window.minsize(width=200, height=50)
self.window.title("Test 123(4)")
self.window.mainloop()
def fakewhile(self):
# You can schedule anything in here
if self.cycles == 5:
self.showtext.configure(text="Five seconds passed")
elif self.cycles == 10:
self.showtext.configure(text="Ten seconds passed...")
elif self.cycles == 15:
self.showtext.configure(text="I quit...")
"""
If the fake while loop should only run a limited number of times,
add a counter
"""
self.cycles = self.cycles+1
"""
Since we do not use while, break will not work, but simply
"routing" the loop to not being scheduled is equivalent to "break":
"""
if self.cycles <= 15:
self.window.after(1000, self.fakewhile)
else:
# start over again
self.cycles = 0
self.window.after(1000, self.fakewhile)
# or: fakebreak, in that case, uncomment below and comment out the
# two lines above
# pass
TestWhile()
In the example above, we run a scheduled process for fifteen seconds. While the loop runs, several simple tasks are performed, in time, by the function fakewhile().
After these fivteen seconds, we can start over again or "break". Just uncomment the indicated section to see...

Function not calling and how to wait for click in tkinter loop

I've hit a dead end at the moment - firstly when you click one of the dynamic buttons, the function call is made, and it does return the name of the button clicked. However the fEndDay function it's supposed to call as well doesn't appear to run.
EDIT: The day is now running. Just relaunched Liclipse and it started working. No explanation. However, the button wait issue remains.
I'm also a little stuck at the moment. In essence I want:
While current day < total days....
Run a daily event, updating the screen objects.
Take a choice via button click.
Increase the current day.
However, the day loop stops the screen from displaying (i.e. processing loop). I guess if there's code that pushes the object display up and sits in an infinate loop, which is broken by the button click, that would do. Other ideas? Current code below.
#!/usr/bin/python
# Reminder to self - lots to add. Include a function to reset the text content
# and populate with day number, score summary etc as a template. We can then
# add to it.
#################### IMPORT MODULES WE NEED ############################
import time # For sleep delays
from random import randint # for random numbers
from _ast import While # while loops
import tkinter as Tkinter # this one handles windows and buttons etc
from tkinter import * # skip the tkinter prefix (constants etc)
# import tkmessagebox # Python 2 alternative!
from tkinter import messagebox as tkMessageBox # Python 3
import sys # for quit when added ie sys.exit()
from functools import partial # So we can create lists of buttons & commands
import time # threading support - check events while waiting
import concurrent.futures # threading - think i'll be needing all this
################## CREATE A NEW CLASS (CONTAINER) ############################
class CrazyCoder (Tkinter.Tk):
# When the class is created, the function fInitialise is run, below.
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.fInitialize() # State here any functions to run on creation
################################ FUNCTION ################################
# Set up variables etc...
def fInitialize(self):
########################### VARIABLES ###############################
# Overkill here probably but will revisit later! Listed / initialised
# here to simplify searching later on!
# Could pass most of theses but will keep it simple and update globally
# to start with
self.vDayNumber = 1 # What the current day is
self.vFinalDay = 10 # The last day of our game
self.vPlayerName = '' # To hold the players name
self.vGameName = '' # To hold the game name
self.vChoice = '' # To hold the user choices clicked
self.vRandom = 0 # To hold random numbers!
self.vGameplay = 0 # SCORES: Current gameplay score
self.vGraphics = 0 # SCORES: Current graphics score
self.vSound = 0 # SCORES: current sound score
self.vBugs = 0 # SCORES: current bug score'
self.vBackColor = 'grey' # The background colour of our app
self.vDynamic_Buttons = [] # To hold button objects each "screen"
self.vEntryBox = [] # To hold text entry box objects
self.vTextEntry = '' # Stores user text entry value temporarily
self.vAvailableButtons = [] # To hold a list of AVAILABLE buttons/event
########################## APP SETUP ################################
self.title('Crazy Coder') # set window title
self.geometry("500x500") # set screen size
self.configure(background=self.vBackColor) # set background colour
# Add a "Title box"
self.vTitle = Tkinter.Label(self,text='Crazy Coder')
self.vTitle.configure(background=self.vBackColor)
self.vTitle.pack(side=TOP,padx=10,pady=10)
# Add a picture box (gif supported)
self.vImage = PhotoImage(file="PUG.gif")
self.vPicture=Label(self,image=self.vImage)
self.vPicture.image=self.vImage
self.vPicture.pack()
# Add the main text box
self.vMessageText = '''
This is where your day number goes
Scores go here too
Event details go here too'''
self.vMessage = Tkinter.Label(self,text=self.vMessageText)
self.vMessage.configure(background=self.vBackColor)
self.vMessage.pack(side=TOP,padx=10,pady=10)
# While loop does not work - there is no concept of
# "display current buttons / screen and wait for click event"
#while self.vDayNumber <= self.vFinalDay:
self.vChoice = '' # Clear it ready to take a user choice each day
print('DEBUG: On Main screen, starting now')
self.vRandom = randint(1,100)
if self.vDayNumber == 1:
self.fWelcomeScreen() # Set up the welcome screen
elif self.vRandom >= 0:
self.fEvent1() # Kick off event 1
############################# FUNCTION #################################
# Sets the message on the main text box to whatever you put in brackets
def fSetText(self,TextMessage):
global vMessageText
self.vMessageText = TextMessage
self.vMessage['text'] = self.vMessageText # This updates the text box
############################# FUNCTION #################################
# Sets the image on the main picture box to whatever you put in brackets
def fSetImage(self,ImageName):
global vImage
self.vImage = PhotoImage(file=ImageName) # Example "PUG2.gif"
self.vPicture['image']=self.vImage # This updates the image box
############################# FUNCTION #################################
# Add a new Entry box to our screen. Supports multiple uses
def fAddEntryBox(self):
self.vNewBox = Entry(width=20)
self.vEntryBox.append(self.vNewBox)
self.vNewBox.pack(side=TOP,padx=10,pady=10)
self.vNewBox.focus()
############################# FUNCTION #################################
# Remove the Entry Boxes
def fDeleteEntryBoxes(self):
for each_box in self.vEntryBox:
each_box.destroy()
############################# FUNCTION #################################
# Read from the requested box number, cutting off the Enter at the end
def fReadEntryBox(self,BoxNumber): #BoxNumber 0 is the first box, 1 next
global vTextEntry
vTextEntry=self.vEntryBox[BoxNumber].get()
############################# FUNCTION #################################
# Handles the the day passing by
def fEndDay(self):
global vPlayerName, vDayNumber
self.vDayNumber = self.vDayNumber + 1
print("This print isn't running either!")
############################# FUNCTION #################################
# A simple step to take a choice from the user - used for button code below
def fMakeChoice(self,value):
global vChoice, vDayNumber
self.fEndDay()
self.vChoice = value
print('Just Clicked:',self.vChoice, "and it's day ", self.vDayNumber)
print('But fEndDay should have just run and increased it to 2!')
############################# FUNCTION #################################
# Add buttons to the screen, based on vAvailableButtons
def fAddButtons(self):
global vAvailableButtons # Shouldn't need this here but...
for each_button in self.vAvailableButtons:
# Important: the Lambda section takes the CURRENT value of the variable
# and stores is in the command string. Without it, all the buttons
# when clicked would do the same as the last button created! daft eh.
vNewButton = Tkinter.Button(self, text=each_button, command=lambda v=each_button: self.fMakeChoice(v))
self.vDynamic_Buttons.append(vNewButton)
vNewButton.pack(side= BOTTOM, padx = 10, pady = 10)
############################# FUNCTION #################################
# Clear the buttons out ie before drawing new ones
def fDeleteButtons(self):
for each_button in self.vDynamic_Buttons:
each_button.destroy()
############################# FUNCTION #################################
# Pop up message box
def fMessage(self,Message):
self.tkMessageBox.showinfo("News", Message)
#*********************************************************************#
#********************* EVENTS SECTION ***************************#
#*********************************************************************#
# We'll define a function here for each "daily event"
# The section will be responsible for:
# 1) Updating the screen image (if necessary)
# 2) Updating the text box content
# 3) Adding entry boxes and buttons as required
# 4) Ending the day (there will be one decision per day for now)
############################# EVENT #################################
# The welcome screen
def fWelcomeScreen(self):
global vAvailableButtons
self.vTextMessage = '''
Yawn. You wake up.
Whats your name?
'''
self.fSetText(self.vTextMessage)
time.sleep(1) # delays for 1 second
self.fAddEntryBox() # Add an entry box for a name
self.vAvailableButtons = ['Ok']
self.fAddButtons() # vChoice set on click, and day ended
############################# EVENT #################################
# A random event
def fEvent1(self):
global vAvailableButtons
self.vTextMessage = '''
This is an event. What will you do?
'''
self.fSetText(self.vTextMessage)
time.sleep(1) # delays for 1 second
self.vAvailableButtons = ['Ok']
self.fAddButtons() # vChoice set on click, and day ended
# Start the program
if __name__ == "__main__":
app = CrazyCoder(None)
app.mainloop()
The fact that you want to run some function once a day is no different than wanting an animation to run 30 frames per second. You effectively want an "animation" that runs 1 fpd (one frame per day).
The way to accomplish that is to create a function that should run once a day.
def do_once_a_day():
...
Next, create a function that will call that function once a day:
def call_daily(self):
self.do_once_a_day()
if self.vDayNumber <= self.vFinalDay:
root.after(1000*60*60*24, self.call_daily)
This will cause do_once_a_day to be called once every 24 hours. You can then do whatever you want inside that function.

globally capture, ignore and send keyevents with python xlib, recognize fake input

i want to implement key chording on a normal keyboard and i thought i use python xlib.
for this to work the program has to globally swallow all keyevents and only later allow them to go through.
my current test just grabs the "1" key. if this key is pressed it calls a handler which sends "x" to the focused window via xtest.fake_input. because im only grabbing the "1"-key, there shouldn't be a problem, right?
but somehow the handler gets called again, because "x" was pressed. in fact, the moment i type "1" the program is listening to all keys.
this could have something to do with calling
display.allow_events(X.ReplayKeyboard, X.CurrentTime)
after handling an event, but if i don't do this, everything freezes.
for the final program the change in the listening behaviour is not really relevant, but i have to be able to distinguish the fake events from the user events. to do this i'm just fast forwarding display.next_event(), but this isnt ideal, because the user could be typing at that exact moment and than those keystrokes would be lost.
i tried releasing the keygrab during sending and emptying the eventqueue via
display.flush()
display.sync()
but that doesn't do anything.
so, any idea how to recognize or ignore fake input events and why i'm suddenly listening to all keypresses (and releases)?
xlib is very frustrating.
from Xlib.display import Display
import Xlib
from Xlib import X
import Xlib.XK
import sys
import signal
display = None
root = None
def handle_event(aEvent):
print "handle!"
send_key("x")
def send_key(emulated_key):
global display,root
print "send key"
# ungrabbing doesnt help
root.ungrab_key(10,X.AnyModifier)
window = display.get_input_focus()._data["focus"]
# Generate the correct keycode
keysym = Xlib.XK.string_to_keysym(emulated_key)
keycode = display.keysym_to_keycode(keysym)
# Send a fake keypress via xtestaaa
Xlib.ext.xtest.fake_input(window, Xlib.X.KeyPress, keycode)
Xlib.ext.xtest.fake_input(window, Xlib.X.KeyRelease, keycode)
display.flush()
display.sync()
# fast forward those two events,this seems a bit hacky,
# what if theres another keyevent coming in at that exact time?
while display.pending_events():
display.next_event()
#
root.grab_key(10, X.AnyModifier, True,X.GrabModeSync, X.GrabModeSync)
def main():
# current display
global display,root
display = Display()
root = display.screen().root
# we tell the X server we want to catch keyPress event
root.change_attributes(event_mask = X.KeyPressMask)
# just grab the "1"-key for now
root.grab_key(10, X.AnyModifier, True,X.GrabModeSync, X.GrabModeSync)
# while experimenting everything could freeze, so exit after 10 seconds
signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
signal.alarm(10)
while 1:
event = display.next_event()
print "event"
#if i dont call this, the whole thing freezes
display.allow_events(X.ReplayKeyboard, X.CurrentTime)
handle_event(event)
if __name__ == '__main__':
main()
i found the problem. im almost certain that xtest.fake_input does something weird, because when i send keypresses and -releases manually (with some code i found), it works
here is an example, that swallows only the "1"-key on keypress and sends "x" on keyrelease to the focused window:
from Xlib.display import Display
import Xlib
from Xlib import X
import Xlib.XK
import sys
import signal
import time
display = None
root = None
def handle_event(event):
print "handle!"
if (event.type == X.KeyRelease):
send_key("x")
# from http://shallowsky.com/software/crikey/pykey-0.1
def send_key(emulated_key):
shift_mask = 0 # or Xlib.X.ShiftMask
window = display.get_input_focus()._data["focus"]
keysym = Xlib.XK.string_to_keysym(emulated_key)
keycode = display.keysym_to_keycode(keysym)
event = Xlib.protocol.event.KeyPress(
time = int(time.time()),
root = root,
window = window,
same_screen = 0, child = Xlib.X.NONE,
root_x = 0, root_y = 0, event_x = 0, event_y = 0,
state = shift_mask,
detail = keycode
)
window.send_event(event, propagate = True)
event = Xlib.protocol.event.KeyRelease(
time = int(time.time()),
root = display.screen().root,
window = window,
same_screen = 0, child = Xlib.X.NONE,
root_x = 0, root_y = 0, event_x = 0, event_y = 0,
state = shift_mask,
detail = keycode
)
window.send_event(event, propagate = True)
def main():
# current display
global display,root
display = Display()
root = display.screen().root
# we tell the X server we want to catch keyPress event
root.change_attributes(event_mask = X.KeyPressMask|X.KeyReleaseMask)
# just grab the "1"-key for now
root.grab_key(10, 0, True,X.GrabModeSync, X.GrabModeSync)
signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
signal.alarm(10)
while 1:
event = display.next_event()
print "event"
handle_event(event)
display.allow_events(X.AsyncKeyboard, X.CurrentTime)
if __name__ == '__main__':
main()

Categories