Problems with Kivy Screen Manager Python - python

I've been searching the internet for a fix, yet i can't seem to fix it..
I wanted to make a Game wherein of course there is a Menu and the Play Screens, But the Button are enormously big, despite of "size: 50, 50" and "pos: 300, 200"
main.py:
from kivy.app import App
from kivy.uix.widget import Widget
#from kivy.core.window import Window
#from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.config import Config
from kivy.core.image import Image
from kivy.graphics import BorderImage
from kivy.graphics import Color, Rectangle
from kivy.uix.image import AsyncImage
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen, CardTransition
import time
import random
# Config.set('graphics', 'width', '1000')
# Config.set('graphics', 'height', '800')
class GridButtons(GridLayout):
pass
class screen1(Screen):
pass
class screen2(Screen):
pass
class GameApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(screen1(name='menu'))
sm.add_widget(screen2(name='game'))
return sm
if __name__ == '__main__':
GameApp().run()
kivy.kv
#kivy 2.0.0
<screen1>:
orientation: 'vertical'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'gamebg.jpg'
GridButtons:
cols: 1
rows: 1
Button:
size: 2, 2
pos: 10, 20
text: 'Play'
The screen i'm getting
I want the Play Button in the middle of the screen, and resizes automatically

If you want to set a widget of your desired size within a layout you have to disable the size_hint attr. Thus the change you need is,
Button:
size_hint: None, None
size: 2, 2
I want the Play Button in the middle of the screen..
Since you are adding Button directly within GridLayout and it manages its children's position automatically (by default lr-tb meaning left to right, top to bottom; from version 2.0.0), none of pos or pos_hint will work as intended.
To achieve this you may add it within a FloatLayout as,
FloatLayout:
Button:
size_hint: None, None
size: 2, 2
pos_hint: {"center_x" : 0.5, "center_y" : 0.5}

Related

Pictures comes up on simulator but doesn’t on iPhone

I’m trying to make app with kivy-iOS. It works perfectly on simulator, but doesn’t on iPhone.
On iPhone, App works with characters, but only pictures are vanished.
My app has only easy structure, Buttom has .jpg background, once push it, it goes to other buttons.
I use Pycharm to make .py and .kv file. On .kv,
<MenuScreen>:
canvas:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
GridLayout:
rows: 3
cols: 3
Button:
background_normal: "../file-ios/filename/filename.jpg"
text_size: self.size
valign: "top"
color: 0, 1, 0, 1
font_size: "30"
bold: True
text: "text"
on_press: root.manager.current = 'Ask'
(abbreviate)
On main.py
from kivy.config import Config
Config.set('graphics', 'width', '500')
Config.set('graphics', 'height', '500')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.widget import Widget
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics.texture import Texture
from kivy.properties import NumericProperty
from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path
resource_add_path("/System/Library/Fonts")
LabelBase.register(DEFAULT_FONT, "ヒラギノ角ゴシック W0.ttc")
class MenuScreen(Screen):
pass
(abbreviate)
class mainApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
(abbreviate)
return sm
def __init__(self, **kwargs):
super(mainApp, self).__init__(**kwargs)
self.title = "Filename"
if __name__ == "__main__":
mainApp().run()
I’ve already tried CleanBuildFolder.
If you have some advice, please help me. Thanks in advance.

(Kivy) How do I display new content on my canvas in Kivy?

This should be a pretty easy fix. I'm new to Kivy. I'm trying to have the canvas cleared on a button press, and then display a new widget to essentially move to another page. When I run it and press the button, the canvas is cleared, but I get nothing from IntroPage.
Python Script:
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
class ABT(App):
def build(self):
return WelcomePage()
class WelcomePage(Widget):
def btn(self):
self.canvas.clear()
print('pressed')
return IntroPage()
class IntroPage(Widget):
def __init__(self):
pass
if __name__ == '__main__':
ABT().run()
KV File:
<WelcomePage>
canvas.before:
Color:
rgba: (.43,.51,.92,.26)
Rectangle:
pos: self.pos
size: self.size
GridLayout:
cols:1
size: root.width, root.height
Image:
source: 'abt1t.png'
size_hint: (1,.8)
Button:
text:"begin"
background_color: (.43,.51,.92,.26)
size_hint: (1,.2)
on_press: root.btn()
<IntroPage>
GridLayout:
cols:1
Label:
text:"This won't show up!"
Returning IntroPage from btn won't work, as btn isn't a build method.
The best way to implement multiple pages is probably to use ScreenManager:
from kivy.uix.screenmanager import ScreenManager, Screen
class ABT(App):
def build(self):
sm = ScreenManager()
sm.add_widget(WelcomePage(name="welcome"))
sm.add_widget(IntroPage(name="intro"))
return sm
class WelcomePage(Screen):
def btn(self):
print('pressed')
self.manager.current = "intro"
class IntroPage(Screen):
def __init__(self):
pass

Making part of the screen a scrollable image with kivy

I'm trying to get a part of the screen a scrollable image, so it will fit in the screen without ruining the image ratio (referring to notebook.jpg in the code). I saw some comments that suggested using ScrollView, but I couldn't really figure out how to add it to the existing class I already have (I mean as a second class in addition to NotebookScreen, so NotebookScreen will be able to use it).
Would really appreciate some help :)
Python code:
import kivy
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
GUI = Builder.load_file('style.kv')
# Window.size = (2224, 1668)
class NotebookScreen(GridLayout):
def __init__(self, **kwargs):
self.rows = 1
super(NotebookScreen, self).__init__(**kwargs)
class MainApp(App):
def build(self):
return NotebookScreen()
if __name__ == "__main__":
MainApp().run()
kivy code:
<NotebookScreen>
FloatLayout:
rows: 2
GridLayout:
size_hint: 1, .05
pos_hint: {"top": 1, "left": 1}
id: tool_bar
cols: 1
canvas:
Color:
rgba: 0, 0, 1, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
id: notebook_grid
size_hint: 1, .95
pos_hint: {"top": .95, "left": 0}
cols: 1
Image:
id: notebook_image
source: 'images/notebook.jpg'
allow_stretch: True
keep_ratio: True
pos: self.pos
size_hint: 1, 1
Here is a quick and dirty example of how you could do that. I simply used a Label's canvas to draw the image. I added the label to the scrollview and added scrollview along with another label to show you that you don't need to have the entire screen for your scrolling part. I only used PIL to get the size of the image, because I wanted to make sure that your window is smaller than the image you want to scroll. I hope it helps you with your approach.
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.core.window import Window
from kivy.graphics import Rectangle
from PIL import Image
class MyApp(App):
def build(self):
img = Image.open("path/to/your/image/dummy.jpg")
Window.size = (img.size[0]*0.8, img.size[1]*1.2)
layout = BoxLayout(orientation="vertical", size_hint=(None, None), size=Window.size)
lbl = Label(text="This is your picture!", size_hint=(None, None), size=(Window.width, Window.height*0.5))
layout.add_widget(lbl)
sv = ScrollView(size_hint=(None, None), size=(Window.width, Window.height*0.5))
img_box = Label(size_hint=(None, None), size=img.size)
with img_box.canvas:
Rectangle(source="path/to/your/image/dummy.jpg", size=img.size)
sv.add_widget(img_box)
layout.add_widget(sv)
return layout
MyApp().run()
[EDIT]
Here is basically the same thing I made at first, but with some outsourcing to a kv string. I hope this is now, what you are looking for.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.lang.builder import Builder
from PIL import Image
kv = """
#:import Window kivy.core.window.Window
<MyImageView>:
orientation: "vertical"
size_hint: None, None
size: Window.size
Label:
text: "This is your picture!"
size_hint: None, None
size: Window.width, Window.height * .5
ScrollView:
size_hint: None, None
size: Window.width, Window.height * .5
Label:
id: img_box
size_hint: None, None
size: root.img.size
canvas:
Rectangle:
source: root.img_path
size: root.img.size
"""
class MyImageView(BoxLayout):
def __init__(self, img_path, **kwargs):
self.img_path = img_path
self.img = Image.open(self.img_path)
Window.size = (self.img.size[0] * 0.8, self.img.size[1] * 1.2)
super(MyImageView, self).__init__(**kwargs)
class MyApp(App):
def build(self):
Builder.load_string(kv)
layout = MyImageView("Path/to/your/image.png")
return layout
MyApp().run()

Scrollview to display different videos in kivy lags after a while

I'm a beginner in kivy and python. I've been trying to create a scrollview in a page that displays selected video on the screen. But after a while when i selected 5-6 videos to display even though i delete the video widget it starts to lag. And i'm open to any suggestions to better way to handle this kind of application.
from kivy.config import Config
Config.set('graphics', 'width', '1920')
Config.set('graphics', 'height', '1080')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.properties import StringProperty
from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.uix.button import Button
import os
from kivy.uix.video import Video
from kivy.uix.videoplayer import VideoPlayer
from kivy.clock import mainthread
from functools import partial
from kivy.core.window import Window
Window.clearcolor = (0, 0, 0, 0)
isThereVideo=False
picture_path="/home/linux/kivyFiles/kivyLogin/assets"
video_path="/home/linux/kivyFiles/kivyLogin/videoAssets/"
class Image(Image):
pass
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class Selfie(Screen):
pass
class RootWidget(Widget):
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
Clock.schedule_once(self.createMultipleButton)
#mainthread
def createMultipleButton(self, dt):
self.root = Widget()
size_y=150;
size_x=150;
for i in range(1):
folderList = os.listdir(picture_path)
if len(folderList)==0:
time.sleep(1)
break
fileList = os.listdir(picture_path)
print fileList
for file in fileList:
x = (picture_path+"/"+file)
button = Button(id=str(file),text="" + str(file),size_hint=(None, None),height=size_y,width=size_x, pos_hint={'x': 0, 'y': 1},background_normal=x)
button.bind(on_release=partial(self.VideoContainer, file))
print file
self.scrollview.content_layout.add_widget(button)
print button.id
print("Parent of ScreenTwo: {}".format(self.parent))
#print(button.pos)
def VideoContainer(self,name,btn):
global isThereVideo
if isThereVideo==True:
#self.videocontainer.video_layout.unload()
self.videocontainer.clear_widgets()
mylist=name.split('.')
emailButton = Button(id='email')
video = Video(source="/home/linux/kivyFiles/kivyLogin/videoAssets/"+mylist[0]+".mp4", state='play',options={'eos': 'loop'})
video.size=(self.parent.width,self.parent.height)
video_pos=(self.parent.x,self.parent.y)
#video.pos_hint={'x': self.parent.width /2, 'y': self.parent.height/2}
video.play=True
#video.pos=(self.parent.width /2 , self.parent.height/2)
#self.videocontainer.video_layout.add_widget(emailButton)
self.videocontainer.add_widget(emailButton)
emailButton.add_widget(video)
isThereVideo=True
print("Parent of ScreenTwo: {}".format(self.parent))
return 0
class ScreenManagement(ScreenManager):
pass
class VideoContain(Widget):
pass
class ScrollableContainer(ScrollView):
pass
presentation = Builder.load_file("login.kv")
class MainApp(App):
def build(self):
return presentation
if __name__ == '__main__':
Window.fullscreen = True
app=MainApp()
app.run()
And my Kv file
ScreenManagement:
MainScreen:
Selfie:
<MainScreen>:
name: 'main'
Button:
on_release: app.root.current = 'selfie'
text: 'Another Screen'
font_size: 50
<Selfie>:
name: 'selfie'
Button:
on_release: app.root.current = 'login'
text: 'Selfie Screen'
font_size: 10
pos_hint: {"right": 1, 'top':1}
size_hint: (0.1, 0.1)
RootWidget:
<RootWidget>
size_hint: (0.1, None)
scrollview: scrollview
videocontainer:videocontainer
size:(self.parent.width, self.parent.height)
VideoContain:
id:videocontainer
##size:(self.parent.width, self.parent.height)
size:(root.width, root.height)
ScrollableContainer:
id: scrollview
size: root.size
pos: root.pos
<VideoContain>
video_layout:video_layout
FloatLayout:
cols:1
id: video_layout
<ScrollableContainer>:
scroll_timeout: 75
scroll_distance: 10
app: app
content_layout: content_layout
GridLayout:
id: content_layout
cols: 1
size_hint: (0.1, None)
pos: root.pos
height: self.minimum_height
padding: 25
spacing: 25
I posted all my code since i don't know which part may causing the problem i'm facing.
Solved it.
def VideoContainer(self,name,btn):
global isThereVideo
if isThereVideo:
# self.videocontainer.video_layout.unload()
self.videocontainer.clear_widgets()
In this part i'm clearing the widgets but i also need to unload the video somehow.
self.video.unload() solved my problem

Changing kivy widget properties within Class

I'm having difficulty figuring out how to change the text of a label within a kivy widget. For simplicity, I have a label set to 0 and I would like to change the text to read 30 in this example. However, I get the following error.
AttributeError: 'super' object has no attribute 'getattr'
I understand that I'm probably not properly targeting that widget and I am hoping someone can please explain how to specifically reference the text of this label (self.ids.mainel1temp.stuff_r.text = '30') to update (with more detail than fixing the code)
#!/usr/bin/kivy
import kivy
from random import random
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.switch import Switch
from kivy.uix.label import Label
from kivy.config import Config
Config.set('graphics', 'width', '800')
Config.set('graphics', 'height', '480')
Builder.load_string("""
<Menuscreen>:
#Handling the gesture event.
ScreenManager:
id: manager
Screen:
id: main_screen
name:'main_screen'
stuff_r: mainel1temp
FloatLayout:
Label:
id: mainel1temp
size: self.texture_size
text:'0'
size_hint: None, None
text_size: 75,75
pos: 295,308
font_size:'20sp'
halign: 'center'
""")
class Thermostuff(Screen):
stuff_r = ObjectProperty(None)
def starttherm(self):
Clock.schedule_interval((self.read_temp), 1)
def read_temp(self, dt):
self.ids.mainel1temp.stuff_r.text = '30'
Thermrun = Thermostuff()
Thermrun.starttherm()
class MenuScreen(Screen):
pass
sm = ScreenManager()
menu_screen = MenuScreen(name='menu')
sm.add_widget(menu_screen)
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
You do a couple of things wrong here.
You dont want to put a ScreenManager inside a Screen
Only one ScreenManager is needed.
Then you can start the Clock in the __init__ of the Thermostuff(Screen)
Or if you want it to initiate on_enter you need to overrite that. In that case you might want to check somehow, if its allready started, so you wont have multiple clocks running.
Then when you create an ObjectProperty you dont need self.ids, because you allready created that property. So self.stuff_r is now the label.
I rewrote your example a bit, to demonstrate this.
Try this:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.properties import ObjectProperty
from kivy.clock import Clock
sm = """
#Handling the gesture event.
ScreenManager:
id: manager
MenuScreen:
Button:
text: "Go to Thermostuff"
on_release:
root.current = "main_screen"
Thermostuff:
name:'main_screen'
stuff_r: mainel1temp
FloatLayout:
Label:
id: mainel1temp
size: self.texture_size
text:'0'
size_hint: None, None
text_size: 75,75
pos: 295,308
font_size:'20sp'
halign: 'center'
"""
class Thermostuff(Screen):
stuff_r = ObjectProperty(None)
test_temp = 0
def __init__(self,**kwargs):
super(Thermostuff,self).__init__(**kwargs)
Clock.schedule_interval((self.read_temp), 1)
def read_temp(self, dt):
self.test_temp += 1
self.stuff_r.text = str(self.test_temp)
class MenuScreen(Screen):
pass
class TestApp(App):
def build(self):
return Builder.load_string(sm)
if __name__ == '__main__':
TestApp().run()

Categories