I've created a Screen with a boxlayout and its children.
I wanna print size of the label "Hello" in the boxlayout, which has id:shadow_label
This size must be relative. But it's [100, 100]
Why?
What could I give more details for this post? Could this behavior be due to AnchorLayout?
Here is my code
kv file:
<WellcomeScreen>:
box_layout: wellcome_box
BoxLayout:
id: wellcome_box
orientation: 'vertical'
pos: self.parent.pos
size: self.parent.size
padding: [30, 30]
spacing: 10
canvas.before:
Rectangle:
source: 'Data\game background.png'
pos: self.pos
size: self.size
Label:
id:shadow_label
size_hint: (1, .6)
font_size: self.height/12
text_size: self.width-10, None
color: 'purple'
halign: "center"
text: "Hello"
AnchorLayout:
size_hint: (1,.3)
Button:
canvas.before:
Rectangle:
source: "Data\Button_start.png"
pos: self.pos
size: self.size
pos_hint: {"center_x":0.5,"center_y":0.5}
size_hint: (None, None)
size: (self.parent.height/4*3, self.parent.height/4*3)
background_color: (1,1,1,0)
font_size: self.height/4
text_size: self.width, None
text: "START"
color: "yellow"
bold: True
halign: 'center'
on_press:
root.manager.transition.direction = 'left'
root.manager.current = 'login'
python
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.uix.label import MDLabel
from kivy.uix.behaviors import ButtonBehavior
from kivy.properties import ObjectProperty
from kivy.config import Config
Config.set('graphics', 'resizable', '0')
Config.set('graphics', 'width', '420')
Config.set('graphics', 'height', '860')
class WellcomeScreen(Screen):
user_name = ObjectProperty()
box_layout = ObjectProperty()
wellcome_label = ObjectProperty()
def __init__(self, **kwargs):
super(WellcomeScreen, self).__init__(**kwargs)
class StartButton(ButtonBehavior, MDLabel):
def __init__(self, **kwargs):
super(StartButton, self).__init__(**kwargs)
self.background_normal = "Data\Button_start.png"
self.text = "START"
self.text_color = "yellow"
self.color = "white"
self.halign = "center"
class FastReadApp(MDApp):
def build(self):
sm = ScreenManager()
screen_wellcome = WellcomeScreen(name='wellcome')
sm.add_widget(screen_wellcome)
print(screen_wellcome.ids.shadow_label.size)
return sm
if __name__ == '__main__':
app = FastReadApp()
app.run()
There is the screen of my app:
You are printing the size of the label before its size is set, so you see the default size of (100,100). Just delay the print until the size is set. Use Clock.schedule_once() or use a Button to trigger the print.
Related
I've tried multiple pieces of code from here, but they all seem to align the text within the label or text box. I want to align the text box and the label vertically and horizontally. I am a beginner at kivy, so please excuse me if the answer is very obvious.
Is there a way to align the label itself and not the text inside?
Is there also a way to align the text box itself and not the text inside?
Thanks in advance!
This is my .kv file firstkivy.kv
#Filename: firskivy.kv
<MyGrid>:
Label:
text: "Writing"
font_size: 80
bold: True
color: 0.204, 0.204, 0.204, 1
size: self.texture_size
text_size: self.size
halign: 'center'
valign:'middle'
canvas.before:
Color:
rgba: 0.549, 1, 0.984, 1
Rectangle:
size: self.size
pos: self.pos
TextInput:
size_hint: (.2, None)
height: 100
width: 360
multiline: True
size_hint: (None, None)
font_size: 30
halign: 'right'
pos_hint: (None, None)
focus: True
This is the .py file firstkivy.py
# setting up and fixing the window size
#to prevent it from being resized
from kivy.config import Config
Config.set('graphics', 'resizable', False)
Config.set('graphics','width', '360')
Config.set('graphics', 'height', '540')
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
# going back to this one...
Window.clearcolor = (0.549, 1, 0.984, 1)
class MyApp(Widget):
pass
#building the app
class FirstKivy(App, BoxLayout):
def build(self):
self.title = 'Arabic Language Learning App'
return MyApp()
# running the app
if __name__ == '__main__':
FirstKivy().run()
Here is the
Output
Try writing your firstkivy.py like this:
from kivy.config import Config
Config.set('graphics', 'resizable', False)
Config.set('graphics','width', '360')
Config.set('graphics', 'height', '540')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
class MyApp(BoxLayout):
pass
class FirstKivy(App):
title = 'Arabic Language Learning App'
def build(self):
return MyApp()
if __name__ == '__main__':
FirstKivy().run
And your firstkivy.kv like:
<MyApp>:
orientation: "vertical"
spacing: 10
space_x: self.size[0]/3
canvas.before:
Color:
rgba: 0.549, 1, 0.984, 1
Rectangle:
size: self.size
pos: self.pos
FloatLayout:
Label:
text: "Writing"
font_size: 80
bold: True
color: 0.204, 0.204, 0.204, 1
pos_hint: {'center_x': .5, 'center_y': .8}
#size: self.texture_size
#text_size: self.size
#halign: 'center'
#valign:'middle'
TextInput:
size_hint: 1, .5
#height: 100
#width: 200
multiline: True
pos_hint: {'center_x': .5}
#size_hint: None, None
#font_size: 30
#halign: 'right'
#pos_hint: None, None
#focus: True
Hope it achieves what you want.
Any assistance is much appreciated.
Here's an example code to show the problem,
when the ('Press me') button is pressed and the widget resized(white box come within view), the TabbedPanel redraws like a glitch (even though its not).
I've tried changing the layout order and toyed a bit with the animation, no
I wish to prevent that blinking behaviour of the tabbedpanel on the left.
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.animation import Animation
from kivy.lang import Builder
Builder.load_string('''
<Main>:
BoxLayout:
orientation:'vertical'
BoxLayout:
id: main_screen
orientation: 'horizontal'
TabbedPanel:
do_default_tab: False
tab_pos: 'left_top'
tab_width: main_screen.height/4
TabbedPanelItem:
text: 'four'
TabbedPanelItem:
text: 'three'
TabbedPanelItem:
text: 'two'
TabbedPanelItem:
text: 'one'
BoxLayout:
id: swidget
slide: 0
size_hint: None, None
height: main_screen.height
width: self.slide
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
Button:
size_hint_y: None
height: '33dp'
text: 'Press me'
on_release: root.display_widget(swidget)
''')
class Main(BoxLayout):
def __init__(self, **kwargs):
super(Main, self).__init__(**kwargs)
def display_widget(self, widget):
swidget = widget
if swidget.slide == 0:
anim = Animation(slide=105, duration=0.6)
anim.start(widget)
else:
anim = Animation(slide=0, duration=0.6)
anim.start(widget)
class TabbedApp(App):
def build(self):
return Main()
TabbedApp().run()
Add AnchorLayout to be the parent of swidget / BoxLayout and when the animation starts, it won't impact the instantiated TabbedPanel.
Snippets
AnchorLayout:
anchor_x: 'right'
anchor_y: 'top'
size_hint_x: None
width: 0
BoxLayout:
id: swidget
slide: 0
size_hint_x: None
width: self.slide
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
I would like my label to have exactly the height it needs to display its text. It is inside a RecycleView. I think my code should work outside an RecycleView.
How can I make the Label big enough so that its content can easily be read? In the same way as it already works for CodeInput and TextInput.
from kivy.base import runTouchApp
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.label import Label
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import StringProperty
Builder.load_string('''
<RV>:
viewclass: 'SnippetView'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
spacing: 10
<SnippetView>:
canvas.before:
Color:
rgb: (255,0,0)
Rectangle:
pos: self.pos
size: self.size
orientation: 'vertical'
Label:
text: root.heading
text_size: root.width, None
size: self.texture_size
TextInput:
text: root.dscrpt
size_hint_y: None
height: self.minimum_height
CodeInput:
text: root.code
size_hint_y: None
height: self.minimum_height
''')
class SnippetView(BoxLayout):
heading = StringProperty()
dscrpt = StringProperty()
code = StringProperty()
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{'heading': str(x),'dscrpt': str(x),'code': str(x)} for x in range(100)]
rv = RV()
runTouchApp(rv)
I am also thankful for any comments regarding RecycleView in general since I am using it for the first time.
You must bind a method to update the height of your SnippetView when the value of the label change because you have fixed it in the rule of your RV. Try this:
...
Builder.load_string('''
...
<SnippetView>:
canvas.before:
Color:
rgb: (255,0,0)
Rectangle:
pos: self.pos
size: self.size
orientation: 'vertical'
Label:
id: l
text: root.heading
text_size: root.width, None
size: self.texture_size
TextInput:
id: ti
text: root.dscrpt
size_hint_y: None
height: self.minimum_height
CodeInput:
id: ci
text: root.code
size_hint_y: None
height: self.minimum_height
''')
class SnippetView(BoxLayout):
heading = StringProperty()
dscrpt = StringProperty()
code = StringProperty()
def __init__(self, **kwargs):
super(SnippetView, self).__init__(**kwargs)
self.ids.l.bind(height=self.update)
def update(self, *args):
self.height = self.ids.l.texture_size[1] + self.ids.ti.height + self.ids.ci.height
...
I'm new to kivy , I'm trying to write an application using kivy in python, I got struck at one point where i have to read text from textinput whenever it is changed and based on that i want to implement my button's functionality - I have gone through all the documentation but i couldn't figure out how to do it - Can any body tell me how can I resolve this or am I missing something?
from __future__ import print_function
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.core.image import Image
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
import walascan
from kivy.clock import Clock
import os
kv = """
<KartScan>:
IntroScreen:
<IntroScreen#Screen>:
orientation: 'horizontal'
name: 'introscreen'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'index.png'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'center'
BoxLayout:
orientation:'horizontal'
size_hint: .5, .1
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
spacing: 20
pos_hint: {'center_x':.8, 'center_y': .8}
AnchorLayout:
anchor_x: 'left'
size_hint_x: .5
TextInput:
id: waybill
width: 20
text: "Enter Waybill No."
multiline: False
height: self.minimum_height
size_hint_y: None
font_size: 30
focus: True
on_text_validate: app.on_waybill()
AnchorLayout:
anchor_x: 'right'
size_hint_x: None
Button:
size_hint: None, None
height: 50
width: self.texture_size[0]
padding: 10, 10
text: "Add"
on_press:app.buttonClicked()
on_release: root.current = 'mainpage'
AnchorLayout:
anchor_x: 'right'
size_hint_x: None
Button:
size_hint: None, None
height: 50
width: self.texture_size[0]
padding: 10, 10
text: "Compare"
on_press:app.buttonClicked()
on_release: root.current = 'mainpage'
"""
Builder.load_string(kv)
waybill = TextInput(text="Enter Waybill No.", multiline=False)
class KartScan(FloatLayout):
def __init__(self, **kwargs):
super(KartScan, self).__init__(**kwargs)
self.register_event_type('on_text_validate')
def on_text(self, *args):
print('new value is ', waybill.text)
def on_text_validate(self):
pass
def on_focus(self, obj, focused):
if not focused:
self.dispatch('on_text_validate')
class KartScanApp(App):
def build(self):
return KartScan()
def buttonClicked(self):
popup = Popup(title='Result',
content=Label(text=self.on_waybill()),
size_hint=(None, None), size=(100, 100))
popup.bind()
popup.open()
def getwlbtstate(self):
return walascan.mainAntennas()
def on_waybill(self):
waybill.bind(text=KartScan.on_text_validate)
# popup = Popup(title='Result',
# content=Label(text=waybill.text),
# size_hint=(None, None), size=(100, 100))
# popup.bind()
# popup.open()
return waybill.text
if __name__ == '__main__':
KartScanApp().run()
kv file
TextInput:
on_text: print(self.text)
You could use on_text to call a function when the text changes. I think it sometimes even triggers when no change has occured.
TextInput has a text property, and in kivy, all properties have associated on_xxx events, that you can bind to to react to them, so when reading the doc, even if it's not explicitly mentionned for them, everytime you see something is defined as a Property (or any subclass of it, like StringPropertyNumericProperty,ObjectProperty,AliasProperty`).
TextInput:
on_text: do_something(self.text)
or in python
t = TextInput(text='', on_text=do_something)
or
t = TextInput(text='')
t.bind(on_text=do_something)
I am working on an application where I want to add n image frames in a vertical BoxLayout. The number of n frames depend on the desktop screen size. Next to this the frames will be filled dynamically with images. I was able to develop this in a static manner with a fixed number of frames.
Now I am trying to convert this to a dynamic solution where n frame widgets will be created depending on the height of the screen (in the example below 7 widgets). And I am lost..... :(
The frames should 'sit' between a top bar and a bottom bar. In the .kv file this is indicated by the # Ilist: line.
I have the following questions:
1) How could I add these widgets dynamically using a .kv file?
2) How could I reference to these individual frame widgets for assigning images dynamically? For example: frame[idx] = swid?
Thanks very much for your time and shared knowledge in advance.
The Python file pplay.py:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.properties import StringProperty
class IListItem(Widget):
sid = StringProperty('')
image = StringProperty('')
label = StringProperty('')
pass
class IList(Widget):
pass
class pplayHome(BoxLayout):
def init_player(self):
global swid
self.Ilayout = IList()
for idx in range (1, 7):
swid = IListItem(
sid = "s" + str(idx),
image = 'empty_image.png',
label = 'Image' + str(idx)
)
self.Ilayout.add_widget(swid)
class pplayApp(App):
def build(self):
Window.clearcolor = (1,1,1,1)
Window.borderless = True
Window.size = 275, 1080
homeWin = pplayHome()
homeWin.init_player()
return homeWin
if __name__ == "__main__":
pplayApp().run()
and the Kivy file pplay.kv
# File: pplay.kv
<IList#BoxLayout>
pid: self.pid
source: self.source
label: self.label
size_hint_y: None
height: "120dp"
BoxLayout:
orientation: "vertical"
Label:
size_hint: None, 1
text: root.label
Image:
size_hint: None, 1
source: root.source
<pplayHome>:
orientation: "vertical"
ActionBar:
font_size: 8
size: (275,25)
# background color in Kivy acts as a tint and not just a solid color.
# set a pure white background image first.
background_image: 'white-bg.png'
background_color: 0,.19,.34,1
ActionView:
ActionPrevious:
with_previous: False
app_icon: 'trButton.png'
ActionOverflow:
ActionButton:
icon: 'butt_exit.png'
on_press: root.exit_player()
# Ilist:
BoxLayout:
height: "10dp"
size_hint_y: None
pos_x: 0
canvas.before:
Color:
rgb: 0.55,0.77,0.25 # groen
Rectangle:
pos: self.pos
size: self.size
You were actually pretty close.
Here is the slightly changed kv file, with added colored rectangles for illustration of sizes:
# File: pplay.kv
<IListItem#Widget>
source: ''
label: ''
size_hint_y: None
height: "120dp"
canvas.before:
Color:
rgb: 0.55,0.77*self.idx/7,0.25 # groen
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: "vertical"
size: root.size
pos: root.pos
Label:
size_hint: None, 1
text: root.label
canvas.before:
Color:
rgb: 0.77*root.idx/7,0.55,0.25 # groen
Rectangle:
pos: self.pos
size: self.size
Image:
size_hint: None, 1
source: root.source
<pplayHome>:
orientation: "vertical"
ActionBar:
font_size: 8
size: (275,25)
# background color in Kivy acts as a tint and not just a solid color.
# set a pure white background image first.
background_image: 'white-bg.png'
background_color: 0,.19,.34,1
ActionView:
ActionPrevious:
with_previous: False
app_icon: 'trButton.png'
ActionOverflow:
ActionButton:
icon: 'butt_exit.png'
on_press: root.exit_player()
IList:
id: ilist
orientation: 'vertical'
BoxLayout:
height: "10dp"
size_hint_y: None
pos_x: 0
canvas.before:
Color:
rgb: 0.55,0.77,0.25 # groen
Rectangle:
pos: self.pos
size: self.size
In pplay.py, the essential part is to retrieve the IList widget using self.ids['ilist']. It also shows how its children (the IListItems) can be retrieved via a differentiating property.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.properties import StringProperty, NumericProperty
class IListItem(Widget):
idx = NumericProperty(1)
sid = StringProperty('')
image = StringProperty('')
label = StringProperty('')
pass
class IList(BoxLayout):
pass
class pplayHome(BoxLayout):
def init_player(self):
#global swid
print self.ids
ilayout = self.ids['ilist']
for idx in range (0, 7):
swid = IListItem(
sid = "s" + str(idx),
image = 'empty_image.png',
label = 'Image' + str(idx),
idx=idx
)
ilayout.add_widget(swid)
children_ids = [il.sid for il in ilayout.children]
print children_ids
print ilayout.children[children_ids.index('s3')]
class pplayApp(App):
def build(self):
# Window.clearcolor = (1,1,1,1)
Window.borderless = True
Window.size = 275, 1080
homeWin = pplayHome()
homeWin.init_player()
return homeWin
if __name__ == "__main__":
pplayApp().run()