Overall question is: Why does my Kivy application crashes instantly?
My Python code is:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Line
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class TouchInput(Widget):
def on_touch_down(self, touch):
with self.canvas:
touch.ud["line"] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud["line"].points += (touch.x, touch.y)
presentation = Builder.load_file("simplekivy.kv")
class SimpleKivy(App):
def build(self):
return presentation
if __name__ == "__main__":
SimpleKivy().run()
My Kv. code is:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "Main"
Button:
on_release: app.root.current = "Other"
text: "Next screen!"
font_size: 50
<AnotherScreen>:
name: "Other"
FloatLayout:
TouchInput:
id: touch
Button:
on_release: app.root.current = "Main"
text: "Going back!"
font_size: 40
color: 0,1,0,1
size_hint: 0.3, 0.2
pos_hint: {'right': 1, 'top': 1}
Button:
on_release: touch.canvas.clear()
text: "Clear window"
font_size: 40
color: 0,1,0,1
size_hint: 0.3, 0.2
pos_hint: {'right': 1, 'top': 0}
When I would remove the 'Clear window'-Button, the application works as expected. However, the moment I add the button, it crashes instantly with the error message:
Python has stopped working
when you make a code in python and use kv the library itself will look for the .kv file in the same directory where the .py file is, so you do not have to start through 'presentation = Builder.load_file (" simplekivy. kv ")'
this can be solved changing the python code to:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.graphics import Line
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
class TouchInput(Widget):
def on_touch_down(self, touch):
with self.canvas:
touch.ud["line"] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud["line"].points += (touch.x, touch.y)
#don't need this
#presentation = Builder.load_file("simplekivy.kv")
class SimpleKivy(App):
pass
#I commented on that part of your code and added a 'pass' above
#def build(self):
# return presentation
if __name__ == "__main__":
SimpleKivy().run()
Related
I have three codes, I am confused with how I would navigate to the next screen in my Organize.kv from my login.py, I have the main kv file that has all the screens saved and the login python and kv file that manages the login screen, the login kv file balances two different tabs, so far I have the create tab that sends you to the create class of the login python file which is connected to mysql, how would I switch screens to the Main Menu which is in the main Organize.kv file from the login python file? Sorry if this doesn't make sense, I'm super warn out from trying to figure this out.
Anything helps, thank you
The main Organize.kv that has all the screens
#:import organize organize
#:import navigation_screen_manager navigation_screen_manager
#:import anchorlayout_with_action_bar anchorlayout_with_action_bar
#:import sharpen_skills sharpen_skills
#:import login login
<MainMenu#BoxLayout>:
orientation: "vertical"
padding: "40dp"
spacing: "20dp"
size_hint: .7, .9
pos_hint: {"center_x": .5}
Button:
text: "Organize"
on_press: app.manager.push("screen2")
Button:
text: "Journal"
on_press: app.manager.push("screen3")
Button:
text: "Sharpen Skills"
on_press: app.manager.push("SkillsExamplesTabs")
Button:
text: "Exit"
on_press: app.stop()
<MyScreenManager>:
Screen:
name: "Login"
title: "login"
LoginTabs:
Screen:
name: "MainMenu"
MainMenu:
Screen:
name: "screen2"
AnchorLayoutWithActionBar:
title: "Organize"
Screen:
name: "screen3"
AnchorLayoutWithActionBar:
title: "Journal"
Screen:
name: "SkillsExamplesTabs"
AnchorLayoutWithActionBar:
title: "Sharpen Skills"
SkillsExamplesTabs:
My login.kv file
<LoginTabs#TabbedPanel>:
do_default_tab: False
TabbedPanelItem:
text: "Create Account"
Create:
TabbedPanelItem:
text: "Login"
Login:
and finally my login.py file
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager
from kivy.uix.stacklayout import StackLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle
import mysql.connector
import navigation_screen_manager
from kivy.uix.screenmanager import ScreenManager, Screen
from navigation_screen_manager import NavigationScreenManager
Builder.load_file("login.kv")
Builder.load_file("Organize.kv")
sm = ScreenManager()
class MyScreenManager(NavigationScreenManager):
pass
class Create(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
self.build()
def build(self):
self.warning = Label(text="", pos_hint={'center_x': .5, 'center_y': .5})
user_label = Label(text="Username", size_hint=(.5, .5),
pos_hint={'center_x': .5, 'center_y': .5})
self.user_textinput = TextInput(text='Enter Username')
pas_label = Label(text="Password", size_hint=(.5, .5),
pos_hint={'center_x': .5, 'center_y': .5})
self.pas_textinput = TextInput(text="enter Password")
enter_button = Button(text="Create")
with user_label.canvas:
Color(0, .25, 1, .25)
enter_button.bind(on_press=self.Add)
self.add_widget(self.warning)
self.add_widget(user_label)
self.add_widget(self.user_textinput)
self.add_widget(pas_label)
self.add_widget(self.pas_textinput)
self.add_widget(enter_button)
def Add(self, btn):
print("Working")
t1 = self.user_textinput.text
t2 = self.pas_textinput.text
print(f"T1 = {t1} and {t2}")
conn = mysql.connector.connect(
user='root',
password='*******',
host='127.0.0.1',
database='Usersdb')
mycursor = conn.cursor()
try:
sql = "INSERT INTO user_info (user_name, user_pass) VALUES (%s, %s)"
val = (t1,t2)
mycursor.execute(sql,val)
conn.commit()
except:
self.warning = "Username Already Taken"
class Login(StackLayout):
pass
And finally my App class
from kivy.app import App
from kivy.uix.label import Label
from kivy.metrics import dp
from kivy.properties import StringProperty, BooleanProperty, ObjectProperty
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.stacklayout import StackLayout
from kivy.uix.widget import Widget
from navigation_screen_manager import NavigationScreenManager
class MyScreenManager(NavigationScreenManager):
pass
class Organizer(App):
manager = ObjectProperty(None)
def build(self):
self.manager = MyScreenManager()
return self.manager
Organizer().run()
And my Navigation Screen Manager
from kivy.uix.screenmanager import ScreenManager
class NavigationScreenManager(ScreenManager):
screen_stack = []
def push(self, screen_name):
self.screen_stack.append(self.current)
self.transition.direction = "left"
self.current = screen_name
def pop(self):
if len(self.screen_stack) > 0:
screen_name = self.screen_stack[-1]
del self.screen_stack[-1]
self.transition.direction = "right"
self.current = screen_name
Good day. You must access your screen manager in order to set the current screen which is your active screen. In your App class, I recommend saving your screen manager as an attribute via the on_start function.
class MyApp(App):
def on_start(self):
screen_manager = self.root
From there, you could set your current screen using callback methods in kivy or python.
#in kv
on_release: setattr(app.screen_manager, 'current', 'the next screen name')
#in python
def set_screen_callback(self, instance *args):
app.screen_manager.current = "the next screen name"
Your post does not include your App class, so a specific answer is impossible. The fact that you have multiple kv files is irrelevant once those kv files are loaded. In general, you just set the current property of the ScreenManager to the name of the Screen that you want displayed.
Again, the fact that you have multiple kv files is irrelevant once those kv files are loaded. So in any of the kv files, I believe that you should be able to use:
app.manager.push("MainMenu")
or:
app.manager.current = "MainMenu"
to get to the MainMenu Screen.
I have been started to work in kivy recently. The thing what I am doing now is, i have a blank page with a button, when I click that button it navigates to an user input screen. It works fine, but the content comes in a very small input boxes and text as in the picture.
My question is that I want it bigger and centred.
Here is my code:
In python:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.lang import Builder
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text="Username:"))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text="Password:"))
self.password = TextInput(multiline=False, password=True)
self.add_widget(self.password)
self.add_widget(Label(text="Two Factor Auth:"))
self.tfa = TextInput(multiline=False)
self.add_widget(self.tfa)
class MainScreen(Screen):
pass
class AnotherScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("screen.kv")
class SimpleKivy(App):
def build(self):
return presentation
if __name__ == "__main__":
SimpleKivy().run()
In kv:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
ScreenManagement:
transition: FadeTransition()
MainScreen:
AnotherScreen:
<MainScreen>:
name: "main"
Button:
color: 0,1,0,1
font_size: 25
size_hint: 0.3,0.2
text: "Click"
on_release: app.root.current = "other"
pos_hint: {"right":1, "top":1}
<AnotherScreen>:
name: "other"
GridLayout:
LoginScreen
In your screen.kv, you have the LoginScreen inside a GridLayout. Since the LoginSCreen is a GridLayout, you do not need that extra GridLayout.
Just change:
<AnotherScreen>:
name: "other"
GridLayout:
LoginScreen
to:
<AnotherScreen>:
name: "other"
LoginScreen:
I want to print out the position of the pointer (mouse) everytime it passes over a widget. Actually to be more specific I'd like to print the current position of the mouse everytime it moves. Is that at all possible?
Right now all I've managed to do is:
Print the position of the mouse whenever the mouse is clicked
(in two different ways)
Print the position of the widget when it's clicked
I'm sure it's easier than I think, thanks in advance.
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.app import App
from kivy.uix.button import Button
from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.input.motionevent import MotionEvent
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
def on_mouse_pos(self, pos):
if Window.mouse_pos == self.ids.example_button:
print("You've made it")
# With out this if statement it does print the position every time
# That the mouse is moved. But can I print "You've made it" every time
# that the mouse is moved over the position of a widget?
print(pos)
def test_print(self):
print(str(self.ids.example_button.pos))
Window.bind(mouse_pos = on_mouse_pos)
class MyScreenManager(Screen):
pass
root_widget = Builder.load_string('''
MyScreenManager:
MainScreen:
<MainScreen>:
name: 'Example'
Button:
id: example_button
text: 'Print position of widget when mouse touches it'
size_hint: 1, .05
pos_hint: {'x': 0, 'y': .5}
on_release: root.test_print()
''')
class TestApp(App):
def build(self):
self.title = 'Example Application'
return root_widget
if __name__ == '__main__':
TestApp().run()
A possible solution is to use mouse_pos:
from kivy.core.window import Window
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainScreen(Screen):
def on_mouse_pos(self, pos):
print(pos)
Window.bind(mouse_pos = on_mouse_pos)
class MyScreenManager(Screen):
pass
root_widget = Builder.load_string('''
MyScreenManager:
MainScreen:
<MainScreen>:
name: 'Example'
Button:
id: example_button
text: 'I am button'
size_hint: 1, .05
pos_hint: {'x': 0, 'y': .5}
''')
class TestApp(App):
def build(self):
self.title = 'Example Application'
return root_widget
if __name__ == '__main__':
TestApp().run()
Update:
If you want to verify that the mouse point is inside a widget you must use collide_point.
from kivy.core.window import Window
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
Window.bind(mouse_pos = self.on_mouse_pos)
def on_mouse_pos(self, instance, pos):
if self.ids.example_button.collide_point(*pos):
print("You've made it")
class MyScreenManager(Screen):
pass
root_widget = Builder.load_string('''
MyScreenManager:
MainScreen:
<MainScreen>:
name: 'Example'
Button:
id: example_button
text: 'I am button'
size_hint: 1, .05
pos_hint: {'x': 0, 'y': .5}
''')
class TestApp(App):
def build(self):
self.title = 'Example Application'
return root_widget
if __name__ == '__main__':
TestApp().run()
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
I need to dismiss the pop up after finishing a function in another class, or at least after specific time like (3 second)
the pop up displaying loading gif image
to notify the user to wait for operating the functions
loading image
*******python******
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class ScreenManagement(ScreenManager):
pass
class progress(Popup):
pass
class Func_(Screen):
# function
pass
presentation = Builder.load_file("Try_.kv")
class MainApp(App):
def build(self):
return presentation
if __name__ == "__main__":
MainApp().run()
********KV File*********
#:import Factory kivy.factory.Factory
<Popup>:
separator_color: 1, 1, 1, 1
background: "White.png"
Button:
id: btn
disabled: True
background_disabled_normal: "White.png"
text: "Hello"
Image:
source: "Loading.gif"
size: root.size
ScreenManagement:
PopupBox:
<PopupBox>:
BoxLayout:
Button:
text: "Click"
on_release:
Factory.Popup().open()
You have to add a function to dismiss the Popup message and use Clock.schedule_once to call that function. Please refer to the example below for details.
main.py
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
class ScreenManagement(ScreenManager):
pass
class Progress(Popup):
def __init__(self, **kwargs):
super(Progress, self).__init__(**kwargs)
# call dismiss_popup in 2 seconds
Clock.schedule_once(self.dismiss_popup, 2)
def dismiss_popup(self, dt):
self.dismiss()
class Func(Screen):
# function
pass
class MainApp(App):
def build(self):
return ScreenManagement()
if __name__ == "__main__":
MainApp().run()
main.kv
#:import Factory kivy.factory.Factory
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
<Progress>:
separator_color: 1, 1, 1, 1
background: "White.png"
Button:
id: btn
disabled: True
background_disabled_normal: "White.png"
text: "Hello"
Image:
source: "Loading.gif"
size: root.size
<ScreenManagement>:
transition: FadeTransition()
Func:
<Func>:
BoxLayout:
Button:
text: "Click"
on_release:
Factory.Progress().open()
Output