Фоновое изображение tkinter в рамке - PullRequest
0 голосов
/ 18 января 2019

Я хочу поместить фоновое изображение в рамку, это код, который я пытаюсь запустить безуспешно.

import tkinter as tk
from tkinter import *

root = tk.Tk()

F1 = Frame(root)
F1.grid(row=0)

photo = PhotoImage(file="sfondo.png")
label = Label(F1, image=photo)
label.image = photo
label.place(x=0, y=0)

b = tk.Button(label, text="Start")
b.grid(row=8, column=8)

root.mainloop()

Если я запускаю код как этот, отображается только маленькая точка в верхнем левом углу (рамка без чего-либо внутри, даже если я поместил метку внутри нее). Если я заменю родительский ярлык на root, он отображает кнопку с небольшой частью изображения в качестве фона (только периметр кнопки окрашен на несколько пикселей). Однако я хочу получить полностью отображаемое фоновое изображение в кадре, где я могу разместить нужные виджеты.

Я пытался использовать метод place как этот и модуль PIL

import tkinter as tk
from tkinter import *
from PIL import Image, ImageTk

root = tk.Tk()

F1 = Frame(root)
F1.grid(row=0)
image = Image.open("sfondo.png")

render = ImageTk.PhotoImage(image)
img = tk.Label(F1, image=render)
img.image = render
img.place(x=0, y=40)

b = tk.Button(img, text="Start")
b.grid(row=8, column=8)

root.mainloop()

Здесь более или менее возникают те же проблемы, если я устанавливаю родителя метки на root, кнопка отображается с цветным периметром. Если я установил для родителя значение F1, ничего не произойдет, и в обоих случаях, если я установлю для родителя значение root и удаляю кнопку, изображение отображается полностью. Но я хочу, чтобы изображение полностью отображалось в кадре и после наложения на фоновое изображение виджетов.

1 Ответ

0 голосов
/ 18 января 2019

Вы можете поместить изображение в Canvas, а затем поместить в него Button, поместив его в объект окна Canvas , который может содержать любой виджет Tkinter.

Дополнительные виджеты могут быть добавлены аналогичным образом, каждый внутри своего собственного Canvas объекта окна (так как они могут содержать только один виджет каждый). Вы можете обойти это ограничение, поместив виджет Frame в окно Canvas, а затем поместив другие виджеты внутри it .

Вот пример, показывающий, как отобразить один Button:

from PIL import Image, ImageTk
import tkinter as tk

IMAGE_PATH = 'sfondo.png'
WIDTH, HEIGTH = 200, 200

root = tk.Tk()
root.geometry('{}x{}'.format(WIDTH, HEIGTH))

canvas = tk.Canvas(root, width=WIDTH, height=HEIGTH)
canvas.pack()

img = ImageTk.PhotoImage(Image.open(IMAGE_PATH).resize((WIDTH, HEIGTH), Image.ANTIALIAS))
canvas.background = img  # Keep a reference in case this code is put in a function.
bg = canvas.create_image(0, 0, anchor=tk.NW, image=img)

# Put a tkinter widget on the canvas.
button = tk.Button(root, text="Start")
button_window = canvas.create_window(10, 10, anchor=tk.NW, window=button)

root.mainloop()

Скриншот:

screenshot of sample code running

Редактировать

Хотя я не знаю способа сделать это в Frame вместо Canvas, вы можете получить свой собственный подкласс Frame, чтобы упростить добавление нескольких виджетов. Вот что я имею в виду:

from PIL import Image, ImageTk
import tkinter as tk


class BkgrFrame(tk.Frame):
    def __init__(self, parent, file_path, width, height):
        super(BkgrFrame, self).__init__(parent, borderwidth=0, highlightthickness=0)

        self.canvas = tk.Canvas(self, width=width, height=height)
        self.canvas.pack()

        pil_img = Image.open(file_path)
        self.img = ImageTk.PhotoImage(pil_img.resize((width, height), Image.ANTIALIAS))
        self.bg = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.img)

    def add(self, widget, x, y):
        canvas_window = self.canvas.create_window(x, y, anchor=tk.NW, window=widget)
        return widget


if __name__ == '__main__':

    IMAGE_PATH = 'sfondo.png'
    WIDTH, HEIGTH = 350, 200

    root = tk.Tk()
    root.geometry('{}x{}'.format(WIDTH, HEIGTH))

    bkrgframe = BkgrFrame(root, IMAGE_PATH, WIDTH, HEIGTH)
    bkrgframe.pack()

    # Put some tkinter widgets in the BkgrFrame.
    button1 = bkrgframe.add(tk.Button(root, text="Start"), 10, 10)
    button2 = bkrgframe.add(tk.Button(root, text="Continue"), 50, 10)

    root.mainloop()

Результат:

screenshot showing two widget displayed on a frame with a background

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...