123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #!/usr/bin/env python
- """An zoomed image viewer that demonstrates Surface.scroll
- This example shows a scrollable image that has a zoom factor of eight.
- It uses the Surface.scroll function to shift the image on the display
- surface. A clip rectangle protects a margin area. If called as a function,
- the example accepts an optional image file path. If run as a program
- it takes an optional file path command line argument. If no file
- is provided a default image file is used.
- When running click on a black triangle to move one pixel in the direction
- the triangle points. Or use the arrow keys. Close the window or press ESC
- to quit.
- """
- import sys
- import os
- import pygame
- from pygame.transform import scale
- from pygame.locals import *
- main_dir = os.path.dirname(os.path.abspath(__file__))
- DIR_UP = 1
- DIR_DOWN = 2
- DIR_LEFT = 3
- DIR_RIGHT = 4
- zoom_factor = 8
- def draw_arrow(surf, color, posn, direction):
- x, y = posn
- if direction == DIR_UP:
- pointlist = ((x - 29, y + 30), (x + 30, y + 30),
- (x + 1, y - 29), (x, y - 29))
- elif direction == DIR_DOWN:
- pointlist = ((x - 29, y - 29), (x + 30, y - 29),
- (x + 1, y + 30), (x, y + 30))
- elif direction == DIR_LEFT:
- pointlist = ((x + 30, y - 29), (x + 30, y + 30),
- (x - 29, y + 1), (x - 29, y))
- else:
- pointlist = ((x - 29, y - 29), (x - 29, y + 30),
- (x + 30, y + 1), (x + 30, y))
- pygame.draw.polygon(surf, color, pointlist)
- def add_arrow_button(screen, regions, posn, direction):
- draw_arrow(screen, Color('black'), posn, direction)
- draw_arrow(regions, (direction, 0, 0), posn, direction)
- def scroll_view(screen, image, direction, view_rect):
- dx = dy = 0
- src_rect = None
- zoom_view_rect = screen.get_clip()
- image_w, image_h = image.get_size()
- if direction == DIR_UP:
- if view_rect.top > 0:
- screen.scroll(dy=zoom_factor)
- view_rect.move_ip(0, -1)
- src_rect = view_rect.copy()
- src_rect.h = 1
- dst_rect = zoom_view_rect.copy()
- dst_rect.h = zoom_factor
- elif direction == DIR_DOWN:
- if view_rect.bottom < image_h:
- screen.scroll(dy=-zoom_factor)
- view_rect.move_ip(0, 1)
- src_rect = view_rect.copy()
- src_rect.h = 1
- src_rect.bottom = view_rect.bottom
- dst_rect = zoom_view_rect.copy()
- dst_rect.h = zoom_factor
- dst_rect.bottom = zoom_view_rect.bottom
- elif direction == DIR_LEFT:
- if view_rect.left > 0:
- screen.scroll(dx=zoom_factor)
- view_rect.move_ip(-1, 0)
- src_rect = view_rect.copy()
- src_rect.w = 1
- dst_rect = zoom_view_rect.copy()
- dst_rect.w = zoom_factor
- elif direction == DIR_RIGHT:
- if view_rect.right < image_w:
- screen.scroll(dx=-zoom_factor)
- view_rect.move_ip(1, 0)
- src_rect = view_rect.copy()
- src_rect.w = 1
- src_rect.right = view_rect.right
- dst_rect = zoom_view_rect.copy()
- dst_rect.w = zoom_factor
- dst_rect.right = zoom_view_rect.right
- if src_rect is not None:
- scale(image.subsurface(src_rect),
- dst_rect.size,
- screen.subsurface(dst_rect))
- pygame.display.update(zoom_view_rect)
- def main(image_file=None):
- if image_file is None:
- image_file = os.path.join(main_dir, 'data', 'arraydemo.bmp')
- margin = 80
- view_size = (30, 20)
- zoom_view_size = (view_size[0] * zoom_factor,
- view_size[1] * zoom_factor)
- win_size = (zoom_view_size[0] + 2 * margin,
- zoom_view_size[1] + 2 * margin)
- background_color = Color('beige')
- pygame.init()
- # set up key repeating so we can hold down the key to scroll.
- old_k_delay, old_k_interval = pygame.key.get_repeat ()
- pygame.key.set_repeat (500, 30)
- try:
- screen = pygame.display.set_mode(win_size)
- screen.fill(background_color)
- pygame.display.flip()
- image = pygame.image.load(image_file).convert()
- image_w, image_h = image.get_size()
- if image_w < view_size[0] or image_h < view_size[1]:
- print ("The source image is too small for this example.")
- print ("A %i by %i or larger image is required." % zoom_view_size)
- return
- regions = pygame.Surface(win_size, 0, 24)
- add_arrow_button(screen, regions,
- (40, win_size[1] // 2), DIR_LEFT)
- add_arrow_button(screen, regions,
- (win_size[0] - 40, win_size[1] // 2), DIR_RIGHT)
- add_arrow_button(screen, regions,
- (win_size[0] // 2, 40), DIR_UP)
- add_arrow_button(screen, regions,
- (win_size[0] // 2, win_size[1] - 40), DIR_DOWN)
- pygame.display.flip()
- screen.set_clip((margin, margin, zoom_view_size[0], zoom_view_size[1]))
- view_rect = Rect(0, 0, view_size[0], view_size[1])
- scale(image.subsurface(view_rect), zoom_view_size,
- screen.subsurface(screen.get_clip()))
- pygame.display.flip()
- # the direction we will scroll in.
- direction = None
- clock = pygame.time.Clock()
- clock.tick()
- going = True
- while going:
- # wait for events before doing anything.
- #events = [pygame.event.wait()] + pygame.event.get()
- events = pygame.event.get()
- for e in events:
- if e.type == KEYDOWN:
- if e.key == K_ESCAPE:
- going = False
- elif e.key == K_DOWN:
- scroll_view(screen, image, DIR_DOWN, view_rect)
- elif e.key == K_UP:
- scroll_view(screen, image, DIR_UP, view_rect)
- elif e.key == K_LEFT:
- scroll_view(screen, image, DIR_LEFT, view_rect)
- elif e.key == K_RIGHT:
- scroll_view(screen, image, DIR_RIGHT, view_rect)
- elif e.type == QUIT:
- going = False
- elif e.type == MOUSEBUTTONDOWN:
- direction = regions.get_at(e.pos)[0]
- elif e.type == MOUSEBUTTONUP:
- direction = None
- if direction:
- scroll_view(screen, image, direction, view_rect)
- clock.tick(30)
- finally:
- pygame.key.set_repeat (old_k_delay, old_k_interval)
- pygame.quit()
- if __name__ == '__main__':
- if len(sys.argv) > 1:
- image_file = sys.argv[1]
- else:
- image_file = None
- main(image_file)
|