Skip to content

Instantly share code, notes, and snippets.

@albertmenglongli
Created December 18, 2014 08:38
Show Gist options
  • Save albertmenglongli/b9090cdb24bcf4e6fda8 to your computer and use it in GitHub Desktop.
Save albertmenglongli/b9090cdb24bcf4e6fda8 to your computer and use it in GitHub Desktop.
Pythonista Scripts
# coding: utf-8
# Calculator
from __future__ import division
import ui
import clipboard
from console import hud_alert
shows_result = False
def button_tapped(sender):
# Get the button's title for the following logic:
'@type sender: ui.Button'
t = sender.title
global shows_result
# Get the labels:
label = sender.superview['label1']
label2 = sender.superview['label2']
if t in '0123456789':
if shows_result or label.text == '0':
# Replace 0 or last result with number:
label.text = t
else:
# Append number:
label.text += t
elif t == '.' and label.text[-1] != '.':
# Append decimal point (if not already there)
label.text += t
elif t in '+-÷×':
if label.text[-1] in '+-÷×':
# Replace current operator
label.text = label.text[:-1] + t
else:
# Append operator
label.text += t
elif t == 'AC':
# Clear All
label.text = '0'
elif t == 'C':
# Delete the last character:
label.text = label.text[:-1]
if len(label.text) == 0:
label.text = '0'
elif t == '=':
# Evaluate the result:
try:
label2.text = label.text + ' ='
expr = label.text.replace('÷', '/').replace('×', '*')
label.text = str(eval(expr))
except SyntaxError:
label.text = 'ERROR'
shows_result = True
if t != '=':
shows_result = False
label2.text = ''
def copy_action(sender):
'@type sender: ui.Button'
t1 = sender.superview['label1'].text
t2 = sender.superview['label2'].text
if t2:
text = t2 + ' ' + t1
else:
text = t1
clipboard.set(text)
hud_alert('Copied')
v = ui.load_view('Calculator')
if ui.get_screen_size()[1] >= 768:
# iPad
v.present('popover')
else:
# iPhone
v.present(orientations=['portrait'])
[{"class":"View","attributes":{"name":"Calculator","tint_color":"RGBA(0.000000,0.478000,1.000000,1.000000)","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":""},"frame":"{{0, 0}, {320, 348}}","nodes":[{"class":"View","attributes":{"name":"view1","background_color":"RGBA(0.857143,1.000000,0.994286,1.000000)","uuid":"CC4B3D71-74EC-4FB4-818D-358953CBBAA8","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"W"},"frame":"{{0, 0}, {320, 82}}","nodes":[]},{"class":"Label","attributes":{"font_size":30,"enabled":true,"text":"0","flex":"","name":"label1","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"right","border_width":0,"uuid":"B149E929-5F4F-4405-A346-1BE00F4514ED"},"frame":"{{6, 31}, {304, 51}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"7","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button1","border_width":1,"uuid":"AF7CF1CC-BA6B-4373-816D-632447E2E62B"},"frame":"{{6, 142}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"8","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button2","border_width":1,"uuid":"E5122F26-BD09-4DCE-ABC9-73ECD6AB79E7"},"frame":"{{84, 142}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"9","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button3","border_width":1,"uuid":"C3F3A6B9-6087-4501-AD4E-6A4E1FFE08F5"},"frame":"{{162, 142}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"font_size":22,"enabled":true,"flex":"","font_bold":false,"name":"button4","uuid":"1C616F1D-E8DF-4886-A64F-0602E8F3316B","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","action":"button_tapped","border_width":1,"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","title":"-"},"frame":"{{240, 142}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"4","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button5","border_width":1,"uuid":"5243E306-25B6-4907-9AA4-8109D06C3A5F"},"frame":"{{6, 194}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"5","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button6","border_width":1,"uuid":"D28987BA-A739-4182-8FDA-9B822A102760"},"frame":"{{84, 194}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"6","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button7","border_width":1,"uuid":"BDCC1E60-590E-4DCA-A90F-E19CDB5A2DA3"},"frame":"{{162, 194}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"font_size":22,"enabled":true,"flex":"","font_bold":false,"name":"button8","uuid":"4ACCB63D-A360-407D-A8AC-2E146715A434","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","action":"button_tapped","border_width":1,"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","title":"+"},"frame":"{{240, 194}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"1","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button9","border_width":1,"uuid":"889445CF-A915-43BC-A5D7-42BE0674A8F0"},"frame":"{{6, 246}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"2","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button10","border_width":1,"uuid":"4655F294-7170-442B-8CFD-0FB6A8D5AEE8"},"frame":"{{84, 246}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"3","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button11","border_width":1,"uuid":"6447B9F0-12FC-41A1-A75F-6357DF0BFAB9"},"frame":"{{162, 246}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"0","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button13","border_width":1,"uuid":"38C3115F-5C4A-4BE4-8650-9728E6C824EC"},"frame":"{{6, 298}, {148, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":".","enabled":true,"tint_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button15","border_width":1,"uuid":"32290A67-2788-4F24-BD29-58535AAC1128"},"frame":"{{162, 298}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"font_size":22,"enabled":true,"flex":"","font_bold":false,"name":"button16","uuid":"804C39B2-BEA1-45A4-9961-0CA28869DEDE","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","action":"button_tapped","border_width":1,"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","title":"="},"frame":"{{240, 246}, {70, 96}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"AC","enabled":true,"tint_color":"RGBA(1.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button12","border_width":1,"uuid":"5C4AB036-DD50-44E9-969B-5C564DBAA8AB"},"frame":"{{6, 90}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","font_size":22,"title":"C","enabled":true,"tint_color":"RGBA(1.000000,0.000000,0.000000,1.000000)","flex":"","action":"button_tapped","font_bold":false,"name":"button14","border_width":1,"uuid":"85CE26A5-BE6C-46F2-B7C9-09C93673FE8B"},"frame":"{{84, 90}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"font_size":22,"enabled":true,"flex":"","font_bold":false,"name":"button17","uuid":"B44FB49D-6AA7-4563-8DE7-EFCFB26F226F","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","action":"button_tapped","border_width":1,"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","title":"÷"},"frame":"{{162, 90}, {70, 44}}","nodes":[]},{"class":"Button","attributes":{"font_size":22,"enabled":true,"flex":"","font_bold":false,"name":"button18","uuid":"E43D7994-946B-414F-830A-9B05C4A9BE17","border_color":"RGBA(0.785714,0.785714,0.785714,1.000000)","action":"button_tapped","border_width":1,"background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","title":"×"},"frame":"{{240, 90}, {70, 44}}","nodes":[]},{"class":"Label","attributes":{"font_size":14,"enabled":true,"text":"","flex":"","name":"label2","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.500000,0.500000,0.500000,1.000000)","alignment":"right","border_width":0,"uuid":"EF6F310B-190C-45D1-AAC8-E7583115882B"},"frame":"{{6, 6}, {304, 26}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"","font_bold":false,"name":"button19","uuid":"84F7FA45-EF6B-42EC-ABBB-580731B89710","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"copy_action","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","image_name":"ionicons-ios7-copy-outline-32","title":""},"frame":"{{6, 40}, {40, 42}}","nodes":[]}]}]
# Card Game
#
# In this game, you have to find matching pairs of cards.
# This scene consists entirely of layers and demonstrates some
# interesting animation techniques.
from scene import *
from random import shuffle
from functools import partial
import sound
class Game (Scene):
def setup(self):
self.root_layer = Layer(self.bounds)
for effect in ['Click_1', 'Click_2', 'Coin_2', 'Coin_5']:
sound.load_effect(effect)
self.deal()
def draw(self):
background(0.0, 0.2, 0.3)
self.root_layer.update(self.dt)
self.root_layer.draw()
def deal(self):
images = ['Rabbit_Face', 'Mouse_Face', 'Cat_Face',
'Dog_Face', 'Octopus', 'Bear_Face',
'Chicken', 'Cow_Face'] * 2
for image in images:
load_image(image)
shuffle(images)
self.root_layer.sublayers = []
self.cards = []
self.selected = []
card_size = 96 if self.size.w > 700 else 64
width = (card_size + 5) * 4
offset = Point((self.size.w - width)/2,
(self.size.h - width)/2)
for i in xrange(len(images)):
x, y = i % 4, i / 4
card = Layer(Rect(offset.x + x * (card_size + 5),
offset.y + y * (card_size + 5),
card_size, card_size))
card.card_image = images[i]
card.background = Color(0.9, 0.9, 0.9)
card.stroke = Color(1, 1, 1)
card.stroke_weight = 4.0
self.add_layer(card)
self.cards.append(card)
self.touch_disabled = False
def touch_began(self, touch):
if self.touch_disabled or len(self.cards) == 0:
return
if len(self.selected) == 2:
self.discard_selection()
return
for card in self.cards:
if card in self.selected or len(self.selected) > 1:
continue
if touch.location in card.frame:
def reveal_card():
card.image = card.card_image
card.animate('scale_x', 1.0, 0.15,
completion=self.check_selection)
self.selected.append(card)
self.touch_disabled = True
card.animate('scale_x', 0.0, 0.15,
completion=reveal_card)
card.scale_y = 1.0
card.animate('scale_y', 0.9, 0.15, autoreverse=True)
sound.play_effect('Click_1')
break
def discard_selection(self):
sound.play_effect('Click_2')
for card in self.selected:
def conceal(card):
card.image = None
card.animate('scale_x', 1.0, 0.15)
card.animate('scale_x', 0.0, 0.15,
completion=partial(conceal, card))
card.scale_y = 1.0
card.animate('scale_y', 0.9, 0.15, autoreverse=True)
self.selected = []
def check_selection(self):
self.touch_disabled = False
if len(self.selected) == 2:
card_img1 = self.selected[0].card_image
card_img2 = self.selected[1].card_image
if card_img1 == card_img2:
sound.play_effect('Coin_5')
for c in self.selected:
c.animate('background', Color(0.5, 1, 0.5))
self.cards.remove(c)
self.selected = []
if len(self.cards) == 0:
self.win()
def new_game(self):
sound.play_effect('Coin_2')
self.deal()
self.root_layer.animate('scale_x', 1.0)
self.root_layer.animate('scale_y', 1.0)
def win(self):
self.delay(0.5, partial(sound.play_effect, 'Powerup_2'))
font_size = 100 if self.size.w > 700 else 50
text_layer = TextLayer('Well Done!', 'Futura', font_size)
text_layer.frame.center(self.bounds.center())
overlay = Layer(self.bounds)
overlay.background = Color(0, 0, 0, 0)
overlay.add_layer(text_layer)
self.add_layer(overlay)
overlay.animate('background', Color(0.0, 0.2, 0.3, 0.7))
text_layer.animate('scale_x', 1.3, 0.3, autoreverse=True)
text_layer.animate('scale_y', 1.3, 0.3, autoreverse=True)
self.touch_disabled = True
self.root_layer.animate('scale_x', 0.0, delay=2.0,
curve=curve_ease_back_in)
self.root_layer.animate('scale_y', 0.0, delay=2.0,
curve=curve_ease_back_in,
completion=self.new_game)
run(Game())
# Cascade Game
#
# This is a complete game that demonstrates drawing images
# and text, handling touch events and combining simple drawing
# with layer animations.
#
# The game is also known as "Same Game".
# It may appear simple at first, but getting a good score
# actually requires some strategy.
from scene import *
from random import randint
from sound import load_effect, play_effect
from functools import partial
# These values are adjusted for the current screen size in
# the setup method, changing them here won't have an effect.
tile_size = 40
cols = 8
rows = 10
class Tile (object):
def __init__(self, image, x, y):
self.offset = Point() # used for falling animation
self.selected = False
self.image = image
self.x, self.y = x, y
def hit_test(self, touch):
frame = Rect(self.x * tile_size + self.offset.x,
self.y * tile_size + self.offset.y,
tile_size, tile_size)
return touch.location in frame
class Game (Scene):
def setup(self):
#Use different sizes on iPad and iPhone:
global tile_size, cols, rows
ipad = self.size.w > 700
tile_size = 64 if ipad else 40
cols = 12 if ipad else 8
rows = 12 if ipad else 10
if not ipad and self.size.h > 480:
rows += 2 #iPhone 5
#Preload some sound effects to reduce latency:
for sound_effect in ['Click_1', 'Error', 'Coin_3']:
load_effect(sound_effect)
self.new_game()
def new_game(self):
#The effects layer is used to display animated text
#overlays for scores and the game over screen:
self.effects = Layer(self.bounds)
images = ['Green_Apple', 'Grapes', 'Tangerine']
self.score = 0
self.game_over = False
self.grid = list()
for i in xrange(cols * rows):
tile = Tile(images[randint(0, len(images)-1)],
i % cols, i / cols)
self.grid.append(tile)
def neighbors(self, tile):
result = []
if tile is None: return result
x, y = tile.x, tile.y
#Check for neighbors with the same image
#in all 4 directions:
directions = [(0, -1), (1, 0), (0, 1), (-1, 0)]
for direction in directions:
neighbor = self.tile_at(x + direction[0],
y + direction[1])
if neighbor is not None and neighbor.image == tile.image:
result.append(neighbor)
return result
def tile_at(self, x, y):
if x < 0 or y < 0 or x >= cols or y >= rows:
return None
return self.grid[y * cols + x]
def touch_began(self, touch):
play_effect('Click_1')
for tile in self.grid:
if tile is not None: tile.selected = False
for tile in self.grid:
if tile is None: continue
if tile.hit_test(touch):
self.select_from(tile, set())
break
def touch_ended(self, touch):
if self.game_over:
#Start a new game if the current game has ended:
self.new_game()
play_effect('Powerup_3')
return
#At least 2 tiles have to be removed:
sel_count = len(filter(lambda(x): x and x.selected,
self.grid))
if sel_count < 2:
play_effect('Error')
for tile in self.grid:
if tile is not None: tile.selected = False
return
#The first tile is 10 points, the second 20, etc.:
score_added = ((sel_count * (sel_count + 1)) / 2) * 10
self.score += score_added
play_effect('Coin_3')
#Show the added score as an animated text layer:
score_layer = TextLayer(str(score_added),
'GillSans-Bold', 40)
score_layer.frame.center(touch.location)
self.effects.add_layer(score_layer)
from_frame = score_layer.frame
to_frame = Rect(from_frame.x, from_frame.y + 200,
from_frame.w, from_frame.h)
score_layer.animate('frame', to_frame, duration=0.75)
score_layer.animate('alpha', 0.0, delay=0.3,
completion=score_layer.remove_layer)
#Remove selected tiles:
for i in xrange(len(self.grid)):
tile = self.grid[i]
if tile is None: continue
if tile.selected:
self.grid[i] = None
#Adjust the positions of the remaining tiles:
self.drop_tiles()
#If at least one tile has a neighbor with the same image,
#another move is possible:
can_move = max(map(len, map(self.neighbors,
self.grid))) > 0
if not can_move:
play_effect('Bleep')
rest = len(filter(lambda x: x is not None, self.grid))
msg = 'Perfect!' if rest == 0 else 'Game Over'
#Show an animated 'Game Over' message:
font_size = 100 if self.size.w > 700 else 50
game_over_layer = TextLayer(msg, 'GillSans', font_size)
game_over_layer.frame.center(self.size.w / 2,
self.size.h / 2)
game_over_layer.alpha = 0.0
self.effects.add_layer(game_over_layer)
#When the animation completes, the game_over flag is set,
#so that the next tap starts a new game:
completion = partial(setattr, self, 'game_over', True)
game_over_layer.animate('alpha', 1.0, duration=1.0,
completion=completion)
game_over_layer.animate('scale_x', 1.2, autoreverse=True,
duration=1.0)
game_over_layer.animate('scale_y', 1.2, autoreverse=True,
duration=1.0)
def drop_tiles(self):
new_grid = [None for x in xrange(len(self.grid))]
shift = 0
for col in xrange(cols):
drop = 0
col_empty = True
for row in xrange(rows):
tile = self.tile_at(col, row)
if tile is None:
drop += 1
else:
col_empty = False
new_y = tile.y - drop
new_x = tile.x - shift
tile.offset.y += tile_size * (tile.y - new_y)
tile.offset.x += (tile.x - new_x) * tile_size
tile.x, tile.y = new_x, new_y
new_grid[new_y * cols + new_x] = tile
if col_empty:
shift += 1
self.grid = new_grid
def select_from(self, tile, visited, count=1):
#Recursively select all neighboring tiles
#with the same image:
tile.selected = True
visited.add(tile)
n = self.neighbors(tile)
for neighbor in n:
if neighbor in visited: continue
if neighbor.image == tile.image:
count = self.select_from(neighbor, visited, count) + 1
return count
def draw(self):
background(0, 0.1, 0.2)
collision = False
falling = False
#Adjust the falling animation speed based
#on the current framerate:
fall_speed = self.dt * 700
#Draw all the tiles:
draw_selected = False
tint(1.0, 1.0, 1.0)
for tile in self.grid:
if tile is None: continue
if draw_selected != tile.selected:
tint(1.0, 1.0, 1.0, 0.5 if tile.selected else 1.0)
draw_selected = tile.selected
image(tile.image,
tile.x * tile_size + tile.offset.x,
tile.y * tile_size + tile.offset.y,
tile_size, tile_size)
if tile.offset.y > 0:
tile.offset.y = max(0.0, tile.offset.y - fall_speed)
if tile.offset.y == 0.0: collision = True
falling = True
#Draw the current score:
tint(1.0, 1.0, 1.0)
w, h = self.size.w, self.size.h
font_size = 60 if self.size.w > 700 else 40
text(str(self.score), 'GillSans', font_size, w * 0.5, h - 50)
#Animate shifting empty columns:
if not falling:
for tile in self.grid:
if tile is None: continue
if tile.offset.x > 0:
tile.offset.x = max(0.0, tile.offset.x - fall_speed)
if tile.offset.x == 0: collision = True
#Play a sound effect if at least one tile has "landed":
if collision:
play_effect('Click_1')
#Update and draw the text effects layer:
self.effects.update(self.dt)
self.effects.draw()
#Always run the game in portrait orientation):
run(Game(), PORTRAIT)
# Clock
#
# An analog clock that demonstrates drawing basic
# shapes with the scene module.
from scene import *
from time import localtime
ipad = False #will be set in the setup method
#Our Clock class inherits from Scene, so that its draw method
#is automatically called 60 times per second when we run it.
class Clock (Scene):
def setup(self):
global ipad
ipad = self.size.w > 700
def should_rotate(self, orientation):
return True
def draw(self):
background(0, 0.2, 0.3)
t = localtime()
minute = t.tm_min
second = t.tm_sec
hour = t.tm_hour % 12
margin = 25 if ipad else 5
r = (min(self.size.w, self.size.h) / 2) - margin * 2
center = Point(self.size.w/2, self.size.h/2)
#Draw the clock face:
fill(0.8, 0.8, 0.8)
stroke(0.5, 0.5, 0.5)
line_w = 10 if ipad else 5
stroke_weight(line_w)
ellipse(center.x - r, center.y - r, r*2, r*2)
#Draw 12 markers for the hours:
push_matrix()
fill(0.5, 0.5, 0.5)
no_stroke()
translate(center.x, center.y)
digit_w = 20 if ipad else 10
digit_h = 40 if ipad else 20
for i in xrange(12):
rotate(30)
rect(-digit_w/2, r-digit_h, digit_w, digit_h)
pop_matrix()
#Draw the minute hand:
push_matrix()
translate(center.x, center.y)
rotate((-360 / 60) * minute + (-360/60) * (second/60.))
fill(0, 0, 0)
m_height = r - (60 if ipad else 30)
m_width = 20 if ipad else 10
rect(-m_width/2, -m_width/2, m_width, m_height)
pop_matrix()
#Draw the hour hand:
push_matrix()
translate(center.x, center.y)
rotate((-360 / 12) * hour + (-360/12.) * (minute/60.))
fill(0, 0, 0)
h_width = 20 if ipad else 10
h_height = r - (120 if ipad else 60)
rect(-h_width/2, -h_width/2, h_width, h_height)
pop_matrix()
#Draw the second hand:
push_matrix()
translate(center.x, center.y)
rotate((-360 / 60) * second)
fill(1, 0, 0)
s_width = 10 if ipad else 6
s_height = r - (60 if ipad else 20)
rect(-s_width/2, -s_width/2, s_width, s_height)
pop_matrix()
fill(0, 0, 0)
#Draw the small circle in the middle:
r = 20 if ipad else 10
ellipse(center.x - r, center.y - r, r*2, r*2)
#Run the scene that we just defined:
run(Clock())
# ColorMixer
# A simple RGB color mixer with three sliders.
import ui
import clipboard
from random import random
from console import hud_alert
def slider_action(sender):
# Get the root view:
v = sender.superview
# Get the sliders:
r = v['slider1'].value
g = v['slider2'].value
b = v['slider3'].value
# Create the new color from the slider values:
v['view1'].background_color = (r, g, b)
v['label1'].text = '#%.02X%.02X%.02X' % (r*255, g*255, b*255)
def copy_action(sender):
clipboard.set(sender.superview['label1'].text)
hud_alert('Copied')
def shuffle_action(sender):
v = sender.superview
s1 = v['slider1']
s2 = v['slider2']
s3 = v['slider3']
s1.value = random()
s2.value = random()
s3.value = random()
slider_action(s1)
v = ui.load_view('ColorMixer')
slider_action(v['slider1'])
if ui.get_screen_size()[1] >= 768:
# iPad
v.present('popover')
else:
# iPhone
v.present()
[{"class":"View","attributes":{"name":"Color Mixer","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","tint_color":"RGBA(0.000000,0.478000,1.000000,1.000000)","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":""},"frame":"{{0, 0}, {320, 244}}","nodes":[{"class":"Slider","attributes":{"tint_color":"RGBA(1.000000,0.000000,0.000000,1.000000)","enabled":true,"flex":"W","name":"slider1","continuous":true,"value":0.5,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"slider_action","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","uuid":"EEC1AB04-2409-4C90-BD37-C72D603BEEFD"},"frame":"{{6, 73}, {308, 34}}","nodes":[]},{"class":"Slider","attributes":{"tint_color":"RGBA(0.000000,1.000000,0.000000,1.000000)","enabled":true,"flex":"W","name":"slider2","continuous":true,"value":0.5,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"slider_action","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","uuid":"24DD30D7-5087-44FF-BA7B-34FA81E96B25"},"frame":"{{6, 115}, {308, 34}}","nodes":[]},{"class":"Slider","attributes":{"tint_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","enabled":true,"flex":"W","name":"slider3","continuous":true,"value":0.5,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"slider_action","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","uuid":"01C997A5-D740-4147-A0FA-984D6B0E496C"},"frame":"{{6, 157}, {308, 34}}","nodes":[]},{"class":"View","attributes":{"enabled":true,"flex":"R","name":"view1","border_width":1,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","uuid":"B83D01DD-419E-4234-B0A6-357C2B9295D6"},"frame":"{{6, 6}, {154, 59}}","nodes":[]},{"class":"Label","attributes":{"font_size":32,"enabled":true,"text":"#FFFFFF","font_name":"HelveticaNeue-Light","name":"label1","flex":"L","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"center","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","uuid":"81F11B65-0F76-42F8-B27C-6568A0728611"},"frame":"{{168, 6}, {148, 59}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"L","font_bold":false,"name":"button1","uuid":"A2344984-839E-4B23-AE36-06F18F500A55","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"copy_action","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","image_name":"ionicons-ios7-copy-outline-32","title":" Copy"},"frame":"{{168, 199}, {146, 38}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"R","font_bold":false,"name":"button2","uuid":"F748FBD8-3614-40E7-967B-301CD2DD5205","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","action":"shuffle_action","background_color":"RGBA(0.000000,0.000000,0.000000,0.000000)","image_name":"ionicons-shuffle-32","title":" Shuffle"},"frame":"{{6, 199}, {145.5, 38}}","nodes":[]}]}]
#coding: utf-8
import random
names=["wang","peng","duan","meng"]
seq=[0,1,2,3]
people=[]
for j in seq:
if j>=0:
people.append(names[j])
winners=[];i=0
num=len(people)
quitStrLst=["exit","quit"]
quit=False
while True:
if len(winners)>=num-1 or quit:
print "game over!"
break
while True:
#the one who left will not participate throwing the dice anymore
if people[i%num] in winners:
i=i+1
continue
input= raw_input()
if input in quitStrLst:
quit=True
break
if input in people:
print input,",lefted"
winners.append(input)
#if the person is just the one thrown the dice, we minus one in the index, to make sure the next person will not be affected.
if input==people[(i-1)%num]:
i=i-1
break
print people[i%num],
r = random.choice(range(1,7))
print "x"*r,"_"*(6-r),r
i+=1
print "winners:" if len(winners) else "no winner"
for win in winners:
print ">>",win,
# Image Effects
# Demonstrates some effects using different modules
# from the Python Imaging Library (PIL).
#
# Tip: You can touch and hold an image in the output
# to copy it to the clipboard or save it to your
# camera roll.
import Image, ImageOps, ImageFilter
from Image import BILINEAR
from math import sqrt, sin, cos, atan2
def sketch(img):
edge_img = img.filter(ImageFilter.CONTOUR)
return ImageOps.grayscale(edge_img)
def color_tiles(img):
size = img.size
small_img = img.resize((size[0]/2, size[1]/2), BILINEAR)
bw_img = small_img.convert('1', dither=False)
gray_img = bw_img.convert('L')
result = Image.new('RGB', size)
tile1 = ImageOps.colorize(gray_img, 'green', 'red')
tile2 = ImageOps.colorize(gray_img, 'purple', 'yellow')
tile3 = ImageOps.colorize(gray_img, 'yellow', 'brown')
tile4 = ImageOps.colorize(gray_img, 'red', 'cyan')
result.paste(tile1, (0, 0))
result.paste(tile2, (size[0]/2, 0))
result.paste(tile3, (0, size[1]/2))
result.paste(tile4, (size[0]/2, size[1]/2))
return result
def twisted(img, strength):
mesh = []
m = 16
w, h = img.size
for x in xrange(w / m):
for y in xrange(h / m):
target_rect = (x * m, y * m, x * m + m, y * m + m)
quad_points = ((x * m, y * m), (x * m, y * m + m),
(x * m + m, y * m + m), (x * m + m, y * m))
quad_list = []
for qx, qy in quad_points:
dx = w/2 - qx
dy = h/2 - qy
d = sqrt(dx**2 + dy**2)
angle = atan2(dx, dy)
angle += max((w/2 - d), 0) * strength
qx = w/2 - sin(angle) * d
qy = h/2 - cos(angle) * d
quad_list.append(qx)
quad_list.append(qy)
mesh.append((target_rect, quad_list))
return img.transform(img.size, Image.MESH, mesh, BILINEAR)
def main():
img = Image.open('Test_Lenna')
img = img.resize((256, 256), Image.BILINEAR)
img.show()
sketch(img).show()
color_tiles(img).show()
twisted(img, 0.02).show()
if __name__ == '__main__':
main()
# Image Warp
#
# Demonstrates an interesting use of the image_quad function
# to distort an image based on touch.
from scene import *
from math import sqrt, sin, pi, floor
import Image
M = 16 # number of vert. and horiz. quads in the mesh (16*16=256)
class ImageWarp (Scene):
def setup(self):
self.offsets = [[(0.0, 0.0) for x in xrange(M+1)] for y in xrange(M+1)]
if self.size.w >= 700:
# Use the original image on iPad:
self.img = 'Test_Lenna'
s = 512
else:
# Resize the image for small screens:
s = 256
img_name = 'Test_Lenna'
img = Image.open(img_name).convert('RGBA')
img = img.resize((s, s), Image.BILINEAR)
self.img = load_pil_image(img)
self.img_size = s
self.m = s / M
def draw_warped_image(self):
m = self.m
for x in xrange(M):
for y in xrange(M):
d = self.offsets
# distances of the 4 corner points from their original position:
d1 = d[x][y]; d2 = d[x + 1][y]
d3 = d[x][y + 1]; d4 = d[x + 1][y + 1]
image_quad(self.img,
# distorted quad:
x * m + d1[0], y * m + d1[1],
x * m + m + d2[0], y * m + d2[1],
x * m + d3[0], y * m + m + d3[1],
x * m + m + d4[0], y * m + m + d4[1],
# source quad in image:
x * m, y * m, x * m + m, y * m,
x * m, y * m + m, x * m + m, y * m + m)
def bulge(self, touch_x, touch_y):
# push mesh vertices away from touch location:
m = self.m
r = self.img_size / 5
for x in xrange(0, M + 1):
for y in xrange(0, M + 1):
offset = self.offsets[x][y]
dist = sqrt((x*m-touch_x + offset[0])**2.0 +
(y*m-touch_y + offset[1])**2.0)
dx = x*m - touch_x
dy = y*m - touch_y
unit_x = dx / dist if dist > 0 else 0.0
unit_y = dy / dist if dist > 0 else 0.0
b = self.dt * 50
if dist < r:
falloff = max(sin(dist/r*pi), 0)
offset_x = unit_x * b * falloff + offset[0]
offset_y = unit_y * b * falloff + offset[1]
self.offsets[x][y] = (offset_x, offset_y)
def revert(self):
for x in xrange(0, M + 1):
for y in xrange(0, M + 1):
offset = self.offsets[x][y]
offset_x = floor(offset[0] - cmp(offset[0], 0))
offset_y = floor(offset[1] - cmp(offset[1], 0))
self.offsets[x][y] = (offset_x, offset_y)
def draw(self):
background(0, 0, 0)
push_matrix()
tx = self.size.w/2 - self.img_size/2
ty = self.size.h/2 - self.img_size/2
translate(tx, ty)
text('Touch the image to deform it.', 'Helvetica-Bold',
18, self.img_size/2, -30, alignment=5)
text('Use two fingers to revert.', 'Helvetica-Bold',
18, self.img_size/2, -60, alignment=5)
self.draw_warped_image()
pop_matrix()
if len(self.touches) ==0:
return
if len(self.touches) > 1:
self.revert()
else:
loc = self.touches.values()[0].location
touch_x, touch_y = loc.x - tx, loc.y - ty
self.bulge(touch_x, touch_y)
run(ImageWarp(), frame_interval=1)
# Markdown Conversion
#
# This script demonstrates how you can convert Markdown documents
# to HTML and view the results in the built-in browser.
import os, tempfile, codecs
import console, clipboard, webbrowser
from markdown2 import markdown
DEMO = '''
# Markdown Conversion Demo
**Markdown** is a plain text formatting language
invented by [John Gruber][1].
You can use this script to convert markdown
documents to html and preview them in the
built-in browser.
Markdown makes it easy to make text **bold** or *italic*,
and to add [links][2].
You can also format block quotes:
> Any intelligent fool can make things bigger, more
> complex, and more violent. It takes a touch of genius
> -- and a lot of courage -- to move in the opposite
> direction.
*-- Albert Einstein*
...and code blocks:
from markdown2 import markdown
text = "*hello world*"
html = markdown(text)
print html
For more detailed information about Markdown,
please read the [introduction and syntax reference][3]
on the project page.
[1]: http://daringfireball.net
[2]: http://omz-software.com/pythonista
[3]: http://daringfireball.net/projects/markdown
'''
# Basic HTML document structure and CSS styling:
TEMPLATE = '''
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<style>
body {
font-family: helvetica;
font-size: 18px;
color: #333;
}
blockquote {
border-left: solid 3px #bbb;
margin-left: 0px;
padding-left: 10px;
}
pre {
border: 1px solid #bbb;
border-radius: 3px;
padding: 3px;
background-color: #f8f8f8;
}
code {
font-family: DejaVuSansMono, monospace;
}
#wrapper {
margin: 20px;}
</style>
</head>
<body>
<div id="wrapper">
{{CONTENT}}
</div>
</body>
</html>
'''
def main():
choice = console.alert('Markdown Conversion', '', 'Demo', 'Convert Clipboard')
md = DEMO if choice == 1 else clipboard.get()
html = markdown(md, extras=['smarty-pants'])
tempdir = tempfile.gettempdir()
html_path = os.path.join(tempdir, 'temp.html')
html = TEMPLATE.replace('{{CONTENT}}', html)
with codecs.open(html_path, 'w', 'utf-8') as f:
f.write(html)
file_url = 'file://' + html_path
webbrowser.open(file_url)
if __name__ == '__main__':
main()
# MPL Plot
# A simple demo of using matplotlib in Pythonista.
import console
console.clear()
print 'Generating plot... (this may take a little while)'
import numpy
import matplotlib.pyplot as plt
import math
plt.grid(True)
plt.title('matplotlib Demo')
x = numpy.linspace(0.0, 2 * math.pi)
p1 = plt.plot(x, numpy.sin(x), lw=2, c='r')
p2 = plt.plot(x, numpy.cos(x), lw=2, c='b')
plt.legend([p1[0], p2[0]], ['sin(x)', 'cos(x)'], loc=4)
plt.show()
print 'Tip: You can tap and hold the image to save it to your photo library.'
# Particles
#
# Create colorful bubbles by moving your fingers.
from scene import *
from random import random
from colorsys import hsv_to_rgb
class Particle (object):
def __init__(self, location):
self.velocity = Size(random() * 4 - 2, random() * 4 - 2)
self.location = location
self.hue = random()
self.alpha = 1.0
class Particles (Scene):
def setup(self):
self.show_instructions = True
self.particles = set()
self.p_size = 64 if self.size.w > 700 else 32
def should_rotate(self, orientation):
return True
def touch_began(self, touch):
if self.show_instructions:
self.show_instructions = False
blend_mode(BLEND_ADD)
def touch_moved(self, touch):
particle = Particle(touch.location)
self.particles.add(particle)
def draw(self):
background(0, 0, 0)
if self.show_instructions:
s = 40 if self.size.w > 700 else 17
text('Move your fingers across the screen.',
'Futura', s, *self.bounds.center().as_tuple())
dead = set()
for particle in self.particles:
r, g, b = hsv_to_rgb(particle.hue, 1, 1)
a = particle.alpha
tint(r * a, g * a, b * a, a)
x, y = particle.location.as_tuple()
s = (2 - a) * self.p_size
image('White_Circle', x - s/2, y - s/2, s, s)
particle.alpha -= 0.02
particle.hue += 0.02
particle.location.x += particle.velocity.w
particle.location.y += particle.velocity.h
if particle.alpha <= 0:
dead.add(particle)
self.particles -= dead
run(Particles())
# Piano
#
# A simple multi-touch piano.
from scene import *
import sound
from itertools import chain
class Key (object):
def __init__(self, frame):
self.frame = frame
self.name = None
self.touch = None
self.color = Color(1, 1, 1)
self.highlight_color = Color(0.9, 0.9, 0.9)
def hit_test(self, touch):
return touch.location in self.frame
class Piano (Scene):
def setup(self):
self.white_keys = []
self.black_keys = []
white_key_names = ['Piano_C3', 'Piano_D3', 'Piano_E3',
'Piano_F3', 'Piano_G3', 'Piano_A3',
'Piano_B3', 'Piano_C4']
black_key_names = ['Piano_C3#', 'Piano_D3#', 'Piano_F3#',
'Piano_G3#', 'Piano_A3#']
for key_name in chain(white_key_names, black_key_names):
sound.load_effect(key_name)
white_positions = range(8)
black_positions = [0.5, 1.5, 3.5, 4.5, 5.5]
key_w = self.size.w
key_h = self.size.h / 8
for i in range(len(white_key_names)):
pos = white_positions[i]
key = Key(Rect(0, pos * key_h, key_w, key_h))
key.name = white_key_names[i]
self.white_keys.append(key)
for i in range(len(black_key_names)):
pos = black_positions[i]
key = Key(Rect(0, pos * key_h + 10, key_w * 0.6, key_h - 20))
key.name = black_key_names[i]
key.color = Color(0, 0, 0)
key.highlight_color = Color(0.2, 0.2, 0.2)
self.black_keys.append(key)
def draw(self):
stroke_weight(1)
stroke(0.5, 0.5, 0.5)
for key in chain(self.white_keys, self.black_keys):
if key.touch is not None:
fill(*key.highlight_color.as_tuple())
else:
fill(*key.color.as_tuple())
rect(*key.frame.as_tuple())
def touch_began(self, touch):
for key in chain(self.black_keys, self.white_keys):
if key.hit_test(touch):
key.touch = touch
sound.play_effect(key.name)
return
def touch_moved(self, touch):
hit_key = None
for key in chain(self.black_keys, self.white_keys):
hit = key.hit_test(touch)
if hit and hit_key is None:
hit_key = key
if key.touch is None:
key.touch = touch
sound.play_effect(key.name)
if key.touch == touch and key is not hit_key:
key.touch = None
def touch_ended(self, touch):
for key in chain(self.black_keys, self.white_keys):
if key.touch == touch:
key.touch = None
run(Piano(), PORTRAIT)
# Function Plotter
import canvas
import console
from math import sin, cos, pi
def draw_grid(min_x, max_x, min_y, max_y):
w, h = canvas.get_size()
scale_x = w / (max_x - min_x)
scale_y = h / (max_y - min_y)
min_x, max_x = round(min_x), round(max_x)
min_y, max_y = round(min_y), round(max_y)
canvas.begin_updates()
canvas.set_line_width(1)
canvas.set_stroke_color(0.7, 0.7, 0.7)
#Draw vertical grid lines:
x = min_x
while x <= max_x:
if x != 0:
draw_x = round(w / 2 + x * scale_x) + 0.5
canvas.draw_line(draw_x, 0, draw_x, h)
x += 0.5
#Draw horizontal grid lines:
y = min_y
while y <= max_y:
if y != 0:
draw_y = round(h/2 + y * scale_y) + 0.5
canvas.draw_line(0, draw_y, w, draw_y)
y += 0.5
#Draw x and y axis:
canvas.set_stroke_color(0, 0, 0)
canvas.draw_line(0, h/2, w, h/2)
canvas.draw_line(w/2, 0, w/2, h)
canvas.end_updates()
def plot_function(func, color, min_x, max_x, min_y, max_y):
#Calculate scale, set line width and color:
w, h = canvas.get_size()
origin_x, origin_y = w * 0.5, h * 0.5
scale_x = w / (max_x - min_x)
scale_y = h / (max_y - min_y)
canvas.set_stroke_color(*color)
canvas.set_line_width(2)
canvas.move_to(origin_x + scale_x * min_x,
origin_y + func(min_x) * scale_y)
#Draw the graph line:
x = min_x
while x <= max_x:
x += 0.05
draw_x = origin_x + scale_x * x
draw_y = origin_y + func(x) * scale_y
canvas.add_line(draw_x, draw_y)
canvas.set_fill_color(*color)
canvas.draw_path()
#Set up the canvas size and clear any text output:
console.clear()
canvas.set_size(688, 688)
#Draw the grid:
area = (-pi, pi, -pi, pi)
draw_grid(*area)
#Draw 4 different graphs (sin(x), cos(x), x^2, x^3):
plot_function(sin, (1, 0, 0), *area)
plot_function(cos, (0, 0, 1), *area)
plot_function(lambda x: x ** 2, (0, 1, 1), *area)
plot_function(lambda x: x ** 3, (1.0, 0.5, 0), *area)
# Lottery Number Generator
from random import choice
import console
#Helper function to input a number within a given range:
def input_number(prompt, min_value, max_value):
value = None
while value is None:
try:
value = int(raw_input(prompt))
except ValueError:
print 'Please enter a number!'
if value < min_value or value > max_value:
print ('Please enter a number between %i and %i!' %
(min_value, max_value))
value = None
return value
#Print the title and input the range of numbers:
console.clear()
title = 'Lottery Number Generator'
print title
print '=' * 40
minimum = input_number('Smallest number: ', 1, 9999)
maximum = input_number('Largest number: ', minimum, 9999)
n = input_number('How many numbers do you want to draw? ',
1, maximum - minimum + 1)
#Pick the numbers and print the results:
all_numbers = range(minimum, maximum + 1)
selection = []
for i in xrange(n):
r = choice(all_numbers)
selection.append(r)
all_numbers.remove(r)
print '=' * 40
print 'Your numbers:', selection
# Sketch
# A very simple drawing 'app' that demonstrates
# custom views and saving images to the camera roll.
import ui
import photos
import console
# The PathView class is responsible for tracking
# touches and drawing the current stroke.
# It is used by SketchView.
class PathView (ui.View):
def __init__(self, frame):
self.frame = frame
self.flex = 'WH'
self.path = None
self.action = None
def touch_began(self, touch):
x, y = touch.location
self.path = ui.Path()
self.path.line_width = 8.0
self.path.line_join_style = ui.LINE_JOIN_ROUND
self.path.line_cap_style = ui.LINE_CAP_ROUND
self.path.move_to(x, y)
def touch_moved(self, touch):
x, y = touch.location
self.path.line_to(x, y)
self.set_needs_display()
def touch_ended(self, touch):
# Send the current path to the SketchView:
if callable(self.action):
self.action(self)
# Clear the view (the path has now been rendered
# into the SketchView's image view):
self.path = None
self.set_needs_display()
def draw(self):
if self.path:
self.path.stroke()
# The main SketchView contains a PathView for the current
# line and an ImageView for rendering completed strokes.
# It also manages the 'Clear' and 'Save' ButtonItems that
# are shown in the title bar.
class SketchView (ui.View):
def __init__(self, width=1024, height=1024):
self.bg_color = 'white'
iv = ui.ImageView(frame=(0, 0, width, height))
pv = PathView(frame=self.bounds)
pv.action = self.path_action
self.add_subview(iv)
self.add_subview(pv)
save_button = ui.ButtonItem()
save_button.title = 'Save Image'
save_button.action = self.save_action
clear_button = ui.ButtonItem()
clear_button.title = 'Clear'
clear_button.tint_color = 'red'
clear_button.action = self.clear_action
self.right_button_items = [save_button, clear_button]
self.image_view = iv
def path_action(self, sender):
path = sender.path
old_img = self.image_view.image
width, height = self.image_view.width, self.image_view.height
with ui.ImageContext(width, height) as ctx:
if old_img:
old_img.draw()
path.stroke()
self.image_view.image = ctx.get_image()
def clear_action(self, sender):
self.image_view.image = None
def save_action(self, sender):
if self.image_view.image:
# We draw a new image here, so that it has the current
# orientation (the canvas is quadratic).
with ui.ImageContext(self.width, self.height) as ctx:
self.image_view.image.draw()
img = ctx.get_image()
photos.save_image(img)
console.hud_alert('Saved')
else:
console.hud_alert('No Image', 'error')
# We use a quadratic canvas, so that the same image
# can be used in portrait and landscape orientation.
w, h = ui.get_screen_size()
canvas_size = max(w, h)
sv = SketchView(canvas_size, canvas_size)
sv.name = 'Sketch'
sv.present('fullscreen')
# Stopwatch
#
# A simple stopwatch that demonstrates the scene module's text
# drawing capabilities.
from scene import *
from time import time
from math import modf
from itertools import chain
import string
class Stopwatch (Scene):
def setup(self):
self.start_time = 0.0
self.stop_time = 0.0
self.running = False
#Render all the digits as individual images:
self.numbers = {}
font_size = 150 if self.size.w > 700 else 60
for s in chain(string.digits, [':', '.']):
#render_text returns a tuple of
#an image name and its size.
self.numbers[s] = render_text(s, 'Helvetica-Bold', font_size)
def should_rotate(self, orientation):
return True
def draw(self):
background(0, 0, 0)
#Format the elapsed time (dt):
dt = 0.0
if self.running:
dt = time() - self.start_time
else:
dt = self.stop_time - self.start_time
minutes = dt / 60
seconds = dt % 60
centiseconds = modf(dt)[0] * 100
s = '%02d:%02d.%02d' % (minutes, seconds, centiseconds)
#Determine overall size for centering:
w, h = 0.0, self.numbers['0'][1].h
for c in s:
size = self.numbers[c][1]
w += size.w
#Draw the digits:
x = int(self.size.w * 0.5 - w * 0.5)
y = int(self.size.h * 0.5 - h * 0.5)
for c in s:
img, size = self.numbers[c]
image(img, x, y, size.w, size.h)
x += size.w
def touch_began(self, touch):
if not self.running:
if self.start_time > 0:
#Reset:
self.start_time = 0.0
self.stop_time = 0.0
else:
#Start:
self.start_time = time()
self.running = True
else:
#Stop:
self.stop_time = time()
self.running = False
run(Stopwatch())
# Zen
#
# Prints the Zen of Python with a color gradient.
# This demonstrates the use of the console module to set
# the output's font and color.
import console
import sys
import codecs
from colorsys import hsv_to_rgb
from StringIO import StringIO
#Suppress the output while importing 'this':
prev_out = sys.stdout
sys.stdout = StringIO()
import this
sys.stdout = prev_out
console.clear()
#Decode the 'Zen of Python' text and split to a list of lines:
decoder = codecs.getdecoder('rot_13')
text = decoder(this.s)[0]
lines = text.split('\n')
#Print the title (first line):
console.set_font('Futura', 22)
console.set_color(0.2, 0.2, 0.2)
print lines[0]
#Print the other lines in varying colors:
hue = 0.45
for line in lines[1:]:
r, g, b = hsv_to_rgb(hue, 1.0, 0.8)
console.set_color(r, g, b)
console.set_font('Futura', 16)
print line
hue += 0.02
#Reset output to default font and color:
console.set_font()
console.set_color()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment