Bir çizginin dönme hızını ön-tanımlı olarak belirlerken istenen sonucu alamadım. Önerisi olan arkadaşlar önerilerini paylaşırsa sevinirim

Merhaba arkadaşlar.

Bir çizgiyi 360 derece döndermeye çalışırken, dönme hızını time.sleep() ile belirliyorum. Mesela aşağıdaki giftte göründüğü gibi, time.sleep() fonksiyonuna bağlı dönme hızını bir spinbox ve scale widgetleri kullanarak değiştirebiliyorum.

Ancak dönme hızını ön-tanımlı olarak değiştirmeye çalıştığımda yalnızca iki tane sayı ön-tanımlı değer olabiliyor. Bunlardan birisi 0 diğeri ise 1. Neden sadece iki değer aldığını anlayamadım.

Aşağıda kodlar paylaşılmıştır. Kodlarda self.doublevar = tk.DoubleVar(value=0) isimli bir değişken var. Buradaki value anahtar argümanının değeri 0 ile 1 arasındaysa, sanki bekleme süresinin değeri 0 olarak belirtilmiş gibi bir sonuç alıyorum.

spinbox ve scale widgetlerinin min, ,max değerleri 0 ve 1 olduğu için bu iki değerden birisi ön-tanımlı bekleme süresi olarak kullanılıyor.

value=2 yaptığımda ise, 1 saniye bekleyerek dönme işlemi gerçekleşiyor.

Yani ön-tanımlı değer neden bu iki değer dışında herhangi bir değer olmuyor merak ediyorum.

Kodlar:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import threading
import tkinter as tk

from math import cos, sin, radians


class RotatingObject(tk.Canvas):
    stopped = []
    def __init__(self, master=None, x=600, y=300, width=1):
        tk.Canvas.__init__(self, master)
        self.pack(expand=True, fill="both")      
        self.x = x 
        self.y = y
        self.width = width      
        self._start = False
        self._stop = True
        self.doublevar = tk.DoubleVar(value=0)
        self.maxvar = tk.DoubleVar(value=1)
        self.minvar = tk.DoubleVar(value=0)
        self.stepvar = tk.DoubleVar(value=10 ** -6)
        self.buttons()
        
    def line_components(self, angle, r):
        x = self.x + (r * cos(radians(angle)))
        y = self.y + (r * sin(radians(angle)))
        return x, y

    def x_y(self, angle, r1, r2):
        x1, y1 = self.line_components(angle=angle, r=r1)
        x2, y2 = self.line_components(angle=angle, r=r2)
        return x1, y1, x2, y2
        
    def rotate(self):
        frame, scale, spinbox = self.scale_and_spinbox()
        i = 0
        while True:
            x1, y1, x2, y2 = self.x_y(angle=i, r1=0, r2=100)
            c = self.create_line(
                x1, 
                y1, 
                x2,
                y2,
                fill="black", 
                width=self.width
            )
            self.update()
            if self._stop:
                self.stopped.append(c)
                scale.destroy()
                spinbox.destroy()
                frame.destroy()
                break
            try:
                time.sleep(self.doublevar.get())
            except ValueError:
                time.sleep(0)
            self.master.update()
            self.delete(c)
            i += 1
                                       
    def start(self):
        if not self._start and self._stop:
            for i in self.stopped:
                self.delete(i)
            self._start = True
            self._stop = False
            t = threading.Thread(target=self.rotate)
            t.start()
            
    def stop(self):
        self._start = False
        self._stop = True
        
    def buttons(self):
        for i, j in zip(["start", "stop"], [self.start, self.stop]):
            button = tk.Button(master=self.master, text=i, command=j)
            button.pack()
           
    def scale_and_spinbox(self):
        frame = tk.Frame(master=self.master)
        frame.pack()
        
        spinbox = tk.Spinbox(master=frame)
        spinbox["from"] = self.minvar.get()
        spinbox["textvariable"] = self.doublevar
        spinbox["to"] = self.maxvar.get()
        spinbox["increment"] = self.stepvar.get()
        spinbox["width"] = 8
        spinbox.pack(side="left")
        
        scale = tk.Scale(master=frame, orient="horizontal")
        scale["length"] = 200
        scale["sliderlength"] = 15
        scale["variable"] = self.doublevar
        scale["digits"] = 7
        scale["resolution"] = self.stepvar.get()
        scale["from"] = self.minvar.get()
        scale["to"] = self.maxvar.get()
        scale["showvalue"] = False        
        scale.pack(side="left")
        
        return frame, scale, spinbox

        
if __name__ == "__main__":
    master = tk.Tk()
    master.geometry(
        f"{master.winfo_screenwidth()}x{master.winfo_screenheight()}"
    )
    rotating_object = RotatingObject(master=master)
    rotating_object.mainloop()

Scale widgetı ile alakalı.

The default resolution is 1, which causes 
the widget to round all values to the 
nearest integer value. You can use the 
resolution option to specify another 
resolution; use -1 to disable rounding

http://effbot.org/tkinterbook/scale.htm

Ayrıca en sonda rotating_object.mainloop() yazmışsın. master.mainloop() olmalı.

1 Beğeni

Teşekkürler.
rotating_object.mainloop() da olur.

Merhaba. Kodunuzla biraz uğraşırken, scale_and_spinbox fonksiyonunda yapılan işlemlerden sonra self.doublevar değişkeninin kendisine tanımlanan değerden başka bir değer aldığını fark ettim. Nedenini bilmiyorum, araştırmaya da üşendim ama aşağıdaki gibi bir düzeltme yapınca istediğiniz şekilde çalışıyor.

[...]
        spinbox = tk.Spinbox(master=frame)
[...]
        spinbox["textvariable"] = self.doublevar # pack fonksiyonu çağrılmadan önce bunu yapmak sorunu çözüyor
        spinbox.pack(side="left")
        
        scale = tk.Scale(master=frame, orient="horizontal")
[...]
        scale["variable"] = self.doublevar # pack fonksiyonu çağrılmadan önce bunu yapmak sorunu çözüyor
        scale.pack(side="left")
[...]

Bu arada, eğer dönüş hızını kontrol etmek istiyorsanız, frame başına düşen döndürme açısı ile oynamanız iş görür gibi. Kodunuzun geri kalanı ile uğraşmadım ama bu şekilde implement etmek daha mantıklı. Hatta biraz ilerletip bir vektör sınıfı yazabilirsiniz, güzel olabilir.

Geçenlerde şöyle bir şey karalamıştım bir proje için: vector.py

1 Beğeni

Merhaba. Cevabınız için teşekkür ederim. Şu an bahsettiğiniz değişikliği yapamıyorum. Ama eve geçince deneyeceğim.

Dönüş hızıyla alakalı bir sorun yaşamadım. Sadece bahsettiğim ön-tanımlı değeri belirlerken değer ondalık bir değer almıyordu. Dönme açısı da while döngüsünün her bir adımında 1 derece artıyor. time.sleep() fonksiyonuyla da her bir adımda ne kadar süre beklenmesi gerektiği belirleniyor.

Bu arada vector.py dosyasına da eve geçince bakacağım. Tekrar teşekkür ederim.

@nwxnk

spinbox["textvariable"] anahtar kelime argümanının, spinbox["increment"] anahtar kelime argümanından önce veya sonra tanımlanmasının bir etkisi yok.

Ancak;
scale["variable"] anahtar kelime argümanı, scale["resolution"] anahtar kelime argümanından sonra tanımlanırsa sorun çözülüyor.

Teşekkür ederim.