Merhaba, tkinter ile bir menü yapıyorum arka plana canvas kullanarak bir resmi ekledim sonrasında buton olarak da bir resim ekledigimde(png) arka planda varsayılan olarak gelen bir renk var bundan kurtulmanın bir yolu varmı ?
Mümkün ama bunun için biraz farklı bir yol izlemek gerekiyor çünkü tkinter widgetlerinin şeffaf arka plan özelliği yok.
Eğer arka planı şeffaf olan bir button oluşturmak istiyorsak, aslında canvas nesnelerini bu amaçla kullanabiliriz. Örneğin bir tane resim ekleyebiliriz ve eklediğimiz resme bir takım olaylar bağlayabiliriz. Bu olaylar resmin button gibi davranmasını sağlayabilir.
Aşağıda bu konuyla alakalı bir örnek görüyorsunuz.
Bu örnekte kullanılan dosyalar şunlar:
import tkinter as tk
from PIL import Image, ImageTk, ImageOps
root = tk.Tk()
# Arka plan olarak kullanılacak resmi açalım.
_background_image = Image.open("background.jpeg")
# Resmin genişlik ve yükselik değerlerini alalım.
width, height = _background_image.size
# Bir tane PhotoImage nesnesi oluşturalım.
background_image = ImageTk.PhotoImage(_background_image)
# Düğme olarak kullanılacak ikonu açalım.
_play_icon = Image.open("play.png")
# Bir tane PhotoImage nesnesi oluşturalım.
play_icon = ImageTk.PhotoImage(_play_icon)
# Canvas nesnesini oluşturuyoruz.
canvas = tk.Canvas(master=root, width=width, height=height)
canvas.pack()
# Arka planı ekrana yerleştiriyoruz.
canvas.create_image(0, 0, image=background_image, anchor="nw")
def on_button_1(img, status):
if status == "pressed": # Eğer resme tıklandıysa
# Resmin modunu RGBA olarak değiştirelim.
_img = img.convert(mode="RGBA")
# Resmi tayflara ayıralım. İkinci -> [1] tayfı seçelim.
# İsterseniz farklı tayflarda nasıl sonuçlar oluşuyor
# deneyebilirsiniz.
_img = _img.split()[1]
# Resmin modunu greyscale olarak değiştirelim.
_img = _img.convert(mode="L")
# Siyah yerler siyah kalsın, beyaz yerler green olsun.
_img = ImageOps.colorize(_img, black="black", white="green")
# Resmin modunu tekrar RGBA olarak ayarlayalım.
_img = _img.convert("RGBA")
# Siyah yerleri transparan bir hale getirelim.
_img.putdata(
[
(0, 0, 0, 0) if all(i[j] < 50 for j in range(3)) else i
for i in _img.getdata()
]
)
# Oluşturduğumuz yeni resim ile yeni bir PhotoImage
# nesnesi oluşturalım.
_img = ImageTk.PhotoImage(_img)
print("Button pressed!")
else: # Eğer button1 serbest bırakıldıysa
# Resim orijinal hale geri gelsin.
_img = ImageTk.PhotoImage(img)
# PhotoImage garbage collector'a gitmesin diye, PhotoImage'i canvas
# nesnesine bağlıyoruz.
canvas._img = _img
# button tagına sahip canvas nesnesinin image özelliğini değiştiriyoruz.
canvas.itemconfig("button", image=canvas._img)
# Button olarak görev yapacak resim nesnemiz.
button = canvas.create_image(
width // 2,
height // 2,
image=play_icon,
anchor="center",
tag="button"
)
# Bu resme bazı olaylar ekleyelim.
# Olay 1: <ButtonPress-1>
canvas.tag_bind(
tagOrId=button,
sequence="<ButtonPress-1>",
func=lambda event: on_button_1(
img=_play_icon,
status="pressed"
)
)
# Olay 2: <ButtonPress-1>
canvas.tag_bind(
tagOrId=button,
sequence="<ButtonRelease-1>",
func=lambda event: on_button_1(
img=_play_icon,
status="released"
)
)
root.mainloop()
Resmin ortasında duran play
simgesine tıklamadan önce resim şu şekilde görünüyor:
Resme tıkladığımızda, play
simgesinin rengi aşağıdaki gibi değişiyor:
Fare’yi serbest bıraktığımızda ise resmin rengi tekrar eski haline dönüyor. Bu arada düğmeye bastığımızda ekrana button pressed
yazısı yazdırılıyor.
Cevapladığınız için teşekkürler aklıma bir kaç soru takıldı bunları sormak isterim ve birde problemle karşılaştım.
öncelikle sorunumdan bahsedeyim eğer bir resime farenin sol tuşunu basılı tutarsak resimin arka planında yeşil bir ekran gözüküyor ve sol tuşa basılı tutmayı bırakana kadar orada kalıyor.
Sorularım:
herhangi bir buton vs. ekledigimizde kanvasın üzerinde degilde aşşagısında yer alıyor her seferine place ile yer mi belirtmemiz gerek yoksa pack kullanarak yapmakta mümkünmüdür.
Herhangi bir resimin yerini degiştirmek istedigimde width // 2,
height // 5, parametrelerini mi kullanmalıyım place felan kullanamazmıyım bunuda sormadan geçmek istemem
Resmin o yeşil gözüken kısımlarını silmediğiniz için komple resmi alıyor sanırım. Genelde, bir resim kullanacaksam, o resme bir katman ekler sonra da resmin çerçevesi dahil olmak üzere istenmeyen kısımları resimden kaldırırım. Bunun için GIMP
kullanabilirsiniz.
place
veya pack
kullanmıyoruz artık. Çünkü burada widgetlerimizi canvas
nesnelerinden oluşturuyoruz. create_window
ile eğer başka bir tkinter
widgeti ekleyecekseniz, ekleme sıranız önemli hale gelir.
Örneğin, button
görevi görecek bir resim ekleyip, onun da üstüne create_window
ile bir tk.Frame
’i getirebilirsiniz. Ancak böyle yaparsanız button
görevi görecek olan resim, frame
tarafından kaplanmış olur. Ekrana yerleşecek widgetleri tasarlarken, buna dikkat etmek gerekiyor.
Aynen, ekran koordinatlarına göre nesneleri yerleştirmek lazım. Bu yöntemle maalesef place
, grid
ve pack
metodlarını kullanamazsınız. Ama ekranın koordinatlarını kullanmak da zevkli (bence), her şeyi hesaplayarak kendiniz belirlemiş olursunuz.
Canvas ile ilk deneyimim olduğu için biraz yadırğadım herhalde zamanla alışırım
spliti 3 yapıtığımda ise resmi yeşile boyuyor basılı tutarken galiba farklı bir sorun var
Boyama işlemini yapan kod parçalarını kullandığım ikon için yazmıştım, dilerseniz kaldırabilirsiniz tabi. Benim kullandığım resim, tek bir renge sahip olduğu için, resim üzerinde yapılan işlemi de ona göre ayarladım. Sizin eklediğiniz resimde çok değişik renkler var. Dolayısıyla aslında PIL kütüphanesine biraz bakarak, birçok rengi olan resimlerin renklerini nasıl değiştirebileceğinizi öğrenebilirsiniz.
img.split()
4 elemanlı bir tuple
verisi döndürüyor ve her bir eleman (kanal) üzerinde yapılan değişiklik farklı sonuçlar üretiyor. Bu 4 kanal RGBA. A yani alpha şeffaflık kanalıdır. Bu yüzden denemeler yapmanız gerektiğini söylemiştim. Siz 3. tayfda (şeffaflık kanalında) bir değişiklik yaptığınız için, resmin geri kalan kısımları şeffaflaştırıldı.
Bu renk değiştirme işlemini de, kullanıcının düğmeye basıp basmadığı görsel olarak belli olsun diye eklemiştim.
Öneriler için minnettarım hepsi benim için çok değerli fakat bir şey fark ettim bilmiyorum yanlışmı anladım olayı ama sizinde bi fikrinizi almak isterim.
Tıklama işlemlerine çok takılmayın biri için aslında (Görsel açıdan )
bu şekilde kullanılabilir resime tıkladıgımda sabit bir biçimde duruyor herangi bir problemi yok arka planı vs. temiz şekilde ama ille bir tıklama hissiyatı verilicek olunursa tıklanan resimi anlık olarak kaldırıp yerine biraz daha büyüğü veya küçüğü eklenilebilir daha sonra resim eski haline döndürülür tıklama hissiyatı birazda olsa karşı tarafa geçebilir diye düşündüm.
Elbette, neden olmasın. Tasarımın nasıl olacağını siz belirlersiniz.
Dediğiniz yöntemi test ediyordum fakat bir soru aklıma geldi resim hariç entry,label gibi arka plan rengi olan widgetlerin arka planını nasıl temizleyebilirim ?
widget = tk.Label(canvas,width=20,text="Merhaba")
widget.pack()
canvas.create_window(200, 200, window=widget)
Entry’ye yazı yazılacağı için, arka plan için daha mat renkler kullanılabilir. tk.Label
yerine de create_text
ile yazı oluşturabilirsiniz.