How do I add a widget via python? What is my mistake?
I want to add a widget using the button.How to apply correctly?
In python format:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang import Builder
from kivy.core.window import Window
Window.size = (320, 720)
Builder.load_file('my.kv')
class Container(FloatLayout):
def minus(self):
self.fp.add_widget(TextInput(text="1103"))
print("ok")
class MyApp(App):
def build(self):
return Container()
if __name__ == "__main__":
MyApp().run()
In kiwy format:
<Container>
fp: fp
FloatLayout:
orientation: "vertical"
Button:
text : "Системы"
size_hint : (0.3, 0.1)
pos_hint : {'x':0.05, 'y':0.9}
font_size : "20sp"
Button:
text : "Локодром"
size_hint : (0.3, 0.1)
pos_hint : {'x':0.35, 'y':0.9}
font_size : "20sp"
Button:
text : "Задачи"
size_hint : (0.3, 0.1)
pos_hint : {'x':0.65, 'y':0.9}
font_size : "20sp"
BoxLayout:
orientation: "horizontal"
cols: 3
size_hint: 0.9,0.975
pos_hint: {'center_x':.5}
Button:
text : "<-"
size_hint : (0.05, 0.05)
font_size : "20sp"
pos_hint: {'top': 0.91}
Label:
text : "19.11.2022"
size_hint : (0.2, 0.05)
font_size : "20sp"
pos_hint: {'top': 0.91}
Button:
text : "->"
size_hint : (0.05, 0.05)
font_size : "20sp"
pos_hint: {'top': 0.91}
TextInput:
text : ""
size_hint:(0.47, 0.05)
pos_hint:{'x': 0.05, 'y': 0.78}
font_size : "18sp"
Button:
text : "Поиск"
size_hint:(0.2, 0.05)
pos_hint:{'x': 0.536, 'y': 0.78}
font_size : "15sp"
Button:
text : "Убрать"
size_hint : (0.2, 0.05)
pos_hint : {'x':0.75, 'y':0.78}
font_size : "15sp"
Label:
text : "S"
size_hint : (0.1, 0.05)
pos_hint : {'x': 0.03, 'y': 0.72}
font_size : "20sp"
Label:
text : "№"
size_hint : (0.15, 0.05)
pos_hint : {'x': 0.12, 'y': 0.72}
font_size : "20sp"
Label:
text : "Описание"
size_hint : (0.53, 0.05)
pos_hint : {'x': 0.25, 'y': 0.72}
font_size : "20sp"
Label:
text : "Прим."
size_hint : (0.18, 0.05)
pos_hint : {'x': 0.77, 'y': 0.72}
font_size : "20sp"
BoxLayout:
orientation: 'vertical'
Label:
text: ""
size_hint : (0.18, 0.53)
ScrollView:
size_hint: 0.9,1
pos_hint: {'center_x':.5}
GridLayout:
id:fp
size_hint_y:None
height: self.minimum_height
cols: 4
cols_minimum: {0: 10, 1: 30, 2: 140, 3: 50}
TextInput:
text: 'Filler'
size_hint:1,None
height:40
Label:
text: ''
size_hint : (0.18, 0.2)
BoxLayout:
orientation: "horizontal"
cols: 3
padding: 20
Button:
text : "Удалить"
size_hint:(0.29, 0.07)
pos_hint: {'top': 0.07}
font_size : "15sp"
on_press: root.minus()
Button:
text : "Добавить"
size_hint : (0.29, 0.07)
pos_hint: {'top': 0.07}
font_size : "15sp"
Button:
text : "Сохранить"
size_hint : (0.29, 0.07)
pos_hint: {'top': 0.07}
font_size : "15sp"
I thought that by referring to the id I would get a new widget
self.fp.add_widget(TextInput(text="1103"))
Но получаю enter image description here
Help please
You can do it this way, see the kivy doc (https://kivy.org/doc/stable/guide/widgets.html):
layout = BoxLayout(padding=10)
button = Button(text='My first button')
layout.add_widget(button)
Related
I have created a Screen with a Scrollview and a MDList on it, with some TwoLineListItems.
Is there a way to reduce the row height on the MDList to fit the font size of the TwoLineListItem?
Part of my kv file:
<SelectionList>:
name: "Selection"
MDBoxLayout:
orientation: 'vertical'
size: root.width, root.height
padding: 5
ScrollView:
size_hint: (1, 1)
bar_color: "#ff0066"
bar_width: 4
MDList:
TwoLineListItem:
id: name_list
text: "[size=10]Name: [/size]"
secondary_text: "[size=12]XXXXXX[/size]"
TwoLineListItem:
id: surname_list
text: "[size=10]Surname: [/size]"
secondary_text: "[size=12]XXXXXX[/size]"
TwoLineListItem:
id: phone_list
text: "[size=10]Phone: [/size]"
secondary_text: "[size=12]XXXXXX[/size]"
...
GridLayout:
cols: 2
size_hint: None, None
height: self.minimum_height
padding: 10
col_force_default: True
col_default_width: root.width/2
MDFloatingActionButton:
type: "small"
icon_size: "30sp"
icon: "arrow-left-bold-circle"
icon_color: "#2d5986"
md_bg_color: "white"
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MDFloatingActionButton:
type: "small"
icon_size: "30sp"
icon: "home-circle"
icon_color: "#2d5986"
md_bg_color: "white"
pos_hint: {'center_x': 0.8, 'center_y': 0.5}
improve coding on kivymd
I am trying to draw a shadow for a ModalView using the Canvas Line vertex instructions. I.e. the ModalView bottom and left sides should have a slight shadowy overlay when open. I have tried calling the ModalView property overlay_color with no effect and Canvas Line vertex instructions do not create the right effect. But I cannot seem to only draw a bottom and left border that gives the shadowy effect.
<PopScrollModal>
on_open: app.root._is_modal_open = True
on_dismiss: app.root._is_modal_open = False
id: popscroll
auto_dismiss: True
orientation: 'vertical'
size_hint: (0.94, 0.41)
border: [50, 50, 16, 16]
overlay_color: [0.1, 0.1, 0.1, 0.4]
pos_hint: {'top': 0.72}
background_normal: ''
background_color: (1, 1, 1, 0)
background: 'white.png'
canvas:
Color:
rgba: app.theme_cls.bg_dark
RoundedRectangle:
size: self.size
pos: self.pos
radius: [7,]
canvas.after:
Color:
rgba: (0.2, 0.2, 0.2, 0.4)
Line:
width: 1.
rounded_rectangle: (self.x, self.y, self.width, self.height, 7)
RecycleView:
id: view_popscroll
viewclass: 'PopScrollBut'
pos_hint: {'top': 1}
size_hint: [1, 0.99]
do_scroll_y: True
RecycleGridLayout:
cols: 1
spacing: 1
default_size: None, 70
default_size_hint: 1, None
size_hint: 1, None
size: self.minimum_size
This line instruction draws on the bottom but does not adhere to the radius of the canvas:
canvas.after:
Color:
rgba: (0.2, 0.2, 0.2, 0.4)
Line:
width: 1.
close: False
points: self.pos[0], self.pos[1], self.pos[0] + self.size[0], self.pos[1]]
The Line instruction only draws a line around the ModalView.
Can somebody help to understand how to set the Points so they only appear left and bottom or set the overlay_color in the same way?
You can do that using BorderImage. It is not well documented and difficult to understand how it is actually intended to work. But here is an example that mostly does what you want:
class MyPop(Popup):
pass
kv = '''
<MyPop>:
canvas.before:
BorderImage:
source: 'shadow32.png'
border: 30, 0, 0, 30
pos: self.x - 30, self.y - 30
size: self.width + 60, self.height + 60
'''
And here is the shadow32.png that is used above:
I have kivy 1.11.1, Ubuntu 20.04 LTS, python 3.8 running on my laptop . I am beginner to kivy and currently working on kivy project, I am stuck on this problem of children gridlayout of scrollview getting overlapped. I have a scroll view with GridLayout and some labels as its children. GridLayout have one Label and a StackLayout which can have different number of entries for different row. Here is source code main.py.
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.effects.scroll import ScrollEffect
kv = '''
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
ScrollApp:
<ScrollApp>:
ScrollView:
size_hint: 1.0, 0.90
pos_hint: {'center_y':0.5}
padding: 22, 0, 22, 50
spacing: 50
effect_cls: ScrollEffect
GridLayout:
cols: 1
# id: streak_zone
size_hint_y: None
height: self.minimum_height
row_force_default: True
row_default_height: 400
canvas:
Color:
rgba: .15, .15, .15, .9
Rectangle:
size: self.size
pos: self.pos
Button:
size_hint: None, None
width: 100
height: 100
on_press: print('This button does not overlap the menu above')
# "ScrollViews containers"
Custom
Custom
Custom
Custom
Custom
Custom
BoxLayout:
size_hint: 1, 0.05
pos_hint: {'bottom':1.0}
Button:
on_press: print("This menu at the bottom is not affected by the problem that occurs with the top one")
BoxLayout:
size_hint: 1, 0.05
pos_hint: {'top':1.0}
Button:
text: 'Fixed Menu'
on_press: print('This button stops working if there is a horizontal scrollview "behind"')
<Custom#GridLayout>:
cols: 1
# id: streak_zone
size_hint_y: None
height: self.minimum_height
row_force_default: True
row_default_height: 60
Label:
id: label
font_size: 20
text: 'Teste'
text_size: self.width, None
size_hint_y: None
halign: "center"
valign: "middle"
canvas:
Color:
rgba: (0, 1, 0, .5) # DarkOliveGreen
Rectangle:
size: self.size
pos: self.pos
StackLayout:
id : grid
size_hint_y: None
ToggleButton:
text:'1'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'2'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'3'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'4'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'5'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'6'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'7'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'8'
size_hint:1/3, 1
group:'ttt'
'''
class ScrollApp(FloatLayout):
pass
class Test(App):
def build(self):
kv1 = Builder.load_string(kv)
print("jhe ",kv1.height)
return kv1
return ScrollApp()
Test().run()
I am getting this layout after running it.
enter image description here
I have read many articles on GridLayout and ScrollView but still unable to fix this issue. What am I missing ?
Updated code:
from kivy.app import App
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.effects.scroll import ScrollEffect
kv = '''
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
ScrollApp:
<ScrollApp>:
ScrollView:
size_hint: 1.0, 0.90
pos_hint: {'center_y':0.5}
padding: 22, 0, 22, 50
spacing: 50
effect_cls: ScrollEffect
GridLayout:
cols: 1
# id: streak_zone
size_hint_y: None
height: self.minimum_height
#row_force_default: True
#row_default_height: 400
canvas:
Color:
rgba: .15, .15, .15, .9
Rectangle:
size: self.size
pos: self.pos
Button:
size_hint: None, None
width: 100
height: 100
on_press: print('This button does not overlap the menu above')
# "ScrollViews containers"
Custom
Custom
Custom
Custom
Custom
Custom
BoxLayout:
size_hint: 1, 0.05
pos_hint: {'bottom':1.0}
Button:
on_press: print("This menu at the bottom is not affected by the problem that occurs with the top one")
BoxLayout:
size_hint: 1, 0.05
pos_hint: {'top':1.0}
Button:
text: 'Fixed Menu'
on_press: print('This button stops working if there is a horizontal scrollview "behind"')
<Custom#GridLayout>:
cols: 1
# id: streak_zone
size_hint_y: None
height: self.minimum_height
#row_force_default: True
#row_default_height: 60
Label:
id: label
font_size: 20
text: 'Teste'
text_size: self.width, None
size_hint_y: None
halign: "center"
valign: "middle"
canvas:
Color:
rgba: (0, 1, 0, .5) # DarkOliveGreen
Rectangle:
size: self.size
pos: self.pos
StackLayout:
id : grid
size_hint_y: None
ToggleButton:
text:'1'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'2'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'3'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'4'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'5'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'6'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'7'
size_hint:1/3, 1
group:'ttt'
ToggleButton:
text:'8'
size_hint:1/3, 1
group:'ttt'
'''
class ScrollApp(FloatLayout):
pass
class Test(App):
def build(self):
kv1 = Builder.load_string(kv)
print("jhe ",kv1.height)
return kv1
return ScrollApp()
Test().run()
I think the problem is that whenever you use the minimum_height property of GridLayout, you must make sure that the size of its children are well defined, and you can't use size_hint_y for those children.
So here is a slightly modified version of your kv that specifies more height properties:
#:import ScrollEffect kivy.effects.scroll.ScrollEffect
ScrollApp:
<ScrollApp>:
ScrollView:
size_hint: 1.0, 0.90
pos_hint: {'center_y':0.5}
padding: 22, 0, 22, 50
spacing: 50
effect_cls: ScrollEffect
GridLayout:
cols: 1
# id: streak_zone
size_hint_y: None
height: self.minimum_height
#row_force_default: True
#row_default_height: 400
canvas:
Color:
rgba: .15, .15, .15, .9
Rectangle:
size: self.size
pos: self.pos
Button:
size_hint: None, None
width: 100
height: 100
on_press: print('This button does not overlap the menu above')
# "ScrollViews containers"
Custom
Custom
Custom
Custom
Custom
Custom
BoxLayout:
size_hint: 1, 0.05
pos_hint: {'bottom':1.0}
Button:
on_press: print("This menu at the bottom is not affected by the problem that occurs with the top one")
BoxLayout:
size_hint: 1, 0.05
pos_hint: {'top':1.0}
Button:
text: 'Fixed Menu'
on_press: print('This button stops working if there is a horizontal scrollview "behind"')
<Custom#GridLayout>:
cols: 1
# id: streak_zone
size_hint_y: None
height: self.minimum_height
#row_force_default: True
#row_default_height: 60
Label:
id: label
font_size: 20
text: 'Teste'
text_size: self.width, None
size_hint_y: None
height: 50
halign: "center"
valign: "middle"
canvas:
Color:
rgba: (0, 1, 0, .5) # DarkOliveGreen
Rectangle:
size: self.size
pos: self.pos
StackLayout:
id : grid
size_hint_y: None
height: self.minimum_height
ToggleButton:
text:'1'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'2'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'3'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'4'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'5'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'6'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'7'
size_hint:1/3, None
height: 50
group:'ttt'
ToggleButton:
text:'8'
size_hint:1/3, None
height: 50
group:'ttt'
This question already has answers here:
How to test the membership of multiple values in a list
(12 answers)
Closed 4 years ago.
So, I want to write this program where I define a class, and the method within it takes a list of colours as an argument. The colours "red", "Red, "green" and "Green" should be replaced with "black", "Black", "white" and "White" (see the dictionary "self.colour_replacement" in the code-text).
If only one of the two colors red/green regardsless of capital letter, is in the list, the program should only return the list without changing it.
Example_1:
print(c.make_readable(['Green', 'Green', 'pink', 'green', 'yellow', 'green',
'green']))
should return:
['Green', 'Green', 'pink', 'green', 'yellow', 'green', 'green']
Example_2:
print(c.make_readable(['green', 'Green']))
should return:
['green', 'Green']
I think the problem has to do with my "or" and "and" statements in the line:
if ('red' and 'green') in colours or ('Red' and 'green') in colours or
('red' and 'Green') in colours or ('Red' and 'Green') in colours:
but I am not entirely sure.
class ColourChanger:
def __init__(self):
"""A dictionary that shows the
replacement colours."""
self.colour_replacement = {'Green' : 'White', 'red': 'black',
'green': 'white', 'Red' : 'Black'}
def make_readable(self, colours):
result = []
if ('red' and 'green') in colours or ('Red' and 'green') in colours or
('red' and 'Green') in colours or ('Red' and 'Green') in colours:
for col in colours:
if col in self.colour_replacement:
result.append(self.colour_replacement[col]) """Appends the
"result"-list with the replacement color instead of the color (col)."""
else:
result.append(col)
else:
return colours
return result
c = ColourChanger()
print(c.make_readable(['green', 'Green']))
print(c.make_readable(['Red', 'red']))
print(c.make_readable(['Red', 'Red', 'pink', 'red', 'yellow', 'red', 'red',
'Green']))
print(c.make_readable(['Green', 'Green', 'pink', 'green', 'yellow', 'green',
'green']))
Expected output:
['green', 'Green']
['Red', 'red']
['Black', 'Black', 'pink', 'black', 'yellow', 'black', 'black', 'White']
['Green', 'Green', 'pink', 'green', 'yellow', 'green', 'green']
Actual Output:
['white', 'White']
['Red', 'red']
['Black', 'Black', 'pink', 'black', 'yellow', 'black', 'black', 'White']
['White', 'White', 'pink', 'white', 'yellow', 'white', 'white']
Your condition is wrong, to fix it use
if ('red' in colours and 'green' in colours) or ( ...) .... :
but its not needed - as much is shared in the dupe.
You can avoid most of your ifs alltogether. There is very few benefit in checking first if something is in the list and then conditionally build the replacement to return it. You might sometimes omit building the replacement list which can be a benefit if your lists are huge but you will still have to iterate each list once to its full length to "see" this. You will also need to do this for all lists that would need to get a substitute list to be built - thouse would be traversed more then once - eating up all the "time" you saved for those that do not need replacements. For short(ish) lists its easier to simply build the replacement every time:
It is easier to build the "replace" on the first run through your data:
class ColourChanger:
def __init__(self):
# A dictionary that shows the replacement colours - only lowercase needed
self.colour_replacement = {'green' : 'white', 'red': 'black'}
def make_readable(self, colours):
result = []
# iterate all col's, append them if not in dict, else append the replacement
for col in colours:
replace = self.colour_replacement.get(col.lower(), col)
# adjust case-ness by string-splicing with uppercase where needed
if col[0].isupper() and replace[0].islower():
replace = replace[0].upper()+replace[1:]
result.append(replace)
return result
c = ColourChanger()
print(c.make_readable(['green', 'Green']))
print(c.make_readable(['Red', 'red']))
print(c.make_readable(['Red', 'Red', 'pink', 'red', 'yellow', 'red', 'red',
'Green']))
print(c.make_readable(['Green', 'Green', 'pink', 'green', 'yellow', 'green',
'green']))
Output:
['white', 'White']
['Black', 'black']
['Black', 'Black', 'pink', 'black', 'yellow', 'black', 'black', 'White']
['White', 'White', 'pink', 'white', 'yellow', 'white', 'white']
See Why dict.get(key) instead of dict[key]? for why using .get(key, default).
I am having issues with the slide direction using SlideTransition in Kivy. When implementing a button-specific slide direction, the direction seems to work fine only occasionally. However, it fails in other circumstances.
To reproduce the problem, please feel free to use the following code:
main.py:
from kivy.app import App # Use of fields and methods of Kivy
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
class Screen1(Screen):
pass
class Screen2(Screen):
pass
class Screen3(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("style.kv")
class MyApp(App):
def build(self):
return presentation
myApp = MyApp()
myApp.run()
style.kv:
#: import SlideTransition kivy.uix.screenmanager.SlideTransition
ScreenManagement:
transition: SlideTransition()
Screen1:
Screen2:
Screen3:
<Screen1>:
name: "screen1"
FloatLayout:
Label:
text: "Screen 1"
pos_hint: {"top": 1.0}
Button:
on_release:
app.root.current = "screen2"
app.root.transition = SlideTransition(direction="left")
size_hint: 0.5, 0.8/3
pos_hint: {"bottom": 0.8, "left": 1}
text: "Screen 2 (slide left)"
font_size: 30
<Screen2>:
name: "screen2"
FloatLayout:
Label:
text: "Screen 2"
pos_hint: {"top": 1.0}
Button:
on_release:
app.root.current = "screen1"
app.root.transition = SlideTransition(direction="right")
size_hint: 0.5, 0.8/3
pos_hint: {"top": 0.8, "right": 1}
text: "Screen 1 (slide right)"
font_size: 30
Button:
on_release:
app.root.current = "screen3"
app.root.transition = SlideTransition(direction="left")
size_hint: 0.5, 0.8/3
pos_hint: {"top": 0.8, "left": 1}
text: "Screen 3 (slide left)"
font_size: 30
<Screen3>:
name: "screen3"
FloatLayout:
Label:
text: "Screen 3"
pos_hint: {"top": 1.0}
Button:
on_release:
app.root.current = "screen1"
app.root.transition = SlideTransition(direction="right")
size_hint: 0.5, 0.8/3
pos_hint: {"top": 0.8, "left": 1}
text: "Screen 1 (slide right)"
font_size: 30
I am experiencing the following problem: Upon clicking on "Slide 2" in the first slide and "Slide 3" in the second slide, both disappearing to the left as specified, clicking "Slide 1" in the third slide results in slide direction "left", although the specified direction is "right". Something seems to override the slide direction?
Did anyone experience similar problems and does know how to solve them? Thanks in advance!
Problem
The screen was displayed before the given direction. Therefore, it used the previous Slide Transition direction i.e. left. You have the same problem in a couple of places.
Button:
on_release:
app.root.current = "screen1"
app.root.transition = SlideTransition(direction="right")
Solution
Set the Slide Transition direction first, and then set current to the desire screen name. Please refer to the example for details.
Button:
on_release:
app.root.transition = SlideTransition(direction="right")
app.root.current = "screen1"
Example
style.kv
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
ScreenManagement:
transition: SlideTransition()
Screen1:
Screen2:
Screen3:
<Screen1>:
name: "screen1"
FloatLayout:
Label:
text: "Screen 1"
pos_hint: {"top": 1.0}
Button:
on_release:
app.root.transition = SlideTransition(direction="left")
app.root.current = "screen2"
size_hint: 0.5, 0.8/3
pos_hint: {"bottom": 0.8, "left": 1}
text: "Screen 2 (slide left)"
font_size: 30
<Screen2>:
name: "screen2"
FloatLayout:
Label:
text: "Screen 2"
pos_hint: {"top": 1.0}
Button:
on_release:
app.root.transition = SlideTransition(direction="right")
app.root.current = "screen1"
size_hint: 0.5, 0.8/3
pos_hint: {"top": 0.8, "right": 1}
text: "Screen 1 (slide right)"
font_size: 30
Button:
on_release:
app.root.transition = SlideTransition(direction="left")
app.root.current = "screen3"
size_hint: 0.5, 0.8/3
pos_hint: {"top": 0.8, "left": 1}
text: "Screen 3 (slide left)"
font_size: 30
<Screen3>:
name: "screen3"
FloatLayout:
Label:
text: "Screen 3"
pos_hint: {"top": 1.0}
Button:
on_release:
app.root.transition = SlideTransition(direction="right")
app.root.current = "screen1"
size_hint: 0.5, 0.8/3
pos_hint: {"top": 0.8, "left": 1}
text: "Screen 1 (slide right)"
font_size: 30