Kivy - Black Screen between transitions - python

I'm trying to copy this gif, which is done in Kivy (here's the link to the full page )
Just as I started, I noticed a black screen between transition (link to what it looks like so you don't have to copy-paste and run)
Why does that black screen appear?
EDIT: I must work without buttons.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
# Create both screens. Please note the root.manager.current: this is how
# you can control the ScreenManager from kv. Each screen has by default a
# property manager that gives you the instance of the ScreenManager used.
Builder.load_string("""
<MenuScreen>:
canvas.before:
Color:
rgba: 122,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
<SettingsScreen>:
canvas.before:
Color:
rgba: 0,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
""")
# Declare both screens
class MenuScreen(Screen):
def on_touch_down(self, touch):
sm.current = 'settings'
class SettingsScreen(Screen):
def on_touch_down(self, touch):
sm.current = 'menu'
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
EDIT: I've tried this but still not working
<sm>:
canvas:
Color:
rgb: (0, 255, 255)
Rectangle:
size: self.size
pos: self.pos

You are not supposed to use the Screen subclasses directly. Instead you must add a component first (e.g. Button or Layout), for example use RelativeLayout:
Builder.load_string("""
<MenuScreen>:
RelativeLayout:
canvas.before:
Color:
rgba: 122,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
<SettingsScreen>:
RelativeLayout:
canvas.before:
Color:
rgba: 0,255,0,2
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'hello'
""")

That black area is a canvas of the screen manager. If you don't like it black, then you can paint it, just like you did with screens; or change transition type to NoTransition to hide it.
Also, you should consider building your screen manager inside that kv lang string.

Old, but in case anyone runs into this issue:
To clarify the vague responses in the comments, you need to paint your screen manager the same way you would paint a screen.
Example in kvlang:
ScreenManagement:
canvas.before:
Color:
rgba: 1,1,1,1
Rectangle:
size: self.size
pos: self.pos
id: screen_manager
transition: NoTransition()
Screen1:
Screen2:
Settings_:

Related

KIvy using a circles position to place a button

I have drawn a circle. I want to place a button at the same position of the circle. How can I get the circle's x and y coordinates. My code(in kv file):
MainWidget:
<MainWidget>:
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
id: point
size: 100, 100
pos: 100, root.y1
Button:
id: No1
pos: point.pos
on_press: root.move()
It shows "NameError: name 'point' is not defined"
Put your widgets in BoxLayout. You can't use id for canvas, you should use groups.
Circle above the button.
from kivy.lang import Builder
from kivy.app import App
KV = '''
Screen:
BoxLayout:
orientation: 'vertical'
spacing: 10
BoxLayout:
size_hint_x: None
pos_hint: {'center_x': .5}
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
size: 100, 100
pos: self.pos
BoxLayout:
Button:
id: No1
on_press: pass
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
Circle in the button.
from kivy.lang import Builder
from kivy.app import App
KV = '''
Screen:
BoxLayout:
padding: 50
Button:
on_press: pass
canvas.after:
Color:
rgb: 1, 0, 0
Ellipse:
size: self.size
pos: self.pos
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
So you can place the circle at the same position as the button.
Ellipse:
size: 100, 100
pos: self.pos

How to target canvas.before in kv

In a button i have made a rounded button with canvas.before, and it changes colors as it should. The line is:
canvas.before:
Color:
rgba: btn_color_not_pressed if self.state=='normal' else btn_color_pressed
RoundedRectangle:
size: self.size
pos: self.pos
radius: [40]
The variables btn_color_not_pressed and btn_color_not_pressed are made with #:set in the start of the kv-file
I have tried to target the line with self.canvas.before.Color.rgba, as i am used to normally, but i get following error:
AttributeError: 'kivy.graphics.instructions.CanvasBase' object has no attribute 'Color'
How do i target that line from within kv and replace the variables ... or if necessary from the python file.?
How do i target the source: "some_file.jpg under Rectangle?
My goal is that when a user has clicked an option all the button colors (and maybe the background) in the app must change.
You cannot change the variables created in kv. Once your app is running, those variables no longer exist. You can, however, use a Property that is created in kv (or python) as an attribute of a class (or the App itself). Such Properties continue to exist while the App is running, and kivy recognizes such Properties and will automatically handle changes to those Properties. An example is to create a new class that extends Button and has Properties like you want:
<-MyButton#Button>:
# create the desired properties
btn_color_not_pressed: [.5, .5, .5,1]
btn_color_pressed: [.25, .25, .25, 1]
canvas:
Color:
# reference the above properties
rgba: self.btn_color_not_pressed if self.state=='normal' else self.btn_color_pressed
RoundedRectangle:
size: self.size
pos: self.pos
radius: [40]
# this is copied from style.kv to show the Button text
Color:
rgba: 1, 1, 1, 1
Rectangle:
texture: self.texture
size: self.texture_size
pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)
# actually make an instance of the new MyButton class
MyButton:
btn_color_not_pressed: [1,0,0,1]
btn_color_pressed: [0,1,0,1]
text: 'Button Test'
The <-MyButton#Button> creates a new class (MyButton) that extends Button. The prepended - indicates that the default canvas instructions for Button are not to be used and the provided instructions are used instead. Those new Properties can be changed in python code as usual. You can use a similar approach for the source property.
That brought me a step closer.
My problem now is that the colors only change the button itself or togglebutton-group, but only when you click on them. It only reacts to the new colors when activated (button og group).
The design is not updated
I tried the solution with the - but it made no difference
main.py
import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ToggleButtonBehavior
from kivy.factory import Factory
kivy.require("1.11.1")
class Controller(BoxLayout):
def __init__(self):
super(Controller, self).__init__()
ToggleButtonBehavior.allow_no_selection = False
def change_button_color(self,theme):
if theme == "red":
Factory.My_tgl_btn.btn_color_pressed = (1,0,0,.7)
Factory.My_tgl_btn.btn_color_not_pressed = (1,0,0,.5)
else: # theme == "blue":
Factory.My_tgl_btn.btn_color_pressed = (0,0,1,.7)
Factory.My_tgl_btn.btn_color_not_pressed = (0,0,1,.5)
class mainApp(App):
def build(self):
return Controller()
if __name__ == "__main__":
mainApp().run()
main.kv
#:set bg_color 1,1,1,.7
#:set txt_color 0,0,0,1
#:import Factory kivy.factory.Factory
<Controller>
BoxLayout:
orientation: "vertical"
background_color: 1,1,1,.5
background_normal: ""
Label:
text: "THIS IS THE MAIN TEKST"
color: txt_color
size_hint_y:.7
BoxLayout:
size_hint_y: .15
My_tgl_btn:
text: "RED theme"
group: 1
state: "down"
on_press: root.change_button_color("red")
on_release: root.change_button_color("red")
My_tgl_btn:
text: "Blue theme"
group: 1
on_press: root.change_button_color("blue")
on_release: root.change_button_color("blue")
BoxLayout:
size_hint_y: .15
My_tgl_btn:
text: "Option1"
group: 2
state: "down"
My_tgl_btn:
text: "Option2"
group: 2
state: "normal"
<My_tgl_btn#ToggleButton>
btn_color_pressed: 1,0,0,.7
btn_color_not_pressed: 1,0,0,.5
color: txt_color
background_color: 0,0,0,0
background_normal: ""
canvas.before:
Color:
rgba:self.btn_color_not_pressed if self.state=='normal' else self.btn_color_pressed
RoundedRectangle:
size: self.size
pos: self.pos
radius: [40]
Found a solution (here: Kivy: resetting toggle buttons to "normal" on re-entering screen)
It's kind'a ugly, but it works..
Give every button an id ... and then use on_enter for each button and set and change the state.
In the code above it would mean:
on_enter:
button1.state = "down"
button1.state = "normal"
button2.state = "down"
button2.state = "normal"
button3.state = "down"
button3.state = "normal"
button4.state = "down"
button4.state = "normal"
It works ... but it is not pretty :|

Multiple text fields inside of kivy text input

I'm working on on a scientific calculator using kivy, is there a way i insert multiple text fields in kivy text input like in below image. thanks for your help.
Not sure exactly what you want, but you can combine TextInput widgets. Here is an example:
from kivy.app import App
from kivy.factory import Factory
from kivy.lang import Builder
kv = '''
<-TextInputNoBorder#TextInput>:
# eliminates the TextInput border
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
Color:
rgba:
(self.cursor_color
if self.focus and not self._cursor_blink
else (0, 0, 0, 0))
Rectangle:
pos: self._cursor_visual_pos
size: root.cursor_width, -self._cursor_visual_height
Color:
rgba: self.disabled_foreground_color if self.disabled else (self.hint_text_color if not self.text else self.foreground_color)
<MyTextInput#BoxLayout>:
# combine three TextInput Widgets to appear as one
orientation: 'vertical'
TextInputNoBorder:
id: ti1
text: 'This is One'
TextInputNoBorder:
id: ti2
text: 'This is Two'
TextInputNoBorder:
id: ti3
text: 'This is Three'
'''
class TestApp(App):
def build(self):
Builder.load_string(kv)
return Factory.MyTextInput()
TestApp().run()
This example just stacks three TextInput widgets vertically, but they could be arranged and sized in many ways. The TextInputNoBorder widget extends the TextInput widget by redefining its appearance (eliminating the border).

can't position label with round button to top corner kivy

I am trying to get a label with in it a rounded button to be placed in top left corner, but can't seem to get it done.
tried pos_hint in both < BackLabel > and < SubScreen >-->backlabel.
excerpts from my code:
tryout.py:
class RoundedButton(Button):
pass
class BackLabel(Label):
def __init__(self, **kwargs):
super(BackLabel, self).__init__(**kwargs)
self.RoundedButton=RoundedButton()
self.add_widget(self.RoundedButton)
class SubScreen(Screen):
def __init__(self, **kwargs):
super(SubScreen, self).__init__(**kwargs)
self.BackLabel = BackLabel(id='bl')
self.add_widget(self.BackLabel)
self.OpenLink = Button(id= 'forward')
self.add_widget(self.OpenLink)
self.Footer = Label(id='footer')
self.add_widget(self.Footer)
.kv file:
<BackLabel#Label>:
background_color: 0,0,0,0
canvas.before:
Color:
rgb: 0, 1, 0
RoundedRectangle:
size: [100,100]
radius: [50,]
<RoundedButton#Button>:
background_color: 0,0,0,0 # the last zero is the critical on, make invisible
canvas.before:
Color:
rgba: (.4,.4,.4,1) if self.state=='normal' else (0,.7,.7,1) # visual feedback of press
RoundedRectangle:
size: [100,100]
radius: [50,]
text:'<--Back'
on_release: app.root.current = 'mainmenu'
<SubScreen>
name: 'submenu'
BackLabel:
id: 'bl'
It is difficult to interpret exactly what you are attempting to do. For example, why are you adding a RoundedButton to a BackLabel in the __init__() method of your BackLabel? Anyway, here is a simpler version of your code that does what I think you want. A couple things to note: In order to position a Widget meaningfully, it must have a reasonable size. The default size of any Widget is the same as its parent, so positioning it doesn't really make sense. So my code below sets the size of your RoundButton (which requires size_hint to be (None, None). Finally, the position can be set (as in the SubScreen rule in the kv below):
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
class SubScreen(Screen):
pass
Builder.load_string('''
<RoundedButton#Button>:
size_hint: (None, None)
size: (100, 100)
background_color: 0,0,0,0 # the last zero is the critical on, make invisible
canvas.before:
Color:
rgba: (.4,.4,.4,1) if self.state=='normal' else (0,.7,.7,1) # visual feedback of press
RoundedRectangle:
pos: (self.center_x - 50, self.center_y - 50)
size: self.size
radius: [50,]
text:'<--Back'
on_release: app.root.current = 'mainmenu'
<SubScreen>
name: 'submenu'
RoundedButton:
pos: (0, root.height-self.height)
''')
class TheApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(SubScreen())
return sm
TheApp().run()

How do you change the background color of a TabbedPanelItem in Kivy

I want to change the background color on my tabs and change from the default grey color, but I can't manage to find out how to do it.
I have tried defining a canvas but that just ends up creating like a colored layer over the tab and then I can't read the text on the tab.
my .py file:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class IntroScreen(Screen):
pass
class MainScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
app=Builder.load_file("main.kv")
class mainApp(App):
def build(self):
return app
mainApp().run()
main.kv file:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import get_color_from_hex kivy.utils.get_color_from_hex
ScreenManagement:
transition: FadeTransition()
MainScreen:
<MainScreen>:
name: "main_screen"
BoxLayout:
orientation: "horizontal"
height: 30
BoxLayout:
orientation: "horizontal"
TabbedPanel:
do_default_tab: False
tab_width: self.parent.width/2
canvas.before:
Color:
rgb: get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
TabbedPanelItem:
text: "Tab 1"
color: get_color_from_hex("#ffffff")
markup: True
Label:
text: "contents of tab 1"
color: get_color_from_hex("#000000")
canvas.before:
Color:
rgb: get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
TabbedPanelItem:
text: "Tab 2"
markup: True
Label:
text: "contents of tab 2"
color: get_color_from_hex("#000000")
canvas.before:
Color:
rgb: get_color_from_hex("#ffffff")
Rectangle:
size: self.size
pos: self.pos
The tab is a class of TabbedPanelHeader and they have the following properties just like Button widget.
Example
Add the following into kv file:
<TabbedPanelHeader>:
background_normal: 'blue.png'
background_down: 'red.png'
Output

Categories