19 Mart 2009 Perşembe

PyGame İle İlerleme Çubuğu (ProgressBar) Yapalım

Bugün pygame ile basit bir ilerleme çubuğu yapacağız. Uzun zaman alan işlemlerde kullanıcı sıkılmasın diye ekranda sürekli ilerleyen bir çubuk görmeye alışkınsanız bunu neden biz de yapamayalım diyor olabilirsiniz. Öyleyse bu yazı size göre.

İlerleme çubuğu sınıfımız ProgressBar olacak. Bu sınıf görsel hazırlıklarını, miras aldığı ProgressImage'a yaptıracak. Kullanım için biraz ilkel olsa da başlangıç olarak basit bir yöntem seçtim. Ama bu yazının amacı sizlere pygame'i anlatmak. Kullanmanızı ve neden ben de yapmayayım demenizi sağlamak. Bu yüzden kullanılabilirlik konusunda yeterinden öte ayrıntıya girmedim.

Örneğin uzun zaman alan bir döngünüz var:

for i in range(kere):
oturanboga.konus()



Bu döngüde ProgressBar sınıfından bir nesneyi şu şekilde kullanacaksınız:

bariscubugu = ProgressBar(kere, adim, cubukboyutu, ilkrenk, sonrenk)
while not bariscubugu.isEnd():
oturanboga.konus()
bariscubugu.makestep()


Bu kadarı bile sizleri harekete geçirmiştir sanırım. Şimdi yapıma geçelim :)

Önce meşhur modülümüzü import edelim ve bakalım internetten indirmiş misiniz ya da pisi paket yöneticinizden yüklemiş misiniz:


import sys
try:
import pygame
except ImportError:
print '''
This Program Needs Pygame module to be installed.
For windows you can download it from this adress:
http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi
For linux this adress will be helpful:
http://pygame.org/ftp/pygame-1.8.1release.tar.gz
'''
sys.exit(0)


Burada try bloğu içinde yer alan ifade("import pygame") test edilir; hata varsa except bloğunda verilen hataya bakılır. Hatalar uyuşuyorsa except bloğu çalıştırılır; traceback ile başlayan soğuk cümleler yerine bizim programımızda yer alan kullanıcı dostu arkadaş cümleler kullanılabilir ve kullanıcının yüreği ferah tutulmuş olur.

Kök sınıfımız(miras veren sınıf) ProgressImage'ı yazmaya başlayalım:


class ProgressImage:
def __init__(self, size, initcolor, barcolor):
pygame.display.init() #1.
self.screen = pygame.display.set_mode(size) #2.
self.bar = pygame.Surface((size[0]-10,size[1]-10)) #3.
self.bar.fill(initcolor) #4.
pygame.display.update(self.screen.blit(self.bar, (5,5))) #5.

def quit(self):
pygame.display.quit()



  1. Bu sınıfı iyi inceleyelim. Pygame bilenler ne yapıldığını aşağı yukarı anlayacaklardır ama bilmeyen ya da az bilenler için açıklayalım:
    pygame.display.init() satırı display modülünü başlangıçlandırır. Değer döndürmez. Bu metod kullanılmadan önce pygame.display.SDL_VIDEODRIVER ortam değişkeninin -eğer isteniyorsa- değiştirilmesi mümkündür. Böylece kullanılacak video sürücüsü seçilebilir. (Ayrıntı için bakınız)

  2. pygame.display.set_mode() metodu görüntüyü ayarlar ve 3 argüman alır. Bize sadece iki tanesi hatta biri gerekecek. İlk argüman genişlik ve yükseklik değerlerini içeren bir sabit listedir.(tuple) Burada (genislik, yukseklik) şeklinde geçecektir. İkinci argüman flags parametresidir. Bu da görüntü modunu seçmeye yarar. Kodumuzda size parametresiyle yetinilmiştir. Bu metod geriye bir Surface nesnesi döndürür.

    • Surface görüntüleri pixeller halinde saklayan bir nesnedir.
    • Yeni bir nesne oluştururken tual = pygame.Surface((100,100)) şeklinde kullanılabilir. Bu tual isminde bir yüzey nesnesi oluşturacaktır.
    • Örneğimizde self.screen = pygame.display.set_mode(size) kodu screen isminde bir Surface nesnesini display modülünün ilk kez oluşturduğu ana ekrandan almaktadır.
    • screen artık ana ekrana referans etmektedir.


  3. self.bar = pygame.Surface((size[0]-10,size[1]-10))
    satırında da az önce gördüğümüz gibi bir Surface nesnesi yaratılmaktadır. Bu nesneyi screen ana ekranının üzerine çizeceğiz; çünkü bu nesne göstergemizin görüneceği nesne olacak(siz buna katman(layer) da diyebilirsiniz). Göstergenin boyutu screen nesnesinin boyutuna göre 5 piksel içerde görünecek.

  4. self.bar.fill(initcolor) satırında elde ettiğimiz bar isimli yüzey nesnesini initcolor rengiyle dolduruyoruz. Burada color hakkında şunu söylemeliyim: Kırmızı(red), Yeşil(green), Mavi(blue) değerlerini 0-255 değerleri arasında içeren bir üçlü sabit listedir color. (0,0,255) gibi(mavi)

  5. pygame.display.update(self.screen.blit(self.bar, (5,5))) satırında önce pygame.display.update() metoduna verilen parametreye bakalım.

    • self.screen.blit(self.bar, (5,5)) komutu bar nesnesini screen nesnesinin üzerine çizer. Ama bunu ekrana yansıtmaz. Dikkat: nesneleri üstüste bindirir ancak görüntünün oluşması için update() metodu çalışmaldır.
    • Bu metod yani blit() metodu Rect döndürür. Bu bar nesnesinin kapladığı dikdörtgen alanın koordinatlarını içeren başka bir nesnedir ki tahmin edeceğiniz gibi pygame.display.update() metodu Rect alır.
    • Sonuç olarak yaptığımız ana ekran nesnesi olan screen'in üzerine bar nesnesini yanlızca kapladığı alan içinde bindirmektir. Bu bütün ekranı güncellemekten daha hızlı bir metoddur.



Bu kadarı pygame için yeterli sanırım şimdi programı huzurlarınıza sunuyorum. Sizde programı dilediğiniz gibi kopyalayıp kendi başınıza birşeyler deneyebilirsiniz.


import sys
try:
import pygame
except ImportError:
print '''
This Program Needs Pygame module to be installed.
For windows you can download it from this adress:
http://pygame.org/ftp/pygame-1.8.1release.win32-py2.5.msi
For linux this adress will be helpful:
http://pygame.org/ftp/pygame-1.8.1release.tar.gz
'''
sys.exit(0)

class ProgressImage:
def __init__(self, size, initcolor, barcolor):
pygame.display.init()
self.screen = pygame.display.set_mode(size)
self.bar = pygame.Surface((size[0]-10,size[1]-10))
self.bar.fill(initcolor)
pygame.display.update(self.screen.blit(self.bar, (5,5)))

class ProgressBar(ProgressImage):
def __init__(self, whole, step, size, initcolor, barcolor):
ProgressImage.__init__(self, size, initcolor, barcolor)
self.size = size
self.initcolor = initcolor
self.barcolor = barcolor
self.whole = whole
self.step = step
if whole < step:
print "Error: ProgressBar length can't be smaller than step"
sys.exit(1)
self.slice = float(step)/float(whole)
self.percent = 0.0

def showprogress(self):
self.screen.fill(self.initcolor)
barwidth = (self.size[0]-10)*self.percent
barheight = self.size[1]-10
self.bar = pygame.Surface((barwidth,barheight))
self.bar.fill(self.barcolor)
pygame.display.update(self.screen.blit(self.bar, (5,5)))

def reset(self):
self.percent = 0.0
self.showprogress()

def makestep(self):
if self.percent < 1.0:
self.percent += self.slice
self.showprogress()

def quit(self):
pygame.display.quit()

def isEnd(self):
if self.percent<=1.0:
return False
else:
return True

if __name__ == "__main__":
pb = ProgressBar(1000, 10, (100,40), (255,255,255), (0,0,255))
i, j, k = 0, 0, 0
while not pb.isEnd():
temp = "running.."
for j in range(5):
for k in range(5):
print temp
pb.makestep()
pb.quit()


progressbar.png
Hepinize kolay gelsin :)

2 yorum:

  1. Makaledeki kodları kopyalayıp yapıştırınca girintileme kayboluyor bu yüzden düzeltip pastebin adresin'e yapıştırdım : http://pastebin.com/m74b79d8e Buradan rahatça alınabilir. :) Ellerinize sağlık çok güzel bir yazı olmuş. Başka örnekler de bekleriz :)

    YanıtlaSil
  2. Mirat; sağolun. Ben de kodları yapıştıracak bir site aramış ama bulamamıştım. Ayrıca beğendiğinize de sevindim :)

    YanıtlaSil