Kivy:使 Scatter 的大小与子标签或图像的大小相同
Kivy: Make Scatter same size as child Label or Image
我正在尝试用 kivy 制作一种基本的照片编辑器。它应该允许放置和转换基本图像以及添加文本标签。我正在使用散点图实现此功能,但我 运行 遇到一个问题,我无法让根散点图与其子标签或图像的大小相匹配。这使得实际拖动和缩放图像和标签变得困难,因为它们每个周围都有不可见的散点 space,这使得几乎不可能拖动和调整所需散点的大小。
这是我的 python 代码:
from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.colorpicker import ColorPicker
from kivy.logger import Logger
from kivy.graphics import Color, Ellipse, Line
from kivy.properties import ListProperty
from kivy.properties import NumericProperty
from kivy.properties import ObjectProperty
from kivy.core.window import Window
import os
#from editor import PhotoEditor
import random
#Each class def is a different screen.
class WelcomeScreen(Screen):
pass
class PhoneSelection(Screen):
pass
class StyleSelection(Screen):
pass
class ColorSelection(Screen):
pass
class DesignSelection(Screen):
pass
class UploadPhoto(Screen):
pass
class PatternSelection(Screen):
pass
class PhotoEditor(Screen):
color = ListProperty([1,1,1,1])
word = 'Enter Text'
font_size = 14
font_type = ''
image_path = 'Mike1.png'
erase = False
def open_popup(self):
popup = ColorPopup()
popup.open()
def close_popup(self):
color_bttn = self.ids['color_bttn']
color_bttn.background_color = self.color
color_bttn.color = [1 - self.color[0], 1 - self.color[1], 1 - self.color[2], 1]
def open_text_entry(self):
al = AnchorLayout(anchor_x='center',anchor_y='top')
popup = TextLabelEntry()
al.add_widget(popup)
popup.open()
def close_text_entry(self):
l = Label(text=self.word,color=self.color,font_size=40)
t = TextLabel()
t.add_widget(l)
t.size = l.size
self.ids['il'].add_widget(t)
class Confirm(Screen):
pass
class Pay(Screen):
pass
class ThankYou(Screen):
pass
#These classes are used as parts of the UI for other screens.
class ColorPopup(Popup):
pass
class TextLabel(Scatter):
pass
class TextLabelEntry(Popup):
fonts = []
def font_selector(self):
for file in os.listdir("/mydir"):
if file.endswith(".tff"):
fonts.append(file)
class ImageLabel(ScatterLayout):
pass
class Variables():
#used for storing info about the case to be printed
phone_type = ""
phone_color = ""
phone_style = ""
phone_design_option = ""
total_price = 0.0
#This is the main class that has all the app info.
class MainApp(App):
#Window.size = (1920, 1080)
#Window.fullscreen = True
#list of names for each screen. Each name is used as an ID when changing the current screen.
screens = ["welcome","choose_phone","choose_style","choose_color","choose_design","upload_photo","choose_pattern","photo_edit","confirm","pay","thanks"]
vars = Variables()
#The manager that holds all the screens and allows transitioning between them.
SM = ScreenManager()
def build(self):
#list of names for each screen. Each name is used as an ID when changing the current screen.
screens = ["welcome","choose_phone","choose_style","choose_color","choose_design","upload_photo","choose_pattern","photo_edit","confirm","pay","thanks"]
#Add all screens to the manager and assign the corresponding ID.
self.SM.add_widget(WelcomeScreen(name=screens[0]))
self.SM.add_widget(PhoneSelection(name=screens[1]))
self.SM.add_widget(StyleSelection(name=screens[2]))
self.SM.add_widget(ColorSelection(name=screens[3]))
self.SM.add_widget(DesignSelection(name=screens[4]))
self.SM.add_widget(UploadPhoto(name=screens[5]))
self.SM.add_widget(PatternSelection(name=screens[6]))
self.SM.add_widget(PhotoEditor(name=screens[7]))
self.SM.add_widget(Confirm(name=screens[8]))
self.SM.add_widget(Pay(name=screens[9]))
self.SM.add_widget(ThankYou(name=screens[10]))
#Set the current screen to the welcome screen.
self.SM.current = screens[0]
return self.SM
#Runs the app.
if __name__ == "__main__":
t = MainApp();
t.run()
大部分操作发生在 PhotoEditor class。
这是我的 kivy 代码:
<WelcomeScreen>:
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
Button:
text: "Welcome!"
size_hint: 0.1,0.1
on_press: root.manager.current = app.screens[7]
<PhoneSelection>:
BoxLayout:
Button:
text: "iPhone 4/4s"
on_press:
root.manager.current = app.screens[1]
app.vars.phone_type = "iPhone YAYAYA"
self.text = str(app.vars.phone_type)
<PhotoEditor>
id: PhotoEditor
FloatLayout:
id: il
ImageLabel:
auto_bring_to_front: False
scale_min: 100/img.width
scale_max: 5000/img.width
id: ilr
Image:
id: img
source: root.image_path
#width: il.width
#height: il.height/self.image_ratio
on_touch_up:
if int(ilr.rotation % 15) < 8: ilr.rotation = int(ilr.rotation - int(ilr.rotation % 15))
if int(ilr.rotation % 15) >= 8: ilr.rotation = int(ilr.rotation - int(ilr.rotation % 15)) + 15
Image:
id: ovrly
source: 'overlay/iphone6.png'
AnchorLayout:
anchor_x: 'left'
anchor_y: 'center'
BoxLayout:
size_hint: 0.1, 0.5
orientation: 'vertical'
Button:
text: 'Color'
color: [1 - root.color[0], 1 - root.color[1], 1 - root.color[2], 1]
background_color: root.color
background_normal: ''
id: color_bttn
on_press: root.open_popup()
Button:
group: 'text'
text: 'Text'
on_press: root.open_text_entry()
<ColorPopup>
size_hint: .5, .5
auto_dismiss: False
title: 'Hello world'
on_open:
r.value = int(r.max * app.SM.get_screen('photo_edit').color[0])
g.value = int(g.max * app.SM.get_screen('photo_edit').color[1])
b.value = int(b.max * app.SM.get_screen('photo_edit').color[2])
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation: 'vertical'
Slider:
id: r
on_value:
app.SM.get_screen('photo_edit').color[0] = self.value_normalized
bttn.background_color = app.SM.get_screen('photo_edit').color
bttn.color = [1 - app.SM.get_screen('photo_edit').color[0], 1 - app.SM.get_screen('photo_edit').color[1], 1 - app.SM.get_screen('photo_edit').color[2], 1]
Slider:
id: g
on_value:
app.SM.get_screen('photo_edit').color[1] = self.value_normalized
bttn.background_color = app.SM.get_screen('photo_edit').color
bttn.color = [1 - app.SM.get_screen('photo_edit').color[0], 1 - app.SM.get_screen('photo_edit').color[1], 1 - app.SM.get_screen('photo_edit').color[2], 1]
Slider:
id: b
on_value:
app.SM.get_screen('photo_edit').color[2] = self.value_normalized
bttn.background_color = app.SM.get_screen('photo_edit').color
bttn.color = [1 - app.SM.get_screen('photo_edit').color[0], 1 - app.SM.get_screen('photo_edit').color[1], 1 - app.SM.get_screen('photo_edit').color[2], 1]
Button:
text: 'Close'
id: bttn
background_normal: ''
on_press:
app.SM.get_screen('photo_edit').close_popup()
root.dismiss()
<ImageLabel>
<TextLabel>
size: lbl.size
on_touch_down: if app.SM.get_screen('photo_edit').erase == True: app.SM.get_screen('photo_edit').remove_widget(self)
Label:
id: lbl
#on_size: root.size = self.size
<TextLabelEntry>
size_hint: 0.5,0.5
title: 'Text Entry'
auto_dismiss: True
on_open:
app.SM.get_screen('photo_edit').word = 'Enter Text'
BoxLayout:
size_hint: 0.5,0.2
orientation: 'horizontal'
TextInput:
id: txt
text: 'Enter Text'
on_text: app.SM.get_screen('photo_edit').word = self.text
Button:
on_press:
app.SM.get_screen('photo_edit').close_text_entry()
root.dismiss()
这个问题困扰我有一段时间了,无论我怎样尝试都无法解决。如有任何帮助,我们将不胜感激。
一切都在你的标题中!
Scatter 的大小必须与 Image 的大小相同。
这意味着它是定义散点大小的图像。
ScatterLayout:
size: img.size
size_hint: (None,None)
Image:
id: img
size: (500, 500/self.image_ratio)
# Here I fix the width to 500p,
# You could fix the height or make them
# related to the size of your screen.
你知道在你的kivy安装文件夹中有你可以做什么的例子吗?一个你特别应该感兴趣的 kivy34\examples\demo\pictures
BR.
PS:就我而言,我必须删除您的 ID 为 "ovrly" 的图片才能看到一些东西。
我正在尝试用 kivy 制作一种基本的照片编辑器。它应该允许放置和转换基本图像以及添加文本标签。我正在使用散点图实现此功能,但我 运行 遇到一个问题,我无法让根散点图与其子标签或图像的大小相匹配。这使得实际拖动和缩放图像和标签变得困难,因为它们每个周围都有不可见的散点 space,这使得几乎不可能拖动和调整所需散点的大小。
这是我的 python 代码:
from kivy.app import App
from kivy.uix.scatter import Scatter
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.scatterlayout import ScatterLayout
from kivy.uix.label import Label
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.colorpicker import ColorPicker
from kivy.logger import Logger
from kivy.graphics import Color, Ellipse, Line
from kivy.properties import ListProperty
from kivy.properties import NumericProperty
from kivy.properties import ObjectProperty
from kivy.core.window import Window
import os
#from editor import PhotoEditor
import random
#Each class def is a different screen.
class WelcomeScreen(Screen):
pass
class PhoneSelection(Screen):
pass
class StyleSelection(Screen):
pass
class ColorSelection(Screen):
pass
class DesignSelection(Screen):
pass
class UploadPhoto(Screen):
pass
class PatternSelection(Screen):
pass
class PhotoEditor(Screen):
color = ListProperty([1,1,1,1])
word = 'Enter Text'
font_size = 14
font_type = ''
image_path = 'Mike1.png'
erase = False
def open_popup(self):
popup = ColorPopup()
popup.open()
def close_popup(self):
color_bttn = self.ids['color_bttn']
color_bttn.background_color = self.color
color_bttn.color = [1 - self.color[0], 1 - self.color[1], 1 - self.color[2], 1]
def open_text_entry(self):
al = AnchorLayout(anchor_x='center',anchor_y='top')
popup = TextLabelEntry()
al.add_widget(popup)
popup.open()
def close_text_entry(self):
l = Label(text=self.word,color=self.color,font_size=40)
t = TextLabel()
t.add_widget(l)
t.size = l.size
self.ids['il'].add_widget(t)
class Confirm(Screen):
pass
class Pay(Screen):
pass
class ThankYou(Screen):
pass
#These classes are used as parts of the UI for other screens.
class ColorPopup(Popup):
pass
class TextLabel(Scatter):
pass
class TextLabelEntry(Popup):
fonts = []
def font_selector(self):
for file in os.listdir("/mydir"):
if file.endswith(".tff"):
fonts.append(file)
class ImageLabel(ScatterLayout):
pass
class Variables():
#used for storing info about the case to be printed
phone_type = ""
phone_color = ""
phone_style = ""
phone_design_option = ""
total_price = 0.0
#This is the main class that has all the app info.
class MainApp(App):
#Window.size = (1920, 1080)
#Window.fullscreen = True
#list of names for each screen. Each name is used as an ID when changing the current screen.
screens = ["welcome","choose_phone","choose_style","choose_color","choose_design","upload_photo","choose_pattern","photo_edit","confirm","pay","thanks"]
vars = Variables()
#The manager that holds all the screens and allows transitioning between them.
SM = ScreenManager()
def build(self):
#list of names for each screen. Each name is used as an ID when changing the current screen.
screens = ["welcome","choose_phone","choose_style","choose_color","choose_design","upload_photo","choose_pattern","photo_edit","confirm","pay","thanks"]
#Add all screens to the manager and assign the corresponding ID.
self.SM.add_widget(WelcomeScreen(name=screens[0]))
self.SM.add_widget(PhoneSelection(name=screens[1]))
self.SM.add_widget(StyleSelection(name=screens[2]))
self.SM.add_widget(ColorSelection(name=screens[3]))
self.SM.add_widget(DesignSelection(name=screens[4]))
self.SM.add_widget(UploadPhoto(name=screens[5]))
self.SM.add_widget(PatternSelection(name=screens[6]))
self.SM.add_widget(PhotoEditor(name=screens[7]))
self.SM.add_widget(Confirm(name=screens[8]))
self.SM.add_widget(Pay(name=screens[9]))
self.SM.add_widget(ThankYou(name=screens[10]))
#Set the current screen to the welcome screen.
self.SM.current = screens[0]
return self.SM
#Runs the app.
if __name__ == "__main__":
t = MainApp();
t.run()
大部分操作发生在 PhotoEditor class。
这是我的 kivy 代码:
<WelcomeScreen>:
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
Button:
text: "Welcome!"
size_hint: 0.1,0.1
on_press: root.manager.current = app.screens[7]
<PhoneSelection>:
BoxLayout:
Button:
text: "iPhone 4/4s"
on_press:
root.manager.current = app.screens[1]
app.vars.phone_type = "iPhone YAYAYA"
self.text = str(app.vars.phone_type)
<PhotoEditor>
id: PhotoEditor
FloatLayout:
id: il
ImageLabel:
auto_bring_to_front: False
scale_min: 100/img.width
scale_max: 5000/img.width
id: ilr
Image:
id: img
source: root.image_path
#width: il.width
#height: il.height/self.image_ratio
on_touch_up:
if int(ilr.rotation % 15) < 8: ilr.rotation = int(ilr.rotation - int(ilr.rotation % 15))
if int(ilr.rotation % 15) >= 8: ilr.rotation = int(ilr.rotation - int(ilr.rotation % 15)) + 15
Image:
id: ovrly
source: 'overlay/iphone6.png'
AnchorLayout:
anchor_x: 'left'
anchor_y: 'center'
BoxLayout:
size_hint: 0.1, 0.5
orientation: 'vertical'
Button:
text: 'Color'
color: [1 - root.color[0], 1 - root.color[1], 1 - root.color[2], 1]
background_color: root.color
background_normal: ''
id: color_bttn
on_press: root.open_popup()
Button:
group: 'text'
text: 'Text'
on_press: root.open_text_entry()
<ColorPopup>
size_hint: .5, .5
auto_dismiss: False
title: 'Hello world'
on_open:
r.value = int(r.max * app.SM.get_screen('photo_edit').color[0])
g.value = int(g.max * app.SM.get_screen('photo_edit').color[1])
b.value = int(b.max * app.SM.get_screen('photo_edit').color[2])
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation: 'vertical'
Slider:
id: r
on_value:
app.SM.get_screen('photo_edit').color[0] = self.value_normalized
bttn.background_color = app.SM.get_screen('photo_edit').color
bttn.color = [1 - app.SM.get_screen('photo_edit').color[0], 1 - app.SM.get_screen('photo_edit').color[1], 1 - app.SM.get_screen('photo_edit').color[2], 1]
Slider:
id: g
on_value:
app.SM.get_screen('photo_edit').color[1] = self.value_normalized
bttn.background_color = app.SM.get_screen('photo_edit').color
bttn.color = [1 - app.SM.get_screen('photo_edit').color[0], 1 - app.SM.get_screen('photo_edit').color[1], 1 - app.SM.get_screen('photo_edit').color[2], 1]
Slider:
id: b
on_value:
app.SM.get_screen('photo_edit').color[2] = self.value_normalized
bttn.background_color = app.SM.get_screen('photo_edit').color
bttn.color = [1 - app.SM.get_screen('photo_edit').color[0], 1 - app.SM.get_screen('photo_edit').color[1], 1 - app.SM.get_screen('photo_edit').color[2], 1]
Button:
text: 'Close'
id: bttn
background_normal: ''
on_press:
app.SM.get_screen('photo_edit').close_popup()
root.dismiss()
<ImageLabel>
<TextLabel>
size: lbl.size
on_touch_down: if app.SM.get_screen('photo_edit').erase == True: app.SM.get_screen('photo_edit').remove_widget(self)
Label:
id: lbl
#on_size: root.size = self.size
<TextLabelEntry>
size_hint: 0.5,0.5
title: 'Text Entry'
auto_dismiss: True
on_open:
app.SM.get_screen('photo_edit').word = 'Enter Text'
BoxLayout:
size_hint: 0.5,0.2
orientation: 'horizontal'
TextInput:
id: txt
text: 'Enter Text'
on_text: app.SM.get_screen('photo_edit').word = self.text
Button:
on_press:
app.SM.get_screen('photo_edit').close_text_entry()
root.dismiss()
这个问题困扰我有一段时间了,无论我怎样尝试都无法解决。如有任何帮助,我们将不胜感激。
一切都在你的标题中!
Scatter 的大小必须与 Image 的大小相同。 这意味着它是定义散点大小的图像。
ScatterLayout:
size: img.size
size_hint: (None,None)
Image:
id: img
size: (500, 500/self.image_ratio)
# Here I fix the width to 500p,
# You could fix the height or make them
# related to the size of your screen.
你知道在你的kivy安装文件夹中有你可以做什么的例子吗?一个你特别应该感兴趣的 kivy34\examples\demo\pictures
BR.
PS:就我而言,我必须删除您的 ID 为 "ovrly" 的图片才能看到一些东西。