ZodiacMotion: Hareketli zodyak

o_O

Ben tabi Linux fasisti oldugum icin bunlardan bihaberim :slight_smile:

1 Beğeni

Anladım ne demek istediğinizi. Bir bakayım. Teşekkür ederim. :kissing_heart:

1 Beğeni

Normalde ben de Linux kullanıyorum ama işte “aranızda hala Linux kullanmayan …lar var.” sözü geliyor aklıma. :grin: requirements.txt dosyasını Windows kullanıcıları için de hazırlamam lazım.

Dayanamadım yazdım, istiyorsanız siz kendiniz uğraşırsınız yine ama şurada bulunsun:

     def start_command(self):
        s_Y = self.starting_date["Year"].get()
        s_m = self.starting_date["Month"].get()
        s_d = self.starting_date["Day"].get()
        s_H = self.starting_date["Hour"].get()
        s_M = self.starting_date["Minute"].get()
        s_S = self.starting_date["Second"].get()
        e_Y = self.ending_date["Year"].get()
        e_m = self.ending_date["Month"].get()
        e_d = self.ending_date["Day"].get()
        e_H = self.ending_date["Hour"].get()
        e_M = self.ending_date["Minute"].get()
        e_S = self.ending_date["Second"].get()
        lat = self.coordinates["Latitude"].get()
        lon = self.coordinates["Longitude"].get()
        try:
            start = dt.strptime(
                f"{s_Y}.{s_m}.{s_d} {s_H}:{s_M}:{s_S}",
                "%Y.%m.%d %H:%M:%S"
            )
        except ValueError:
            showinfo(
                title="Info",
                message="Invalid date for starting time."
            )
            return
        try:
            end = dt.strptime(
                f"{e_Y}.{e_m}.{e_d} {e_H}:{e_M}:{e_S}",
                "%Y.%m.%d %H:%M:%S"
            )
        except ValueError:
            showinfo(
                title="Info",
                message="Invalid date for ending time."
            )
            return
        if start >= end:
            showinfo(
                title="Info",
                message="Starting time should be greater "
                        "than ending date."
            )
            return
        try:
            lat = float(lat)
        except ValueError:
            showinfo(
                title="Info",
                message="Invalid latitude value."
            )
            return
        try:
            lon = float(lon)
        except ValueError:
            showinfo(
                title="Info",
                message="Invalid longitude value."
            )
            return
        try:
            timezone(
                TimezoneFinder().timezone_at(
                    lat=lat, lng=lon
                )
            )
        except AttributeError:
            showinfo(
                title="Info",
                message="Invalid timezone for given "
                        "latitude and longitude values."
            )
            return
        if float(self.time_increase_scale.get()) <= 0:
            showinfo(
                title="Info",
                message="The amount of increase time "
                        "should be greater than 0."
            )
            return
        if not self.start:
            self.start = True
            if self.canvas:
                for k, v in self.canvas.objects.items():
                    self.canvas.delete(v)
                self.canvas.objects = {}
                self.canvas.destroy()
                self.canvas = None
            if self.pframe:
                self.pframe.destroy()
            for i in self.current_date:
                self.current_date[i]["state"] = "normal"
            s = (end - start).total_seconds()
            c = 0
            n = time()
            self.pframe = tk.Frame(master=self.left_frame)
            pbar = Progressbar(
                master=self.pframe,
                orient="horizontal",
                length=200,
                mode="determinate"
            )
            pstring = tk.StringVar()
            plabel = tk.Label(
                master=self.pframe,
                textvariable=pstring
            )
            self.pframe.pack()
            pbar.pack()
            plabel.pack()
    
            def draw_loop():
                nonlocal start, c
                start += td(
                    seconds=float(
                        self.time_increase_scale.get()
                    )
                )
                c += float(self.time_increase_scale.get())
                pbar["value"] = c
                pbar["maximum"] = s
                pstring.set(self.progress_info(c=c, s=s, n=n))

                self.change_current_date(date=start)
                self.change_zodiac(date=start, lat=lat, lon=lon)
                self.update()

                if start < end:
                    self.after(int(float(self.chart_per_sec_scale.get())*1000), draw_loop)
                else:
                    
                    if self.start:
                        self.change_current_date(date=end)
                    for i in self.current_date:
                        self.current_date[i]["state"] = "disable"
                    self.start = False

            draw_loop()
1 Beğeni

Sayenizde bugün baya bir şey öğrendim. :heart_eyes:

Ah bu update/double buffering mekanizmasina el atayim bu sabah demistim, duzelmis :slight_smile:

Fakat nasil duzeltildigine bakmak istedigimde ilgili commit(ler)i bulamadim. Projede hic commit mesaji yok. :S

Simdi ornek olsun diye ekleyecek baska bir sey bulmam lazim :slight_smile:

@EkremDincel sağolsun hareketteki takılmayı önlemek için şunları yaptı:

  1. self.start_animation düğmesinde referans olarak gösterilen self.start_command fonksiyonunu Thread'den çıkarttı.

  2. text_object, line_object ve aspect_line_object gibi canvas nesneleri oluşturan ve nesnelerin koordinatlarının sürekli değişmesini sağlayan fonksiyonlardan self.update fonksiyonunu çıkarttı. Çünkü while start < end döngüsünde self.update zaten sürekli çağrılıyordu.

Hareketteki takılmaya bir etkisi olmasa da while start < end döngüsünü iptal etti. Döngünün içindekileri loop isimli bir fonksiyona kaydetti, döngü içinde bulunan sleep fonksiyonunu iptal etti. loop fonksiyonun içinde if start < end şeklinde bir koşul tanımladı ve bu koşulda self.after(değişken bekleme süresi, loop) yazarak, fonksiyonun self.after ile kendisinin çağrılmasını sağladı.

1 Beğeni

Gordum, gordum.

Burayi da takip ediyorum, commit’i de buldum :slight_smile:
Cok daha guzel gozukuyor bence, ellerinize saglik.

Asıl @EkremDincel’in eline sağlık. Değişiklikler onun marifeti.

1 Beğeni

Evet, tkinter’de Tk objesinin oluşturulduğu thread’ın dışından arayüzü değiştirmek sıkıntı çıkarıyor. Bunu yapmadığımızda çizimdeki problem de devam ediyor.

Tam olarak ondan değil aslında, while döngüsünde self.update çağırılmasa bile sorun devam edecekti. Normalde canvas’a yapılan çizimler ekrana yansıtılmıyor, update metodu çağırıldığında daha önce çizilmemiş bütün değişiklikler tek seferde çiziliyor. Ekrana yapılan her çizimden sonra bu metodu çağırmak ekrana yansıtılan çizimler arasında gözle görülebilir bir zaman dilimi bulunmasına sebep oluyor.

Bunu yapmamızın sebebi o anda sleep fonksiyonu yüzünden bütün programın -ve dolayısı ile de arayüzün- donuyor olmasıydı.


Okuyanlar tek bir yerde yaptıklarımızın sebebini bulabilsinler diye yazdım.

1 Beğeni

Bu ara çok dikkatsizim, sorunu bile fark edememişim. Çok teşekkür ederim. :kissing_heart:

1 Beğeni

çalıştırmam için ne yapmam gerek

Aşağıdaki adresten dosyaları indirin.


Daha sonra konsolu açın ve gereksinimleri aşağıdaki komutu yazarak kurun.

pip3 install -r requirements.txt

Gereksinimlerin kurulumu bittikten sonra konsola aşağıdaki komutu yazarak programı çalıştırabilirsiniz.

Linux ve Mac için

python3 ZodiacMotion.py

Windows için

python ZodiacMotion.py

@aib’in önerisi doğrultusunda yapılan değişiklikler şunlardır:

  1. requirements.txt dosyası oluşturuldu.
  2. ZodiacMotion.py dosyası parçalara ayrıldı ve parçalar Scripts isimli bir klasöre yerleştirildi.

@dildeolupbiten sorudaki videoyu da güncelleyin istiyorsanız, video silindiği için açılamıyor.

1 Beğeni

Video güncellendi…

Bu arada frame.py ve menu.py dosyalarını birleştirdim tek bir çatı altında topladım. Sebebi de şu: constants.py dosyasının içinde HSYS isminde bir değişken tanımlı ön-tanımlı değeri de "P". Bu değişken menu.py'den değiştirilebilir bir halde. Ben normalde dosyaları bölerken menu.py'nin içine şöyle bir kod yazmıştım from .constants import HSYS. menu.py'deki change_hsys fonksiyonu bu global HSYS'yi kullanıcı seçimine göre değiştiriyor. Ama yapılan değişiklik frame.py'de içe aktarılan HSYS değişkenine etki etmiyordu, değer sürekli "P" olarak kalıyordu. (içe aktarma constants.py veya menu.py'den de yapılsa frame.py'nin içindeki HSYS de bir değişiklik olmuyor.)

frame.py ve menu.py aynı anda ana programın içine aktarıldığı için frame.py, HSYS'nin ilk değeri neyse onu alıyor. Ben de bu yüzden menu.py ile frame.py'yi aynı scriptin içine yerleştirdim.

Aslında birleştirmem de gerekmiyormuş. constants.py içindeki HSYS’yi kaldırdım. HOUSE_SYSTEMS sözlüğüne "Default" isminde bir anahtar ekledim, değerini de "P" yaptım. menu.py dosyasında ön-tanımlı ev sistemi bu yeni değeri kullanarak değiştirilebilir ve bu değişiklik frame.py dosyasında da etkili oluyor artık.

Burada global start, c değişkenlerini loop’un parametresi haline getirmek gerekiyor aksi taktirde, start tuşuna her basıldığında program bozulmaya başlıyor.

Ayrıca paylaştığınız kodlarda start_command fonksiyonunun başına da global start, c olmalıydı. Ben onu fonksiyonun başına koymuştum, bir kere start tuşuna basınca düzgün çalışıyor. Ancak ikinci kez start tuşuna basınca program bozulmaya başlıyor.

Bu yüzden global ifadeyi kaldırdım yerine loop fonksiyonunu parametreler yazdım.

Gezegen seçme özelliği eklendi.