我正在努力工作,希望将图片嵌入到显示的文本中。 文本被加载一个简单的字符串,然后显示,这很容易做,但我不知道如何找到如何在所述字符串中显示图像的线索。
这个问题的答案是为这些构建一个新的布局,在这种情况下是TextWrapper。
示例代码:
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()
此代码无效!因为你不能在不破坏程序的情况下点击标签,这就是问题所在。 text_selected只接受str
ValueError: SpeciesView.text_selected accept only str
我不知道如何显示视图中每个元素描述中的TextWrapper。
这一切的目的是,我可以根据例如改变文本来改变文本。可选择的选项列表,每个文本中仍有图像 结果看起来应该类似于:
同样,问题是如何根据最后按下的按钮动态更改右侧文本并更改图像。
感谢您的帮助!
答案 0 :(得分:1)
我还没有在kivy找到任何特定的包装工具来解决你的问题,所以我为此编写了一个临时函数。理想情况下,我认为应该有一个TextMarkup选项允许在文本中嵌入图像,甚至是一个单独的小部件,但是现在这将比没有更好。
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
Main.kv 内容
BoxLayout:
orientation: 'vertical'
当然,如果您愿意,可以引入一些改进,例如,您可以自行创建自定义Label
,而不是添加常规\n
。或者您可以使图像始终水平添加,除非rv.text_selected = rv.data[index]['description']
字符位于图像引用之前的字符串中。或者您可以尝试扩展现有的kivy工具以包含您想要的功能(正如人们在kivy的Garden中所做的那样)。
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
例如Add-Type -AssemblyName PresentationFramework
$window = New-Object Windows.Window
$commonKeyEvents = {
[System.Windows.Input.KeyEventArgs] $e = $args[1]
if (($e.Key -eq "Q" -and $e.KeyboardDevice.Modifiers -eq "Ctrl") -or
($e.Key -eq "ESC")) {
$this.Close()
}
}
$window.Add_PreViewKeyDown($commonKeyEvents)
$window.ShowDialog() | Out-Null
来添加它。
答案 1 :(得分:1)
要实现此目的,您必须创建自定义窗口小部件,首先创建Content
,然后将BasedOn
添加到Button
。在FloatLayout
中添加{ {1}}和Button
这是一个例子
的.py
FloatLayout
.kv文件
Image