Tkinter Entry girişini kontrol etme

Bir GUI geliştiriyorum ve bu gui de entry kullanıcam fakat entry sadece integer değerleri alması gerekiyor , herhangi sayı dışı bir şey giridliğinde kabul etmemesi ve entrye yazmaması gerekiyor .İnternette bakındım bir cevap bulamadım. Yardımlarınız için şimdiden teşekkürler…

Tkinterda kivy gibi int, string beya float gibi kullanıcı input kısıtlaması varmı tam olarak bilmiyorum. Ama kendiniz bi fonksiyon yazabilirsiniz bununla ilgili.
Örneğin

def ayikla(num) -> float:#sayı ayıkla
   """  """
   veri = str(num)
   try:#eğer string cevrilebilicek ise
   	return round(float(num), 2)
   except:
   	if not veri:#eğer boş string ise
   		return 0.0
   	elif veri.count(",") >= 2:#eğer birden cok virgül var ise sondakini noktaya dönüştür ve gerikalanını yok et
   		d = veri.rsplit(",", 1)
   		return round(float(d[0].replace(",", "") + "." + d[1]), 2)
   	elif veri.count(",") == 1:#virgülün bir adet olması durumunda
   		if len(veri) <= 4:# örn 1,22-12,1-1,2 vs
   			return round(float(veri.replace(",", ".")), 2)
   		elif len(veri) == 5:#1,236 farklı & 123,5-12,35 farklı
   			if veri.index(",") == 1:
   				return round(float(veri.replace(",", "")), 2) #1,236 durumu
   			elif veri.index(",") >= 2:#123,5-12,36 durumu
   				return round(float(veri.replace(",", ".")), 2)
   		elif len(veri) == 6:#1,2362-12,236-123,12-1236,5
   			if veri.index(",") <= 2:#1,2364-12,236 durumu
   				return round(float("".join(veri.replace(",", ""))), 2)
   			elif veri.index(",") >= 3:#123,56-1235,5 durumu
   				return round(float(veri.replace(",", ".")), 2)
   		elif len(veri) >= 7:#12345,6 - 1234,56
   			return round(float(veri.replace(",", ".")), 2)



for i in ["", 1, 1.4, "hebele"]:
   print(ayikla(i))

Yukarıdaki fonksiyon gibi, tabi biraz daha geliştirilmesi gerekebilir.

Merhaba,

Entry'i bir değişkene atayın daha sonra Entry içine yazılmış olan veriyi .get() ile alın.

Bu işlemden sonra şunu uygulayın

try:
    #entry için atanmış değişken ismi userpass olsun
    userpass.get() = int(userpass.get())
    break
except:
    #bu kısım eğer üstteki çalışmaz ise yapılacak işlemdir.
    #if elif else gibi düşünün
    etiket = Label(text="Lütfen sadece rakam giriniz")
    etiket.pack()
2 Beğeni

Uygulamalı örnek göstereyim.

from tkinter import *

class Application(object):
    
    def __init__():

        self.main()

    def main(self):

        self.pencere = Tk()
        self.pencere.geometry("250x250+100+100")
        self.pencere.resizable(FALSE, FALSE)
        
        self.userpass = Entry(self.pencere)
        self.userpass.grid(row=0, column=1)

        self.dugme = Button(self.pencere, text="Kaydet", command=self.kaydet)
        self.dugme.grid(row=1, column=1)

    def kaydet(self):

        entry_degeri = self.userpass.get()
        
        try:
            entry_degeri = int(entry_degeri)
            break

        except:
            self.uyari_etiket = Label(self.pencere, text="LÜTFEN SADECE SAYI GİRİNİZ")
            self.uyari_etiket.grid(row=2, column=1)

app = Application()
mainloop()

inşallah bir yanlışlık olmaz kodları deneyecek platformum yok şuan hata alırsanız -ki inşallah almazsınız- burada iletişimde olalım

Şu işinizi görür sanırım:

import tkinter as tk
import string

root = tk.Tk()

def on_click(event):
    if event.char == "": # sağ- sol ok tuşları ve belki bir kaç özel karakter daha
        return True
    if event.char.isalpha() or event.char.isspace() or event.char in string.punctuation:
        return "break" # event tkinter tarafından işlenmiyor ve basılan tuş entry'e yazılmıyor

entry = tk.Entry()
entry.bind("<Key>", on_click)
entry.pack()

root.mainloop()

Bind’lenen event’lerin tkinter tarafından işlenmesini engellemeyi daha önce de araştırıp bulamamıştım, şimdi burada buldum.


Bir de bunu buldum:

import tkinter as tk

root = tk.Tk()

vcmd = root.register(str.isdigit)

entry = tk.Entry(root, validate = 'all', validatecommand = (vcmd, '%S'))
entry.pack()

root.mainloop()

@tevhidulvahset Kodunuzda birkaç hata var ve bu hali ile çalışmıyor. Ayrıca bu kod entry’e girilenleri en son kontrol eder, OP’nin istediği bu değil:


Kendimiz yazıyoruz, hazır hali yok diye biliyorum ben de.

Bu fonksiyon tam olarak ne işe yarıyor, biraz açabilir misiniz?

>>> ayikla("1,2324")
12324.0
>>> ayikla("12,1")
12.1
>>> 
>>> ayikla("1,2,2")
12.2
>>> ayikla("1.2")
1.2
>>> ayikla("1..2")
>>> ayikla("1.2..")
>>> ayikla("1.2.3")
>>> ayikla("12.3")
12.3
>>> ayikla("1,2.3")
12.3
>>> ayikla("123.123,5")
Traceback (most recent call last):
  File "C:\Users\user\Desktop\deneme.py", line 5, in ayikla
    return round(float(num), 2)
ValueError: could not convert string to float: '123.123,5'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    ayikla("123.123,5")
  File "C:\Users\user\Desktop\deneme.py", line 26, in ayikla
    return round(float(veri.replace(",", ".")), 2)
ValueError: could not convert string to float: '123.123.5'
>>>

Yapmak istediğiniz float gösteriminde . yerine , kullanmak ise geçersiz girişlerde hata verilecek bir şekilde bu kolayca yapılabilir:

def ayikla(text: str) -> float:
    return float(text.replace(",", "."))
    
for i in ("112", "0", "12,23", "213,89000"):
    print(ayikla(i))

Ve bu kodun da OP ile alakası olduğunu sanmıyorum, soruda istenilen entry’nin sadece integer alması, float değil.

1 Beğeni

aslında bu fonksiyonu kendi kodlarına entegre etmesi için örnek olarak verdim. O nokta olayı ise genelde klavyenin sayı bölümündeki virgül tuşu kullanıldığından gerek duymadım. Ki zaten geliştirilebilir diye not düştüm

v = StringVar()
e = Entry(master, textvariable=v)
e.pack()

v.set(“a default value”)
s = v.get()

Bu örnekde gördüğün gibi yapabilirsin. StringVar yerine IntVar() kullanarak int değerde verebilirsin

Bu kullanıcının entry’e alfabetik karakter vermesini engellemiyor, deneyebilirsiniz:

from tkinter import *

root = Tk()
v = IntVar()
e = Entry(textvariable=v)
e.pack()

v.set("12")

root.after(10 * 1000, lambda: print(repr(v.get())))

root.mainloop()