I am new to Kivy and I am sort of stuck. I am using GridLayout to make my app and I am having some trouble putting a video in my background. The code I will post makes an app with a black background. How do I replace the black background with a video, particularly mp4. I would also like to make the video darker if possible. I wanted to use AnchorPoint but I am not quite sure how to put both in there. Any help will be appreciated.
from kivy.app import App
from kivy.uix.video import Video
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
class MZ_Invest(App):
def build(self):
self.root_layout = FloatLayout()
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.6,0.7)
self.window.pos_hint = {"center_x":0.5, "center_y":0.5}
#add widgets
#Video
video = Video(source='birds.mp4', state='play')
video.opacity = 0.5
#Image
self.window.add_widget(Image(
source="mzi.png",
size_hint = (1.5,1.5)
))
#Label
self.greeting = Label(
text="How much would you like to invest?",
font_size = 18,
color='90EE90'
)
self.window.add_widget(self.greeting)
#User Input
self.user = TextInput(
multiline=False,
padding_y= (20,20),
size_hint = (1, 0.5)
)
self.window.add_widget(self.user)
#Button
self.button = Button(
text="Submit",
size_hint = (1,0.5),
bold = True,
background_color = '90EE90',
)
self.button.bind(on_press=self.callback)
self.window.add_widget(self.button)
#self.root_layout.add_widget(video)
self.root_layout.add_widget(self.window)
return self.root_layout
def callback(self, instance):
if self.user.text.isnumeric() and int(self.user.text) >= 10000:
self.greeting.text = "Calculating: $" + self.user.text
self.greeting.color = '90EE90'
else:
self.greeting.text = "Invalid"
self.greeting.color = "#FF0000"
if __name__ == "__main__":
MZ_Invest().run()
Most Kivy widgets have a transparent background, so you can just display a video and then display your GUI over that. Try adding something like this at the end of your build() method:
self.root_layout = FloatLayout()
video = Video(source='BigBuckBunny.mp4', state='play')
video.opacity = 0.5 # adjust to make the video lighter/darker
self.root_layout.add_widget(video) # add the video first
self.root_layout.add_widget(self.window) # now add the GUI window so it will be drawn over the video
return self.root_layout # return the root_layout instead of the window
Related
I built a simple app using pytube with which you can download Youtube videos.
That's the code:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from pytube import YouTube
import os
class AVPlayer(App):
def build(self):
self.window = GridLayout()
self.window.cols = 1
self.user = TextInput(
padding_y = (20, 20),
size_hint = (1, 0.5),
)
self.window.add_widget(self.user)
self.window.size_hint = (0.6, 0.2)
self.window.pos_hint = {"center_x": 0.5, "center_y": 0.5}
self.button = Button(
text="Download",
size_hint = (1, 0.5),
background_color = '#398AFF'
)
self.button.bind(on_press=self.callback)
self.window.add_widget(self.button)
return self.window
def callback(self, event):
url = self.user.text
my_video = YouTube(url)
#get Video Title
print("*********************Video Title************************")
print(my_video.title)
#get Thumbnail Image
print("********************Tumbnail Image***********************")
print(my_video.thumbnail_url)
#download
print("********************Download video*************************")
#my_video = my_video.streams.get_highest_resolution().download()
my_video = my_video.streams.filter(res="360p").first().download()
if __name__ == "__main__":
AVPlayer().run()
It just runs on my desktop. But I would like to have it as a mobile app on my iPhone. I could create an iOS app using swift but there is no library like pytube.
I guess kivy would be possible, too, but I do not like it.. so is there an other alternative?
I know this question may have been asked already, but I am a beginner to Kivy, so I would like for someone to explain how to put two buttons on the same screen.
The problem is I try to return the button variable, and it works. However, when I try to return two at the same time, it will give me an error.
here is my code:
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from functools import partial
class App(App):
def com1(self, instance, *args):
label1 = Label(text = "Hi")
return label1
def com2(self, instance, *args):
label = Label(text= "Bye")
def build(self):
button1 = Button(text = "Hi", size_hint = (0.25, 0.18), pos = (350, 100))
button1.bind(on_press=partial(self.com1, button1))
button2 = Button(text = "Bye", size_hint = (0.25, 0.18), pos = (350, 200))
button2.bind(on_press=partial(self.com2, button2))
return button1, button2
App().run()
The build method must return a single widget, so depending on how you want the buttons to be arranged you have several options such as BoxLayout, RelativeLayout, FloatLayout, etc. In this case for simplicity I will use a BoxLayout:
# ...
from kivy.uix.boxlayout import BoxLayout
# ...
class App(App):
# ...
def build(self):
button1 = Button(text="Hi", size_hint=(0.25, 0.18), pos=(350, 100))
button1.bind(on_press=partial(self.com1, button1))
button2 = Button(text="Bye", size_hint=(0.25, 0.18), pos=(350, 200))
button2.bind(on_press=partial(self.com2, button2))
boxlayout = BoxLayout()
boxlayout.add_widget(button1)
boxlayout.add_widget(button2)
return boxlayout
# ...
I'm trying to output text from button presses and add it to a textbox each time it's pressed as well as delete the text when the delete button is pressed - in normal python.
I've been trying to use kivy.uix.textinput, but I'm not sure on how to output the value from the buttons as well as delete it.
This is what I've done so far.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name='code_screen')
main_grid_lay = GridLayout(cols=2,cols_minimum={0:640, 1:175})
self.add_widget(main_grid_lay)
#Code ouput display
display_code = TextInput(text='Code!', readonly = True, id=output)
main_grid_lay.add_widget(display_code)
#Options Buttons
box_lay = BoxLayout(orientation='vertical')
main_grid_lay.add_widget(box_lay)
delete_button = Button(
text='Delete',
size_hint_x= None,
width=160,
id='' #unsure on how to delete
)
box_lay.add_widget(delete_button)
base_left = Button(
text='Base Left',
#on_release= b_left(),
#id='left',
)
base_right = Button(
text='Base Right',
on_release=self.degree_popup,
#on_release= b_right(),
)
#b_left = self.ids.output.text='left'
#b_left = self.ids.output.text='right'
box_lay.add_widget(base_left)
box_lay.add_widget(base_right)
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == '__main__':
MyMain().run()
It currently sends an error and is probably because of the ids. Not fully sure how ids work without using kv language. Any help is appreciated.
The id only makes sense in .kv, in python they are useless. In this case the solution is to access the objects in the methods connected to on_release but for this they must be class attributes.
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class CodeScreen(Screen):
def __init__(self):
super(CodeScreen, self).__init__(name="code_screen")
self.display_code = TextInput(text="Code!", readonly=True)
self.delete_button = Button(
text="Delete", size_hint_x=None, width=160, on_release=self.delete_clicked
)
self.base_left = Button(text="Base Left", on_release=self.left_clicked)
self.base_right = Button(text="Base Right", on_release=self.right_clicked)
main_grid_lay = GridLayout(cols=2, cols_minimum={0: 640, 1: 175})
main_grid_lay.add_widget(self.display_code)
self.add_widget(main_grid_lay)
box_lay = BoxLayout(orientation="vertical")
box_lay.add_widget(self.delete_button)
main_grid_lay.add_widget(box_lay)
box_lay.add_widget(self.base_left)
box_lay.add_widget(self.base_right)
def delete_clicked(self, instance):
self.display_code.text = ""
def left_clicked(self, instance):
self.display_code.text += "left"
def right_clicked(self, instance):
self.display_code.text += "right"
# The app class
class MyMain(App):
def build(self):
return CodeScreen()
# Runs the App
if __name__ == "__main__":
MyMain().run()
I am trying to create a menu using box layout in kivy. I wanted to use "root.top-self.height" so that it sticks the vertical layout from the top of screen but its still sticking from bottom. Also when I print(root.top) its strangely giving 100 which is not my screen resolution. Please let me know how can I place it accurately.
Furthermore I read somewhere that I need to use root=BoxLayout(), now after using this the button's are not clickable after adding that, before adding this I could use the buttons. Please do let me know how to deal with "root" ie screen or App size functionality.
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.label import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.layout import Layout
from kivy.uix.button import Button
from kivy.lang import Builder
## CREATING A CLASS WHICH HAS SCREEN CONTENT:
class firstScreen(BoxLayout):
def __init__(self,**kwargs):
super(firstScreen, self).__init__(**kwargs)
self.orientation = 'vertical'
root = BoxLayout()
self.pos = (0 ,root.top-self.height)
print(root.top)
self.myButton1 = Button(text='Home',
color = (1,0,0,1),
size_hint = (0.1,None),
## pos_hint = {'x':.8, 'y':'.7'},
## pos_hint = {'x':0, 'top':'0'},
pos = (0,0)
)
self.myButton2 = Button(text='Buy Now',
color = (1,0,0,1),
size_hint = (0.1,None))
self.myButton3 = Button(text='Blog',
color = (1,0,0,1),
size_hint = (0.1,None))
self.myButton4 = Button(text='Contant Us',
color = (1,0,0,1),
size_hint = (0.1,None))
self.add_widget(self.myButton1)
self.add_widget(self.myButton2)
self.add_widget(self.myButton3)
self.add_widget(self.myButton4)
def on_touch_down(self,touch):
print(touch)
def on_touch_move(self,touch):
print(touch)
def on_touch_up(self,touch):
print(touch)
## CREATING A CLASS WHICH RETURNS SOME SCREEN:
class myKivyApp(App):
def build(self):
return firstScreen()
## THIS CODE RUNS THE CLASS WHICH HAS SOME SCREEN
if __name__ == "__main__":
myKivyApp().run()
Eliminating the unused BoxLayout and setting the y component of size_hint to 1.0 means that each button will share equally in the vertical space available for the firstScreen.
class firstScreen(BoxLayout):
def __init__(self,**kwargs):
super(firstScreen, self).__init__(**kwargs)
self.orientation = 'vertical'
self.myButton1 = Button(text='Home',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.myButton2 = Button(text='Buy Now',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.myButton3 = Button(text='Blog',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.myButton4 = Button(text='Contant Us',
color = (1,0,0,1),
size_hint = (0.1,1.0))
self.add_widget(self.myButton1)
self.add_widget(self.myButton2)
self.add_widget(self.myButton3)
self.add_widget(self.myButton4)
By the way, the root.top will always be 100 in the __init__() method. The 100 is the default value and is not updated until the app is actually displayed.
I want to create an Accordion containing content consisting of an RstDocument and a button. The Accordion shall be scrollable as well as the content of the RstDocument when this content is larger than the given space. So I came up with the following code but after some clicks on AccordionItems all further interaction is blocking. What am I doing wrong here?
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.uix.rst import RstDocument
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.accordion import Accordion, AccordionItem
from kivy.uix.button import Button
class ShowrstApp (App):
def update_size(self, instance, *args):
instance.size = 60 * len(instance.children)
def build (self):
numitems = 10
root = BoxLayout()
accheight = numitems * 60
accitems = Accordion(id='acc_panel', orientation='vertical', pos_hint={'top': 1}, size_hint_y=None,
height=accheight, md_bg_color=(1, 1, 1, 1))
for i in xrange(numitems):
item = AccordionItem(title='This is item: %d' % i)
somecontent = BoxLayout(orientation='vertical')
somecontent.add_widget(RstDocument(text='Some nicely formatted text here'))
somecontent.add_widget(Button(text='click here', height=(42), size_hint=(1,None)))
item.add_widget(somecontent)
item.bind(children=self.update_size)
accitems.add_widget(item)
sv = ScrollView(do_scroll_x = False)
sv.add_widget(accitems)
root.add_widget(sv)
return root
Window.size = (350,650)
showrst = ShowrstApp()
showrst.run()
Below the scrolling effect works when the RstDocument Boxlayout is either horizontal of vertical, but an issue I saw was that when the BoxLayout was set to vertical, the toggle of each item was mute, you had to go one by one from the bottom-up. This was weird. You can click on each AccordionItem, where the RstDocument is not. This should be a great starting point. Noticed this effect doesn't occur when using a Label, so that could be a another option.
from kivy.app import App
from kivy.uix.scrollview import ScrollView
from kivy.uix.rst import RstDocument
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.accordion import Accordion, AccordionItem
from kivy.uix.button import Button
class ShowrstApp (App):
def update_size(self, instance, *args):
instance.height = 100 * len(instance.children) # set Accordion height to the number of accordionItem times the height accordionItem height
def build (self):
numitems = 10
root = BoxLayout()
accheight = numitems * 60
accitems = Accordion(id='acc_panel', orientation='vertical', size_hint_y=None, pos_hint={'top':1}
height=accheight, md_bg_color=(1, 1, 1, 1))
for i in xrange(numitems * 2): # *2 to show it works
item = AccordionItem(title='This is item: %d' % i)
somecontent = BoxLayout(orientation = 'horizontal') # couldn't solve an issue I notice so I used horizontal
somecontent.add_widget(RstDocument(text='Some nicely formatted text here' * 10))
somecontent.add_widget(Button(text='click here', height=(42), size_hint=(1,None)))
item.add_widget(somecontent)
accitems.bind(size=self.update_size)
accitems.add_widget(item)
sv = ScrollView(do_scroll_x = False)
sv.add_widget(accitems)
root.add_widget(sv)
return root
Window.size = (350,650)
showrst = ShowrstApp()
showrst.run()
I was having the same issue with RstDocuments in a ScrollView. The problem arises because RstDocuments have their own scrolling and 'intercept' the scroll command because it thinks you're trying to scroll inside the RstDocument. If you're fine with non-scrolling RstDocuments, you can set do_scroll_y: False for RstDocument, and scrolling will then work fine in the ScrollView regardless of mousing over an RstDocument.