How to include image in Kivy application with onefile mode pyinstaller? - python

I have been trying for the past 8 hours to get my image to show up in my .exe built using pyinstaller. My program is written in kivy. Everything else works, but the image doesn't show up. I have read [this][2] question. That has not worked for me. Or I just followed the answer wrong. If someone can please explain to me how to do it step by step, I would be very grateful. Also, if there is another answer, please consider telling me that as well.
I will include my main.py file:
#!/usr/bin/env python3
import os
import sys
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 kivy.uix.slider import Slider
class SayHello(App):
def build(self):
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}
self.window.add_widget(Image(source = "say.png"))
self.greeting = Label(
text = "Hello",
font_size = 40,
color = "#00FFCE"
)
self.window.add_widget(self.greeting)
self.slid = Slider(min = 0, max = 300, orientation = "horizontal")
self.window.add_widget(self.slid)
self.user = TextInput(
multiline = False,
padding_y = (20,20),
size_hint = (1, 0.4)
)
self.window.add_widget(self.user)
self.button = Button(
text = "Click me to greet you!",
size_hint = (1,0.5),
bold = True,
background_color = "00FFCE",
)
self.button.bind(on_press = self.callback)
self.window.add_widget(self.button)
return self.window
def slided(self, event):
self.slid
def callback(self, event):
self.greeting.text = "Hello " + self.user.text + "!"
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
base_path = getattr(
sys,
'_MEIPASS',
os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
path = resource_path("say.png")
if __name__ == "__main__":
SayHello().run()
[1]: https://stackoverflow.com/questions/31836104/pyinstaller-and-onefile-how-to-include-an-image-in-the-exe-file
[2]: https://stackoverflow.com/questions/48467917/include-kv-json-files-while-packaing-kivy-with-pyinstaller-onefile
Thanks in advance!

The problem is with your attempt to fix the path:
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
base_path = getattr(
sys,
'_MEIPASS',
os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base_path, relative_path)
path = resource_path("say.png")
just replace that code with:
import kivy.resources
if getattr(sys, 'frozen', False):
# this is a Pyinstaller bundle
kivy.resources.resource_add_path(sys._MEIPASS)

Related

How to display all returned photos on a kivy app using python

I am making a project involving looking up images. I decided to use kivy, creating a system where you can input a name of a folder (located in a specific directory) into a search bar, and it will return all images inside said folder tagged '.jpg'. I am stuck with updating the window to display these images, and I can't find anything online which helps.
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.screenmanager import Screen
from kivymd.app import MDApp
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.core.window import Window
import glob
import os
os.chdir(r'directory/of/imagefolders')
class functions:
def lookup(name):
root = f'imagefolder'
for root, subdirs, files in os.walk(f'imagefolder'):
for d in subdirs:
if d == name:
print(d)
path = f'imagefolder/'+d
print(path)
return path
def load_images(f):
facefile = []
for images in glob.glob(f + '\*.jpg'):
facefile.append(images)
print(facefile)
return facefile
class MainApp(MDApp):
def build(self):
Window.clearcolor = (1,1,1,1)
layout = GridLayout(cols=2, row_force_default=True, row_default_height=40,
spacing=10, padding=20)
self.val = TextInput(text="Enter name")
submit = Button(text='Submit', on_press=self.submit)
layout.add_widget(self.val)
layout.add_widget(submit)
return layout
def submit(self,obj):
print(self.val.text)
layout2 = GridLayout(cols=2, row_force_default=True, row_default_height=40,
spacing=10, padding=20)
name = self.val.text
f = functions.lookup(name)
print(f)
facefile = functions.load_images(f)
x = len(facefile)
print(x)
for i in range(0, x):
print(facefile[i])
self.img = Image(source=facefile[i])
self.img.size_hint_x = 1
self.img.size_hint_y = 1
self.img.pos = (200,100)
self.img.opacity = 1
layout2.add_widget(self.img)
return layout2
MainApp().run()
This is what I tried, but the window doesn't update. All images are returned (demonstrated by print(facefile[i])), but nothing happens with them. Any help would be massively appreciated
Your submit() method is creating Image widgets and adding them to a newly created layout2, You are returning that new layout2 from that method, but that does not add it to your GUI. Try replacing:
layout2.add_widget(self.img)
with:
self.root.add_widget(self.img)

How to run python / pytube code on iOS device?

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?

How to add a background video in Kivy

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

How to use MDNavigationRail + MDNavigationRailItem without KV language

How can I create MDNavigationRail without KV language? I tried this code but I get a lot of errors.
class MyApp(MDApp):
def build(self):
boxlayout1 = MDBoxLayout(orientation = "vertical")
toolbar = MDToolbar(title = "Hello")
boxlayout1.add_widget(toolbar)
boxlayout2 = MDBoxLayout()
boxlayout1.add_widget(boxlayout2)
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
navigationrail = MDNavigationRail()
navigationrail.add_widget(MDNavigationRailItem(icon="access-point"))
boxlayout2.add_widget(navigationrail)
return boxlayout1
root = MyApp()
root.run()
You have to pass your object navigationrail as an argument of MDNavigationRailItem.
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.toolbar import MDToolbar
from kivy.utils import get_color_from_hex
class MyApp(MDApp):
def build(self):
boxlayout1 = MDBoxLayout(orientation = "vertical")
toolbar = MDToolbar(title = "Hello")
boxlayout1.add_widget(toolbar)
boxlayout2 = MDBoxLayout()
boxlayout1.add_widget(boxlayout2)
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
navigationrail = MDNavigationRail(
md_bg_color = get_color_from_hex("#344954"),
# color_normal = get_color_from_hex("#718089"), #crash the app when clicking on an item, don't understand why...
color_active = get_color_from_hex("#f3ab44"),
visible = "Persistent")
for i in range(3):
item = MDNavigationRailItem(navigation_rail = navigationrail, text="item%d" %(i+1))
navigationrail.add_widget(item)
boxlayout2.add_widget(navigationrail)
return boxlayout1
root = MyApp()
root.run()

Can buildozer made android apps use glob and os modules?

So at the moment in try to figure out why is my small player i wrote in kivy crashes on start. It says build successful and all modules seem to work separately in other tests (except for glob) but this one is pure python as far as i know.
here's my code
import glob
import kivy
from kivy.core.audio import SoundLoader
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.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Rectangle
from kivy.graphics import Color
from kivy.uix.widget import Widget
import random
import os
from android.permissions import request_permissions, Permission
request_permissions([Permission.READ_EXTERNAL_STORAGE])
class PageI(GridLayout):
def __init__(self,**kwargs):
super().__init__( **kwargs)
self.cols = 3
self.state = False
self.music = glob.glob('/Phone/reMusic/*.mp3')#glob.glob('music\\*.mp3')
self.currname = self.music[0]
self.lasttime = 0
self.currsound = SoundLoader.load(self.currname)
fillclr = (round(random.random(),4), round(random.random(),4), round(random.random(),4), 1)
SR = Button(text='forward')
SR.bind(on_press=self.switchoR)
self.add_widget(SR)
placeholder = Label()
self.add_widget(placeholder)
SL = Button(text='backward')
SL.bind(on_press=self.switchoL)
self.add_widget(SL)
placeholder = Label()
self.add_widget(placeholder)
self.PP = Button(on_press = self.switchostate)
self.add_widget(self.PP)
placeholder = Label()
self.add_widget(placeholder)
placeholder = Label()
self.add_widget(placeholder)
self.showcase = Label(text=self.currname)
self.add_widget(self.showcase)
def PPcontrol(self):
if not self.currsound.state == 'play':
self.currsound.play()
self.currsound.seek(self.lasttime)
else:
self.lasttime = int(self.currsound.get_pos())
self.currsound.stop()
def switchostate(self,instance):
self.PPcontrol()
def showsitch(self):
self.showcase.text = self.currname
def switchoR(self,instance):
instance.background_color = (round(random.random(),4), round(random.random(),4), round(random.random(),4), 1)
ind = self.music.index(self.currname)
if ind+1 > len(self.music)-1:
self.currname = self.music[ind - len(self.music) + 1]
else:
self.currname = self.music[ind + 1]
self.lasttime = 0
self.currsound.stop()
self.currsound = SoundLoader.load(self.currname)
self.currsound.play()
self.showsitch()
def switchoL(self,instance):
instance.background_color = (round(random.random(),4), round(random.random(),4), round(random.random(),4), 1)
ind = self.music.index(self.currname)
if ind - 1 < 0:
self.currname = self.music[len(self.music) - 2]
else:
self.currname = self.music[ind - 1]
self.lasttime = 0
self.currsound.stop()
self.currsound = SoundLoader.load(self.currname)
self.currsound.play()
self.showsitch()
class Applet(App):
def build(self):
self.dircheck()
self.p = PageI()
return self.p
def dircheck(self):
try:
if not os.path.exists(os.path.join(os.getcwd(),'\\music')):
os.mkdir(os.path.join(os.getcwd(),'\\music'))
except: None
if __name__ == '__main__':
apper = Applet()
apper.run()
ik its quite messy but as you can see i tried both creating directories and accessing premade one.
and well, im not sure why it dies, i made sure it had all perms in spec file as well.

Categories

Resources