如何使用 pysimplegui 为我的 GUI 创建背景?
How can I create a background for my GUI with pysimplegui?
我正在尝试在我的 raspberry pi 上为 运行 创建一个 pysimplegui 应用程序。我设法设置了一张背景图片,但要使其正常工作,我需要打开 2 个 windows,一个用于背景,一个用于我的应用程序的布局(长度 x 宽度输入)。
如何制作一个 pysimplegui 应用程序,在其中向 window 添加背景,同时还能够在其上添加布局?
我目前使用的代码是:
import PySimpleGUI as sg
from io import BytesIO
from PIL import Image
import os
def image_to_data(im):
"""
Image object to bytes object.
: Parameters
im - Image object
: Return
bytes object.
"""
with BytesIO() as output:
im.save(output, format="PNG")
data = output.getvalue()
return data
class GUI:
def __init__(self):
self.size = (1280, 800)
self.background_image = os.path.join(os.getcwd(), 'background.png')
self.im = Image.open(self.background_image)
#background
self.background_layout = [[sg.Image(data=image_to_data(self.im))]]
self.window_background = sg.Window('Background', self.background_layout, no_titlebar=True, finalize=True, margins=(0, 0), element_padding=(0,0), right_click_menu=[[''], ['Exit',]])
#background
self.column1 = [
[sg.Text('Fill in the length', justification='center', font='Helvetica 18')],
[sg.Input(justification='center', key='length'), sg.Text('X', justification='center'), sg.Input(justification='center', key='width')],
[sg.Button('OK', key='OK')],
[sg.Button('Exit', key='Exit')]
]
self.layout = [
[sg.Column(self.column1, element_justification='center')]
]
self.window = sg.Window('Title', keep_on_top=True, layout=self.layout, finalize=True, grab_anywhere=False, transparent_color=sg.theme_background_color(), no_titlebar=True)
self.start()
def start(self):
while True:
window, event, values = sg.read_all_windows()
if event in (sg.WINDOW_CLOSED, 'Exit'):
break
self.window.close()
self.window_background.close()
if __name__ == '__main__':
if os.environ.get('DISPLAY','') == '':
print('DISPLAY variable will be set to :0.0')
os.environ.__setitem__('DISPLAY', ':0.0')
GUI()
else:
print('DISPLAY variable is already set to :0.0')
此代码工作正常,但如果我单击 window 之外的任何位置,我会在我的 window 前面单击包含我 raspberry pi 上的背景图像,window 消失在后面。
我的问题:
有没有办法只创建一个 window 带有背景图像,我可以在其上添加布局?
编辑:考虑到我对 pysimplegui 的经验为 0,并且过去使用 Kivy 做过一些项目,我决定坚持使用 Kivy。结束这个问题。
Kivy 示例代码:
main.py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config
Config.set('graphics', 'width', '1280')
Config.set('graphics', 'height', '800')
class MainWidget(BoxLayout):
pass
class TheLabApp(App):
pass
if __name__ == '__main__':
TheLabApp().run()
thelab.kv:
#:kivy 2.1.0
MainWidget:
<MainWidget>:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'assets/background.png' #note how simple it is to add a background image
BoxLayout:
orientation: 'vertical'
Label:
BoxLayout:
orientation: 'vertical'
Label:
text: 'Fill in the length'
font_size: 30
BoxLayout:
orientation: 'horizontal'
TextInput:
id: width
multiline: False
font_size: 30
#size_hint: (0.5, 1)
Label:
text: 'X'
font_size: 20
TextInput:
id: length
multiline: False
font_size: 20
Label:
这是示例,但使用了 tkinter 代码。
import os
from io import BytesIO
from PIL import Image
import PySimpleGUI as sg
def image_to_data(im):
with BytesIO() as output:
im.save(output, format="PNG")
data = output.getvalue()
return data
def make_background(window, file, main_frame):
global images
def find_frames(widget):
widgets = list(widget.children.values())
if isinstance(widget, (sg.tk.Frame, sg.tk.LabelFrame)):
widget.update()
x, y = widget.winfo_rootx() - x0, widget.winfo_rooty() - y0
width, height = widget.winfo_width(), widget.winfo_height()
new_im = im_.crop((x, y, x+width, y+height))
image = sg.tk.PhotoImage(data=image_to_data(new_im))
images.append(image)
label = sg.tk.Label(widget, image=image, padx=0, pady=0, bd=0, bg=bg)
label.place(x=0, y=0)
label.lower()
for widget in widgets:
find_frames(widget)
size = window.size
im_ = Image.open(file).resize(size)
root = window.TKroot
widgets = list(root.children.values())
x0, y0 = root.winfo_rootx(), root.winfo_rooty()
frame = sg.tk.Frame(root, padx=0, pady=0, bd=0, bg=bg)
frame.place(x=0, y=0)
images = []
image = sg.tk.PhotoImage(data=image_to_data(im_))
images.append(image)
label = sg.tk.Label(frame, image=image, padx=0, pady=0, bd=0, bg=bg)
label.pack()
main_frame.Widget.master.place(in_=frame, anchor='center', relx=.5, rely=.5)
frame.lower()
frame.update()
for widget in widgets:
find_frames(widget)
bg = sg.theme_background_color()
background_image_file = os.path.join(os.getcwd(), 'background.png')
size = (640, 480)
sg.set_options(dpi_awareness=True)
frame = [
[sg.Text('Fill in the length', justification='center', background_color='black', font='Helvetica 18')],
[sg.Input(justification='center', size=10, key='length'),
sg.Text('X', justification='center', background_color='black'),
sg.Input(justification='center', size=10, key='width')],
[sg.Button('OK', key='OK')],
[sg.Button('Exit', key='Exit')]
]
# Need only one frame here to move it to center of window
layout = [[sg.Frame('', frame, border_width=0, key='FRAME', background_color=bg)]]
location = sg.Window.get_screen_size()
window = sg.Window('Background Demo', layout, margins=(0, 0), grab_anywhere=True,
size=size, keep_on_top=True, finalize=True,
no_titlebar=True,
transparent_color=bg,
)
images = []
make_background(window, background_image_file, window['FRAME'])
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Cancel', 'Exit'):
break
print(event)
window.close()
我正在尝试在我的 raspberry pi 上为 运行 创建一个 pysimplegui 应用程序。我设法设置了一张背景图片,但要使其正常工作,我需要打开 2 个 windows,一个用于背景,一个用于我的应用程序的布局(长度 x 宽度输入)。 如何制作一个 pysimplegui 应用程序,在其中向 window 添加背景,同时还能够在其上添加布局? 我目前使用的代码是:
import PySimpleGUI as sg
from io import BytesIO
from PIL import Image
import os
def image_to_data(im):
"""
Image object to bytes object.
: Parameters
im - Image object
: Return
bytes object.
"""
with BytesIO() as output:
im.save(output, format="PNG")
data = output.getvalue()
return data
class GUI:
def __init__(self):
self.size = (1280, 800)
self.background_image = os.path.join(os.getcwd(), 'background.png')
self.im = Image.open(self.background_image)
#background
self.background_layout = [[sg.Image(data=image_to_data(self.im))]]
self.window_background = sg.Window('Background', self.background_layout, no_titlebar=True, finalize=True, margins=(0, 0), element_padding=(0,0), right_click_menu=[[''], ['Exit',]])
#background
self.column1 = [
[sg.Text('Fill in the length', justification='center', font='Helvetica 18')],
[sg.Input(justification='center', key='length'), sg.Text('X', justification='center'), sg.Input(justification='center', key='width')],
[sg.Button('OK', key='OK')],
[sg.Button('Exit', key='Exit')]
]
self.layout = [
[sg.Column(self.column1, element_justification='center')]
]
self.window = sg.Window('Title', keep_on_top=True, layout=self.layout, finalize=True, grab_anywhere=False, transparent_color=sg.theme_background_color(), no_titlebar=True)
self.start()
def start(self):
while True:
window, event, values = sg.read_all_windows()
if event in (sg.WINDOW_CLOSED, 'Exit'):
break
self.window.close()
self.window_background.close()
if __name__ == '__main__':
if os.environ.get('DISPLAY','') == '':
print('DISPLAY variable will be set to :0.0')
os.environ.__setitem__('DISPLAY', ':0.0')
GUI()
else:
print('DISPLAY variable is already set to :0.0')
此代码工作正常,但如果我单击 window 之外的任何位置,我会在我的 window 前面单击包含我 raspberry pi 上的背景图像,window 消失在后面。 我的问题: 有没有办法只创建一个 window 带有背景图像,我可以在其上添加布局?
编辑:考虑到我对 pysimplegui 的经验为 0,并且过去使用 Kivy 做过一些项目,我决定坚持使用 Kivy。结束这个问题。
Kivy 示例代码:
main.py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config
Config.set('graphics', 'width', '1280')
Config.set('graphics', 'height', '800')
class MainWidget(BoxLayout):
pass
class TheLabApp(App):
pass
if __name__ == '__main__':
TheLabApp().run()
thelab.kv:
#:kivy 2.1.0
MainWidget:
<MainWidget>:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'assets/background.png' #note how simple it is to add a background image
BoxLayout:
orientation: 'vertical'
Label:
BoxLayout:
orientation: 'vertical'
Label:
text: 'Fill in the length'
font_size: 30
BoxLayout:
orientation: 'horizontal'
TextInput:
id: width
multiline: False
font_size: 30
#size_hint: (0.5, 1)
Label:
text: 'X'
font_size: 20
TextInput:
id: length
multiline: False
font_size: 20
Label:
这是示例,但使用了 tkinter 代码。
import os
from io import BytesIO
from PIL import Image
import PySimpleGUI as sg
def image_to_data(im):
with BytesIO() as output:
im.save(output, format="PNG")
data = output.getvalue()
return data
def make_background(window, file, main_frame):
global images
def find_frames(widget):
widgets = list(widget.children.values())
if isinstance(widget, (sg.tk.Frame, sg.tk.LabelFrame)):
widget.update()
x, y = widget.winfo_rootx() - x0, widget.winfo_rooty() - y0
width, height = widget.winfo_width(), widget.winfo_height()
new_im = im_.crop((x, y, x+width, y+height))
image = sg.tk.PhotoImage(data=image_to_data(new_im))
images.append(image)
label = sg.tk.Label(widget, image=image, padx=0, pady=0, bd=0, bg=bg)
label.place(x=0, y=0)
label.lower()
for widget in widgets:
find_frames(widget)
size = window.size
im_ = Image.open(file).resize(size)
root = window.TKroot
widgets = list(root.children.values())
x0, y0 = root.winfo_rootx(), root.winfo_rooty()
frame = sg.tk.Frame(root, padx=0, pady=0, bd=0, bg=bg)
frame.place(x=0, y=0)
images = []
image = sg.tk.PhotoImage(data=image_to_data(im_))
images.append(image)
label = sg.tk.Label(frame, image=image, padx=0, pady=0, bd=0, bg=bg)
label.pack()
main_frame.Widget.master.place(in_=frame, anchor='center', relx=.5, rely=.5)
frame.lower()
frame.update()
for widget in widgets:
find_frames(widget)
bg = sg.theme_background_color()
background_image_file = os.path.join(os.getcwd(), 'background.png')
size = (640, 480)
sg.set_options(dpi_awareness=True)
frame = [
[sg.Text('Fill in the length', justification='center', background_color='black', font='Helvetica 18')],
[sg.Input(justification='center', size=10, key='length'),
sg.Text('X', justification='center', background_color='black'),
sg.Input(justification='center', size=10, key='width')],
[sg.Button('OK', key='OK')],
[sg.Button('Exit', key='Exit')]
]
# Need only one frame here to move it to center of window
layout = [[sg.Frame('', frame, border_width=0, key='FRAME', background_color=bg)]]
location = sg.Window.get_screen_size()
window = sg.Window('Background Demo', layout, margins=(0, 0), grab_anywhere=True,
size=size, keep_on_top=True, finalize=True,
no_titlebar=True,
transparent_color=bg,
)
images = []
make_background(window, background_image_file, window['FRAME'])
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Cancel', 'Exit'):
break
print(event)
window.close()