Tkinter Y Koordinatı

Evet burda biraz plansız ve doğaçlama ilerledim sanırım :smiley:

Koordinatları aldıktan sonra dönüştürüp çizerken tekrar eski hakine getirmek yerine çizim için ayrıca giriş koordinatlarını saklayabilirdiniz.

1 Beğeni

Acaba buradaki gibi birşeyden mi bahsediyorsunuz:
https://tr.coredump.biz/questions/42476040/tkinter-get-mouse-coordinates-on-click-and-use-them-as-variables

Hallettim. Sanırım bu kod istediğiniz gibi çalışacak:

from tkinter import *
from tkinter import messagebox as msg
import tkinter.ttk as ttk


noktalar = []
class Nokta:
    def __init__(self,x,y):
        self.x=x
        self.y=y

class AlanKatiliDogrular(Frame):
    ayirici = ","

    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        self.parent = parent

        self.canvas = Canvas(self, bg="gray")
        self.hud = Frame(self)


        self.kframe = Frame(self.hud)
        self.kgiren = StringVar()
        self.kgiren.trace(W, self.onayla)
        self.kgirdi = ttk.Entry(self.kframe, textvariable=self.kgiren)
        self.keklebuton = ttk.Button(self.kframe, text="EKLE", command=self.kekle)
        self.kscroll = ttk.Scrollbar(self.kframe)
        self.kliste = Listbox(
            self.kframe,
            height=5,
            state=DISABLED,
            font="Calibri 12 bold",
            yscrollcommand=self.kscroll.set)

        self.kscroll.config(command=self.kliste.yview)
        self.ksilbuton = ttk.Button(self.kframe, text="KALDIR", command=self.kkaldir)
        self.ktumsilbuton = ttk.Button(
            self.kframe,
            text="TÜM NOKTALARI KALDIR",
            command=self.ktumkaldir)

        self.cizbuton = ttk.Button(self.kframe, text="ÇİZ", command=self.ciz)


        self.kgirdi.bind("<Return>", self.kekle)
        self.canvas.bind("<Button-1>", self.click_action)

        self.pack_widgets()
        self.repack_canvas()


    def koor_donustur(self, x=None, y=None): # VARSAYILANA ÇEVİRİRKEN
        if x == None and y == None:
            raise ValueError("En az bir girdi girmelisiniz!")
        elif x == None:
            y += int(self.parent.winfo_screenheight() / 2)
            return y
        elif y == None:
            x += int((self.parent.winfo_screenwidth() - 245) / 2)
            return x
        else:
            x += int((self.parent.winfo_screenwidth() - 245) / 2)
            y += int(self.parent.winfo_screenheight() / 2)
            return (x, y)


    def koor_geri_cevir(self, x=None, y=None): # ÖZEL KOORDİNAT SİSTEMİ
        if x == None and y == None:
            raise ValueError("En az bir girdi girmelisiniz!")
        elif x == None:
            y -= int(self.parent.winfo_screenheight() / 2)
            return -y
        elif y == None:
            x -= int((self.parent.winfo_screenwidth() - 245) / 2)
            return x
        else:
            x -= int((self.parent.winfo_screenwidth() - 245) / 2)
            y -= int(self.parent.winfo_screenheight() / 2)
            return (x, -y)


    def click_action(self, event):
        if not self.siniri_gecti_mi():
            noktalar.append(Nokta(event.x,event.y))
            self.kliste.config(state=NORMAL)
            self.kliste.insert(END, str(self.koor_geri_cevir(x=event.x)) \
                                    +str(AlanKatiliDogrular.ayirici) \
                                    +str(self.koor_geri_cevir(y=event.y)))
            self.kliste.config(state=DISABLED)
            self.repack_canvas(event)


    def repack_canvas(self,event=None):
        self.canvas.delete(ALL)
        
        for i in noktalar:
            self.canvas.create_oval(
                i.x - 3,
                i.y - 3,
                i.x + 3,
                i.y + 3,
                fill="yellow")

        self.canvas.create_line(
            self.koor_donustur(x=0),
            self.koor_donustur(y=self.parent.winfo_screenwidth()) * -1,
            self.koor_donustur(x=0),
            self.koor_donustur(y=self.parent.winfo_screenwidth()),
            fill="dark gray"
        )

        self.canvas.create_line(
            self.koor_donustur(x=self.parent.winfo_screenheight()) * -1,
            self.koor_donustur(y=0),
            self.koor_donustur(x=self.parent.winfo_screenheight()),
            self.koor_donustur(y=0),
            fill="dark gray"
        )


    def ciz(self):
        for i in self.koor_eslesmeler():
            self.canvas.create_line(i[0][0], i[0][1], i[1][0], i[1][1])


    def onayla(self, *args):
        gecerliler = "1234567890-" + AlanKatiliDogrular.ayirici
        veri = self.kgirdi.get()
        gecerli_mi = all(True if i in gecerliler else False for i in veri)
        if not gecerli_mi:
            self.kgiren.set("".join(x for x in veri if x in gecerliler))


    def kekle(self, *args):
        veri = self.kgiren.get().split(AlanKatiliDogrular.ayirici)
        en = self.parent.winfo_screenwidth()
        boy = self.parent.winfo_screenheight()
        if self.giris_gecerli_mi():
            if not self.siniri_gecti_mi():
                self.kliste.config(state=NORMAL)
                self.kliste.insert(END, self.kgirdi.get())
                self.kliste.config(state=DISABLED)
                self.kgirdi.delete(0, END)
                self.repack_canvas()
        else:
            msg.showwarning(
                ">- UYARI -<", "HATALI GİRİŞ YAPTINIZ !\nÖRNEK GİRİŞ: 300{}467".format(AlanKatiliDogrular.ayirici))


    def koor_eslesmeler(self):
        ktumliste = list()
        for i in noktalar:
            ktumliste.append((i.x, i.y))

        eslesmeler = list()

        try:
            for i in range(0, len(ktumliste)):
                eslesmeler.append((ktumliste[i], ktumliste[i+1]))
        except IndexError:
            pass
        finally:
            try:
                eslesmeler.append((ktumliste[-1], ktumliste[0]))
            except IndexError:
                pass

        return eslesmeler


    def siniri_gecti_mi(self):
        if len(self.kliste.get(0, END)) < 4:
            return False
        else:
            msg.showwarning(
                ">- UYARI -<",
                "'ŞİMDİLİK' YALNIZCA ÜÇGEN VE\nKARE GİRİŞLERİ YAPABİLİRSİNİZ!")
            return True


    def giris_gecerli_mi(self):
        demo_canvas = Canvas(self)
        try:
            demo_canvas.create_line(self.kgiren.get().split(",")[0],
                                    self.kgiren.get().split(",")[1],
                                    0, 0)
            del demo_canvas
            return True
        except (TclError, IndexError):
            del demo_canvas
            return False


    def kkaldir(self):
        self.kliste.config(state=NORMAL)
        self.kliste.delete(END)
        self.kliste.config(state=DISABLED)
        self.canvas.delete(LAST)
        noktalar.pop()
        self.repack_canvas()


    def ktumkaldir(self):
        self.kliste.config(state=NORMAL)
        for i in self.kliste.get(0, END):
            self.kliste.delete(END)
        self.kliste.config(state=DISABLED)
        noktalar.clear()
        self.repack_canvas()
  


    def pack_widgets(self):
        self.canvas.pack(fill=BOTH, expand=TRUE, side=LEFT)
        self.hud.pack(fill=Y, side=RIGHT)


        self.kgirdi.grid(row=0, column=0, columnspan=2, sticky=E+W, pady=1)
        self.keklebuton.grid(row=1, column=0, columnspan=2, sticky=E+W, pady=1)
        self.kliste.grid(row=2, column=0, sticky=E+W, pady=1)
        self.kscroll.grid(row=2, column=1, sticky=N+S, pady=1)
        self.ksilbuton.grid(row=3, column=0, columnspan=2, sticky=E+W, pady=1)
        self.ktumsilbuton.grid(row=4, column=0, columnspan=2, sticky=E+W, pady=1)
        self.kframe.pack(side=RIGHT)

        ttk.Separator(self.kframe, orient=HORIZONTAL).grid(row=5, columnspan=2, pady=40)

        self.cizbuton.grid(row=6, column=0, columnspan=2, sticky=E+W)


def main():
    root = Tk()
    root.title("PENCERE"*30)
    root.minsize(650, 400)

    g1 = AlanKatiliDogrular(root)
    g1.pack(fill=BOTH, expand=TRUE)


    root.mainloop()


if __name__ == '__main__':
    main()

1 Beğeni

Yardımınız için teşekkürler.

Onun geometri tarafını da size bırakalım artık :smiley: Benim o konu hakkında çok bilgim yok. İstiyorsanız yeni bir konu açarsınız o işlem ile alakalı.

1 Beğeni

Önemli değil. Kodumda anlamadığınız bir yer oldu ise sorabilirsiniz.

1 Beğeni

Aslında bir sorum var.

Bunlardan nasıl kurtulabilirim acaba :smiley:

Onların ikisi de şuanda kullanılıyor, yani kurtulmak yerine belki daha sade bir hale getirebilirsiniz. Neden kaldırmak istediniz?

1 Beğeni

Onların işlevlerini yeni koordinat sistemiyle halledip onları kaldırsam daha mantıklı olmaz mı?

Yeni koordinat sisteminden kastınız analitik düzlem sanırım. Analitik düzleme çevirmek için hala o fonksiyonlar kullanılıyor zaten. Eğer yapabiliyorsanız koddaki gereksiz kullanımlarını bulup daha kısa bir hale getirebilirsiniz.

1 Beğeni

Sizce bu işlemleri Nokta class’ının içine yazsam mantıklı olur mu?

Olabilir, sonuçta onlar üzerinde işlem yapacağız. Ancak şunu hatırlatıyım, Nokta sınıfı noktaların ekrana çizileceği koordinatları saklıyor. Siz geometrik işlemlerinizde sağdaki kutuda yazan koordinatları kullanacaksınız büyük ihtimalle.Tabii isterseniz o asıl koordinatları da birer nitelik haline getirebilirsiniz.

1 Beğeni

Sağdaki kutuyu kullanmam gerektiğini unutmuşum. Yardımınız için tekrar teşekkürler.

Önemli değil, dediğim gibi onları her seferinde fonksiyona vermek yerine en başta yine bir listeye kayıt da edebilirsiniz.

1 Beğeni

Hangi koordinat sisteminden hangisine donustururken? Kodda koor_donustur diye bir fonksiyon var, ondan mi bahsediyoruz? koor_geri_cevir duzgun calisiyor mu?

Hangi koordinat sisteminde?
Orijin nerede?

Y koordinatinin orijinin uzerindeyken negatif, altindayken pozitif deger almasi yukaridaki soruna sebep olarak soylenmis ama galiba bu durumun yanlis oldugu ima ediliyor? Eger yanlisligi belirtiyorsa, iki koordinat sisteminde de boyle mi olmasi lazim, yoksa ikisinde de tersi mi olmasi lazim?


Koordinat sistemi ceviren fonksiyonlarin hangi sistemden hangisine cevirdigini belirtmeleri lazim, su haliyle kafa karistiriyorlar. (kanvastan_mantiksala/mantiksaldan_kanvasa veya programin sistemi ima edilerek tk_den/tk_ye olabilir mesela)

Bazen x alip x dondurup, bazen y alip y dondurup bazen de (x, y) alip (x, y) dondurmeleri de kafa karistirici ve kendini tekrar eden kod iceriyor. x alip x ve y alip y donduren iki fonksiyon ve bunlari cagirip (x, y) alip (x, y) donduren ucuncu bir fonksiyona ayrilmalari lazim. Ben olsam (x, y) alip (x, y) donduren tek bir fonksiyon yazip her yerde onu kullanirim. kliste.insert’e eval edilerek yollanan sihirle nasil calisir, bilmiyorum.

Genel olarak Tk koduyla mantiksal kodun ayrilmasi lazim. Mesela verilen noktalar Listbox’ta Tk’nin istedigi sekilde tutulup Tk’nin abuk fonksiyonlariyla islenecegine, list’te tutulup sadece gerektiginde Listbox’a cevrilmeliler. Programi once konsoldan calisacak sekilde tasarlayip sonra grafik arayuzune baglamak yardimci olabilir.

Bu konu hakkında aklıma bir fikir geldi, bir şeklin kütle merkezinden geçen her doğru onu aynı alana sahip iki parçaya bölüyor diye biliyorum. Eğer bu konuda yanılmıyor isem bunu koda dönüştürmek kolay olacaktır. Sonuçta şekillerin köşelerinin koordinatlarını biliyoruz, okulda da öyle şeyleri pek öğretmiyorlar ancak geometride bu işlemi yaparken kullanacağımız formüller mevcut.

1 Beğeni

Peki bunu nasıl yapabilirim.

Bu konu ilgimi çektiği için ben yapacağım zaten. Siz kendiniz de uğraşmak istiyorsanız iki doğrunun kesiştiği noktayı bulmamızı sağlayan bir formüle ihtiyacınız olacak. Daha sonra örneğin şeklimiz bir ABC üçgeni ise A noktasından |CB| nin orta noktasına giden doğruyu bulacaksınız. Daha sonra da B noktasından |AC| nin orta noktasına giden doğruyu bulacaksınız. Bu iki doğrunun kesiştiği noktayı verdiğim linkten yardım alarak bulduğunuzda üçgenin kütle merkezini bulmuş olacaksınız. Bu kütle merkezinden geçen her doğru üçgeni alanları eşit iki parçaya böler.

Verdiğim link tek başın anlaşılır gelmeyebiilir, bu yüzden konunun javascript ile uygulandığı bir örnek video atıyorum:

Kodda biraz oynama yapmam gerekti. Bazı fonksiyonların ismini ve içeriğini değiştirdim. Siz de bir kod yazarken fonksiyonların anlaşılabilir isimlere sahip olmasına dikkat edin lütfen. Bu kod üçgenler için kütle merkezini buluyor, bu kütle merkezinden geçen herhangi bir doğru işinizi görecektir:

from tkinter import *
from tkinter import messagebox as msg
import tkinter.ttk as ttk

def RayCast(x1,y1,x2,y2,x3,y3,x4,y4): # iki doğru kesişiyorsa kesişme noktasını döndürür
    """Is the ray intersect with the line or not."""

    bölen = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
    if bölen == 0: return False

    t = ((x1-x3)*(y3-y4)-(y1-y3)*(x3-x4))/bölen
    if not 1>t>0:
        return False
    u = -((x1-x2)*(y1-y3)-(y1-y2)*(x1-x3))/bölen
    if not u>0:
        return False
    return (x1+t*(x2-x1),y1+t*(y2-y1))

def find_middle(x1,y1,x2,y2): # doğru parçasının orta noktasını bulur.
    xd = x2 - x1
    yd = y2 - y1
    return x1 + xd/2 , y1 + yd/2

def kütle_merkezi_bul(*noktalar):
    if len(noktalar) == 3:
        x1, y1 = noktalar[0].x, noktalar[0].y
        x2, y2 = noktalar[1].x, noktalar[1].y
        x3, y3 = noktalar[2].x, noktalar[2].y

        orta = find_middle(x1,y1,x2,y2)
        orta2 = find_middle(x2,y2,x3,y3)
        
        x1, y1, x2, y2 = noktalar[2].x, noktalar[2].y, orta[0], orta[1]
        
        x3, y3, x4, y4 = noktalar[0].x, noktalar[0].y, orta2[0], orta2[1]
        
        kütle_merkezi = RayCast(x1,y1,x2,y2,x3,y3,x4,y4)
        return kütle_merkezi

analitik_noktalar = []
noktalar = []
class Nokta:
    def __init__(self,x,y):
        self.x=x
        self.y=y

    def __repr__(self):
        return "Nokta({},{})".format(self.x,self.y)


ayirici = ","
class MainFrame(Frame):

    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.parent = parent

        self.canvas = Canvas(self, bg="gray")
        self.hud = Frame(self)


        self.kframe = Frame(self.hud)
        self.kgiren = StringVar()
        self.kgiren.trace(W, self.onayla)
        self.kgirdi = ttk.Entry(self.kframe, textvariable=self.kgiren)
        self.keklebuton = ttk.Button(self.kframe, text="EKLE", command=self.nokta_ekle)
        self.kscroll = ttk.Scrollbar(self.kframe)
        self.kliste = Listbox(
            self.kframe,
            height=5,
            state=DISABLED,
            font="Calibri 12 bold",
            yscrollcommand=self.kscroll.set)

        self.kscroll.config(command=self.kliste.yview)
        self.ksilbuton = ttk.Button(self.kframe, text="KALDIR", command=self.nokta_kaldir)
        self.ktumsilbuton = ttk.Button(
            self.kframe,
            text="TÜM NOKTALARI KALDIR",
            command=self.tum_noktaları_kaldir)

        self.cizbuton = ttk.Button(self.kframe, text="ÇİZ", command=self.ciz)


        self.kgirdi.bind("<Return>", self.nokta_ekle)
        self.canvas.bind("<Button-1>", self.click_action)

        self.pack_widgets()
        self.repack_canvas()

    def analitik_to_canvas(self,x,y):
        x += int((self.parent.winfo_screenwidth() - 181) / 2)
        y += int(self.parent.winfo_screenheight() / 2)
        return (x, y)

    def canvas_to_analitik(self,x,y):
        x -= int((self.parent.winfo_screenwidth() - 181) / 2)
        y -= int(self.parent.winfo_screenheight() / 2)
        return (x, -y)

    def click_action(self, event):
        if not self.siniri_gecti_mi():
            noktalar.append(Nokta(event.x,event.y))
            self.kliste.config(state=NORMAL)
            self.kliste.insert(END, str(self.canvas_to_analitik(event.x,event.y)))
            self.kliste.config(state=DISABLED)
            self.repack_canvas(event)
            analitik_noktalar.append(Nokta(*self.canvas_to_analitik(event.x,event.y)))


    def repack_canvas(self,event=None):
        self.canvas.delete(ALL)
        
        for i in noktalar:
            self.canvas.create_oval(
                i.x - 3,
                i.y - 3,
                i.x + 3,
                i.y + 3,
                fill="yellow")

        self.canvas.create_line(
            0,
            self.analitik_to_canvas(0,0)[1],
            self.parent.winfo_screenwidth(),
            self.analitik_to_canvas(0,0)[1],
            fill="dark gray"
        )

        self.canvas.create_line(
            self.analitik_to_canvas(0,0)[0],
            0,
            self.analitik_to_canvas(0,0)[0],
            self.parent.winfo_screenheight(),
            fill="dark gray"
        )


    def ciz(self):
        for i in self.koor_eslesmeler():
            self.canvas.create_line(i[0][0], i[0][1], i[1][0], i[1][1])
        merkez = kütle_merkezi_bul(*analitik_noktalar)
##        print(merkez)
        merkez = self.analitik_to_canvas(merkez[0],-merkez[1])
##        print(merkez)
        self.canvas.create_oval(merkez[0] -3,
                                merkez[1] -3,
                                merkez[0] +3,
                                merkez[1] +3,
                                fill="red"
                                )

    def onayla(self, *args):
        gecerliler = "1234567890-" + ayirici
        veri = self.kgirdi.get()
        gecerli_mi = all(True if i in gecerliler else False for i in veri)
        if not gecerli_mi:
            self.kgiren.set("".join(x for x in veri if x in gecerliler))


    def nokta_ekle(self, *args):
        if self.giris_gecerli_mi() and not self.siniri_gecti_mi():
            veri = self.kgiren.get().split(ayirici)
##            print(veri)
            analitik_noktalar.append(Nokta(int(veri[0]),int(veri[1])))
            noktalar.append(Nokta(*self.analitik_to_canvas(int(veri[0]),-int(veri[1]))))
            en = self.parent.winfo_screenwidth()
            boy = self.parent.winfo_screenheight()
            self.kliste.config(state=NORMAL)
            self.kliste.insert(END, self.kgirdi.get())
            self.kliste.config(state=DISABLED)
            self.kgirdi.delete(0, END)
            self.repack_canvas()
##            print("update")
        else:
            msg.showwarning(
                ">- UYARI -<", "HATALI GİRİŞ YAPTINIZ !\nÖRNEK GİRİŞ: 300{}467".format(ayirici))


    def koor_eslesmeler(self):
        ktumliste = list()
        for i in noktalar:
            ktumliste.append((i.x, i.y))

        eslesmeler = list()

        try:
            for i in range(0, len(ktumliste)):
                eslesmeler.append((ktumliste[i], ktumliste[i+1]))
        except IndexError:
            pass
        finally:
            try:
                eslesmeler.append((ktumliste[-1], ktumliste[0]))
            except IndexError:
                pass

        return eslesmeler


    def siniri_gecti_mi(self):
        if len(self.kliste.get(0, END)) < 4:
            return False
        else:
            msg.showwarning(
                ">- UYARI -<",
                "'ŞİMDİLİK' YALNIZCA ÜÇGEN VE\nKARE GİRİŞLERİ YAPABİLİRSİNİZ!")
            return True


    def giris_gecerli_mi(self):
        demo_canvas = Canvas(self)
        try:
            demo_canvas.create_line(self.kgiren.get().split(",")[0],
                                    self.kgiren.get().split(",")[1],
                                    0, 0)
            del demo_canvas
            return True
        except (TclError, IndexError):
            del demo_canvas
            return False


    def nokta_kaldir(self):
        self.kliste.config(state=NORMAL)
        self.kliste.delete(END)
        self.kliste.config(state=DISABLED)
        self.canvas.delete(LAST)
        try:
            noktalar.pop()
            analitik_noktalar.pop()
        except IndexError: pass
        self.repack_canvas()


    def tum_noktaları_kaldir(self):
        self.kliste.config(state=NORMAL)
        for i in self.kliste.get(0, END):
            self.kliste.delete(END)
        self.kliste.config(state=DISABLED)
        noktalar.clear()
        analitik_noktalar.clear()
        self.repack_canvas()
  


    def pack_widgets(self):
        self.canvas.pack(fill=BOTH, expand=TRUE, side=LEFT)
        self.hud.pack(fill=Y, side=RIGHT)


        self.kgirdi.grid(row=0, column=0, columnspan=2, sticky=E+W, pady=1)
        self.keklebuton.grid(row=1, column=0, columnspan=2, sticky=E+W, pady=1)
        self.kliste.grid(row=2, column=0, sticky=E+W, pady=1)
        self.kscroll.grid(row=2, column=1, sticky=N+S, pady=1)
        self.ksilbuton.grid(row=3, column=0, columnspan=2, sticky=E+W, pady=1)
        self.ktumsilbuton.grid(row=4, column=0, columnspan=2, sticky=E+W, pady=1)
        self.kframe.pack(side=RIGHT)

        ttk.Separator(self.kframe, orient=HORIZONTAL).grid(row=5, columnspan=2, pady=40)

        self.cizbuton.grid(row=6, column=0, columnspan=2, sticky=E+W)


def main():
    root = Tk()
    root.title("PENCERE"*30)
    root.minsize(650, 400)
    root.geometry("{}x{}+0+0".format(root.winfo_screenwidth(),root.winfo_screenheight()-50))

    global g1
    g1 = MainFrame(root)
    g1.pack(fill=BOTH, expand=TRUE)


    root.mainloop()


if __name__ == '__main__':
    main()

Kare için daha sonra yapacağım, farklı bir işlem gerektiriyor.

1 Beğeni