Python 3.x 如何在Kivy中将图像放入动态文本中
我正在将自己融入kivy,并希望将图片嵌入到显示的文本中。 文本被加载到一个简单的字符串中,然后显示出来,这很容易做到,但我不知何故找不到如何在所述字符串中显示图像的线索 这个问题的答案是为它们构建一个新的布局,在本例中是TextWrapper 示例代码:Python 3.x 如何在Kivy中将图像放入动态文本中,python-3.x,kivy,Python 3.x,Kivy,我正在将自己融入kivy,并希望将图片嵌入到显示的文本中。 文本被加载到一个简单的字符串中,然后显示出来,这很容易做到,但我不知何故找不到如何在所述字符串中显示图像的线索 这个问题的答案是为它们构建一个新的布局,在本例中是TextWrapper 示例代码: from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Label, Button from kivy.lan
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Label, Button
from kivy.lang import Builder
from kivy.properties import BooleanProperty, StringProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.image import Image
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.scrollview import ScrollView
Builder.load_string("""
<ScreenSpecies>:
BoxLayout:
orientation: 'vertical'
Label:
pos_hint: {"x": .45, "top": 1}
size_hint: .1, .1
text: "The Species"
GridLayout:
id: species_layout
rows: 1
cols: 2
padding: dp(10)
spacing: dp(10)
orientation: 'horizontal'
SpeciesView:
id: species_list_view
SpeciesLabel:
id: species_text
text_selected: "Text" if not species_list_view.text_selected else species_list_view.text_selected
name_selected: "" if not species_list_view.name_selected else species_list_view.name_selected
<SpeciesView>:
viewclass: 'SelectableLabel'
text_selected: ""
name_selected: ""
SelectableRecycleBoxLayout:
orientation: 'vertical'
default_size: None, dp(32)
default_size_hint: .6, None
size_hint: 1, .9
multiselect: False
touch_multiselect: False
<SpeciesLabel>:
size_hint_y: .85
Label:
halign: 'left'
valign: 'middle'
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
text: root.text_selected
<SelectableLabel>:
canvas.before:
Color:
rgba: (.05, 0.5, .9, .8) if self.selected else (.5, .5, .5, 1)
Rectangle:
pos: self.pos
size: self.size
""")
class TextWrapper(BoxLayout):
def __init__(self, text="", **kwargs):
super(TextWrapper, self).__init__(**kwargs)
self.content = self.wrap_text(text)
def wrap_text(self, source):
text = source.split("|")
for i in range(0, len(text)):
if "img=" in text[i]:
self.add_widget(Image(source=text[i][4:]))
else:
self.add_widget(Label(text=text[i]))
return text
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
pass
class SelectableLabel(RecycleDataViewBehavior, Label):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected:
print("selection changed to {0}".format(rv.data[index]))
rv.name_selected = rv.data[index]['text']
rv.text_selected = rv.data[index]['description']
else:
print("selection removed for {0}".format(rv.data[index]))
class ScreenSpecies(Screen):
pass
class SpeciesView(RecycleView):
def __init__(self, **kwargs):
super(SpeciesView, self).__init__(**kwargs)
self.species_data = [
{"text": "Test1", "description": "Test1.textbf |img=serveimage.png| Test1.textaf"},
{"text": "Test2", "description": "Test2.text"},
{"text": "Test3", "description": "Test3.text"}
]
for species in self.species_data:
species["description"] = TextWrapper(species["description"])
# clean keywords out
self.data = self.species_data
class SpeciesLabel(ScrollView):
text_selected = StringProperty("")
name_selected = StringProperty("")
screen_manager = ScreenManager()
screen_manager.add_widget(ScreenSpecies(name="screen_species"))
class TestApp(App):
def build(self):
return screen_manager
test_app = TestApp()
test_app.run()
我不知道如何显示视图中每个元素的描述中的TextWrapper
这一切的目的是,我可以根据选项的可选列表来更改文本,并且每个文本中仍然有图像。结果应该与此类似: 同样,问题是如何根据上一次按下的按钮动态更改右侧的文本和图像 谢谢你的帮助 包装 我还没有在kivy中找到任何特定的包装工具来解决您的问题,所以我已经为此编写了一个临时函数。理想情况下,我认为应该有一个选项,允许在文本中嵌入图像,甚至是一个单独的小部件,但现在这将比什么都没有要好
def wrap_text(target, source):
text = source.split("|")
for i in range(0, len(text)):
if "img=" in text[i]:
target.add_widget(Image(source=text[i][4:]))
else:
target.add_widget(Label(text=text[i]))
提供的代码示例假定您以以下格式将图像引用放入字符串中-| img=path |
。例如:
class Main(App):
def build(self):
base = Builder.load_file("Main.kv")
text_field = "This is text, below it should be the first image|img=example_1.png|" \
"Whereas this text should appear in between the images|img=example_2.png|" \
"And this text under the second image"
wrap_text(base, text_field)
return base
主要千伏含量
当然,如果您愿意,您可以引入许多改进,例如,您可以自己定制一个标签,而不是添加常规的标签。或者,可以使图像始终水平添加,除非\n
字符位于图像引用之前的字符串中。或者,您可以尝试扩展现有的kivy工具,以包含所需的功能(就像人们在kivy中所做的那样)
从小部件检索文本
rv.text\u selected=rv.data[index][description']
不起作用,因为rv.data[index][description']
是一个TextWrapper
小部件,而不是字符串。请注意,您在以下行中将其指定为包装器:species[“description”]=TextWrapper(species[“description”])
如果要从小部件内检索文本字段(实际上是小部件内标签内的文本),请使用以下代码:
# Initialise a new, empty string, to add to it later
text = ""
# Iterate over widget's children (might as well dynamically assign them an id to find them faster)
for widget in rv.data[index]['description'].walk():
# Add text if a label is found
if isinstance(widget, Label):
text += widget.text
# Assign the text to the field
rv.text_selected = text
输出:
同样,您也可以用同样的方法检索图像。但是,请注意,如果要同时显示文本和图像,则不必手动检索文本或图像,只需显示TextWrapper
。您可以通过调用add_widget()
来添加它,例如到BoxLayout
要存档,您必须创建一个自定义小部件,首先创建一个按钮
,然后将浮动布局
添加到按钮
。在浮动布局
中添加一个图像
和标签
这里有一个例子
白痴
.kv文件
<TextImage>:
lbl: lbl
img: img
box: box
FloatLayout:
BoxLayout: # add more Image widget and change there orientation
id: box
Image:
id: img
source: 'myexample.png'
pos_hint: {'center_x':.5,'center_y':.5}
size_hint: 1,.9
Label:
id: lbl
size_hint: 1,.1
pos_hint: {'center_x':.5,'center_y':.5}
halign:'center'
:
lbl:lbl
img:img
盒子:盒子
浮动布局:
BoxLayout:#添加更多图像小部件并更改方向
id:盒子
图片:
id:img
来源:“myexample.png”
位置提示:{'center_x':.5,'center_y':.5}
尺寸提示:1.9
标签:
id:lbl
大小提示:1、.1
位置提示:{'center_x':.5,'center_y':.5}
哈利格:“中心”
谢谢!虽然这不允许我在文本中添加可变数量的图像,也不允许在我想添加的位置添加图像,因此这不是我的具体问题的答案,但这是一个更静态的方法的好主意。如果您想添加可变图像并更改文本相对于图像的位置,那么您将添加一个BoxLayout(指定id:name)到FloatLayout并使用add widget Image,您可以更改boxlayout的方向,也可以使用widget的索引来归档您想要的内容。我发现了一个新问题并再次编辑了我的问题,感谢您的想法(我在您的答案中制作了TextWrapper),但我不知道如何将TextWrapper添加到视图中,谢谢!!我编辑了我的答案来回答你的一些新问题。就是这样,我只是通过描述中的文本构建TextWrapper,虽然效率不高,但效果很好:)万分感谢!
# Initialise a new, empty string, to add to it later
text = ""
# Iterate over widget's children (might as well dynamically assign them an id to find them faster)
for widget in rv.data[index]['description'].walk():
# Add text if a label is found
if isinstance(widget, Label):
text += widget.text
# Assign the text to the field
rv.text_selected = text
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
from kivy.uix.image import Image
#the TextImage control
class TextImage(Button):
lbl = ObjectProperty()
img = ObjectProperty()
box = ObjectProperty()
def __init__(self, **kwargs):
super(TextImage, self).__init__(**kwargs)
#function to change specific widget position
def orient1(self):
children = self.ids.box.children[:]
self.ids.box.clear_widgets()
for child in sorted(children):
wid.add_widget(child)
.... # you can create your own funtions for arrangement
class Form(FloatLayout):
def __init__(self, **kwargs):
super(Form, self).__init__(**kwargs)
Textimg = TextImage()
Textimg.orient1() #for index arrangement
#an image
self.Img = Image(source='pic.png', size_hint=(None,None),size=(100,100))
# change the widget organization
Textimg.ids.box.orientation='vertical'
Textimg.ids.box.add_widget(self.Img)
#change your picture
Textimg.ids.img.source='myexample.png'
#Change the text
Textimg.ids.lbl.text='Picture1'
self.add_widget(Textimg)
class MainApp(App):
def build(self):
return Form()
if __name__=='__main__':
MainApp().run()
<TextImage>:
lbl: lbl
img: img
box: box
FloatLayout:
BoxLayout: # add more Image widget and change there orientation
id: box
Image:
id: img
source: 'myexample.png'
pos_hint: {'center_x':.5,'center_y':.5}
size_hint: 1,.9
Label:
id: lbl
size_hint: 1,.1
pos_hint: {'center_x':.5,'center_y':.5}
halign:'center'