Kivy not opening new window on button press? (Subprocess/Popen, Python) - python

I am trying to open a new window upon a button press with kivy.
However, when I try to open the file with the separate window in it, it simply doesn't do anything, however I do know it runs the function the button calls.
Can any help with why this is happening?
Thank you
# Banned Book Project (Name pending) for digitech subject, Y13
from multiprocessing import Manager
from tkinter import Grid
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
import selenium
from selenium import webdriver
import subprocess
from kivy.uix.screenmanager import Screen,ScreenManager
def bannedBooksMain(self):
from subprocess import Popen, PIPE
process = Popen(['python3', 'seearch_parameters.py'], stdout=PIPE, stderr=PIPE)
class mainApp(GridLayout):
def __init__(self, **kwargs):
super(mainApp, self).__init__(**kwargs)
self.cols = 2
btn1 = Button(text='Database (Search)')
btn1.bind(on_release=bannedBooksMain)
self.add_widget(btn1)
class MyApp(App):
def build(self):
return mainApp()
MyApp().run()

Related

Kivy(framework): blank window after running code

After running this code python idle gave me a blank window without any kivy widgets and python idle does not show any error.
what is the problem in this code?
screen shot of blank window
code:
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
class me(App):
def __init__(self,b,g,l,t):
super(me, self).__init__()
self.b=Button(text='start')
self.g=GridLayout(cols=4)
self.l=Label(text='label')
self.t=TextInput()
self.g.add_widget(self.b)
self.g.add_widget(self.t)
self.g.add_widget(self.l)
m=me('b','g','l','t')
m.run()
Building the App should be done in a build() method of the App, and that method should return the root widget for the App. Like this:
class me(App):
def __init__(self,b,g,l,t):
super(me, self).__init__()
self.b=Button(text='start')
self.g=GridLayout(cols=4)
self.l=Label(text='label')
self.t=TextInput()
self.g.add_widget(self.b)
self.g.add_widget(self.t)
self.g.add_widget(self.l)
def build(self):
return self.g

close webview in kivy

iam trying to close or destroy the webview and show other layout
here is my code for webview or if that won't possible i want to get the link of the current page and if current page link is equal to some link i want to exit the webview pls help me out this
from android.runnable import run_on_ui_thread as run_thread
from jnius import autoclass
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.app import runTouchApp
from kivy.clock import Clock, mainthread
#mainthread
def quit_screen():
app = App.get_running_app()
e=GridLayout()
d1=button(text="hi end")
e.add_widget(e)
app.root.switch_screen(e)
#run_thread
def key_back_handler():
webview.loadUrl("about:blank")
webview.clearHistory()
webview.clearCache(True)
webview.clearFormData()
webview.freeMemory()
Clock.schedule_once(quit_screen, 0)
#run_thread
def WebView(link,*args):
WebV = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity = autoclass('org.kivy.android.PythonActivity').mActivity
webview = WebV(activity)
settings = webview.getSettings()
settings.setJavaScriptEnabled(True)
settings.setUseWideViewPort(True)
settings.setLoadWithOverviewMode(True)
settings.setSupportZoom(True)
settings.setBuiltInZoomControls(True)
wvc = WebViewClient()
webview.setWebViewClient(wvc)
activity.setContentView(webview)
webview.loadUrl(link)
m=GridLayout(cols=1,rows=1)
d=GridLayout(cols=1,rows=1)
m.add_widget(d)
def Push(butoon):
WebView("https://www.google.com")
b=Button(text="hi")
b.bind(on_press=Push)
d.add_widget(b)
runTouchApp(m).run()
like this but its not closing on back pressed on android
Thanks for help in advance
The trick is to put the Webview in a Kivy ModalView and catch the back button/gesture from Java to exit the ModalView , for example:
https://github.com/RobertFlatt/Android-for-Python/tree/main/webview

How can I play a video with kivy v2.0.0?

I want to play a video with Kivy 2.0.0 and Python 3.6, but running this code will give me a load error because Kivy's video player won't recognize the file. How can I get Kivy's video player to recognize the file?
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.videoplayer import VideoPlayer
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.video import Video
from kivy.lang.builder import *
from kivy.app import App
import kivy
import os
kivy.require('2.0.0')
# Main page code
class MainPage(Screen):
""" This is the code for the Main Screen """
# Initialization
def __init__(self, **var_args):
# Constructor for the Main Page class
super(MainPage, self).__init__(**var_args)
# Layout
self.layout = FloatLayout()
# Video player
self.filename = '/'
self.player = VideoPlayer(source=self.filename,state='play',options={'allow_stretch': True})
self.layout.add_widget(self.player)
# Add the layout to the screen
self.add_widget(self.layout)
# Main app class
class Video_Viewer(App):
""" Main build """
# Main build
def build(self, **kwargs):
# Create the screen manager
self.manager = ScreenManager()
# Add screens to screen manager
self.manager.add_widget(MainPage(name='Main'))
# Set the screen to the main sceren
self.manager.current = 'Main'
# Return the current screen of the screen manager
return self.manager
# Run the file
if __name__ == '__main__':
Video_Viewer().run()
This is the error that happens as a result of the code:
[ERROR ] [Image ] Error loading <C:/Users/My Laptop/Downloads/video.mp4>
Try to install ffpyplayer
python -m pip install ffpyplayer

How to create button with kivy

I'm trying to use kivy for my project but I can't deal with it well..
I made a button, but I want that when I press him it will create another (new) button. Thanks a lot!
from kivy.app import App
from kivy.lang import builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
def createButton():
b = Button(pos=(0, 90), size_hint=(.2, .2), on_press=lambda a:ad())
return b
def ad():
"crate new button here!"
class NoobApp(App):
def build(self):
return createButton()
if __name__ == '__main__':
NoobApp().run()
In your ad() method add a line to create a Button and add it to the root of the app:
def ad():
print("crate new button here!")
App.get_running_app().root.add_widget(Button(text='hi'))
Note that this is adding a Button to a Button, (the root of the app is the original Button). Not a recommended approach. You should probably return some kind of Layout from your build() method instead.

Running multiple Kivy apps at same time that communicate with each other

I would like my Kivy application to be able to spawn multiple apps (i.e. new windows) on a Windows machine that can communicate with each other.
ScreenManager and Popup options will not cut it because they live in the same window..I need to be able to drag new screens across multiple monitors and therefore need multiple windows.
Kivy docs explicitly state that "Kivy supports only one window
per application: please don't try to create more than one."
A google search produces this simple approach of simple spawning a new app from within another app, like so:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
class ChildApp(App):
def build(self):
return Label(text='Child')
class MainApp(App):
def build(self):
b = Button(text='Launch Child App')
b.bind(on_press=self.launchChild)
return b
def launchChild(self, button):
ChildApp().run()
if __name__ == '__main__':
MainApp().run()
However, when I do this, it launches the app within the same window and crashes, and my terminal spits out like crazy:
Original exception was:
Error in sys.exceptionhook:
I get the same result if instead of ChildApp().run() I do multiprocessing.Process(target=ChildApp().run()).start()
Using the subprocess library gets me closer to what I want:
# filename: test2.py
from kivy.app import App
from kivy.uix.label import Label
class ChildApp(App):
def build(self):
return Label(text='Child')
if __name__ == '__main__':
ChildApp().run()
# filename: test.py
from kivy.app import App
from kivy.uix.button import Button
import subprocess
class MainApp(App):
def build(self):
b = Button(text='Launch Child App')
b.bind(on_press=self.launchChild)
return b
def launchChild(self, button):
subprocess.call('ipython test2.py', shell=True)
if __name__ == '__main__':
MainApp().run()
This spawns the child window without error, however now the main window is locked (white canvas) and if I close the child window, it just gets reopened.
They need to be able pass data between one another. Any ideas on how to do this correctly in Windows? This post seems to suggest that this is possible but I'm not sure where to start.
I tried baconwichsand's code and can confirm with Python 3.6 and Windows 10 it does not work. Apparently only top level object classes can be pickled, and since both apps inherit from the App class python throws an error. However a top level definition that simply executes the ChildApp().run() command can be pickled and works. Here is my working code.
import multiprocessing
from kivy.app import App
from kivy.uix.label import Label
class MainApp(App):
def build(self):
return Label(text='Main App Window')
class OtherApp(App):
def build(self):
return Label(text='Other App Window')
def open_parent():
MainApp().run()
def open_child():
OtherApp().run()
if __name__ == '__main__':
a = multiprocessing.Process(target=open_parent)
b = multiprocessing.Process(target=open_child)
a.start()
b.start()
And here is the code I am using, including the Builder to use a shared .kv file for both windows.
import multiprocessing
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.widget import Widget
class MainRoot(Widget):
pass
class OtherRoot(Widget):
pass
class MainApp(App):
def build(self):
Builder.load_file('B:\Python_Codes\Testing Grounds\shared.kv')
main = MainRoot()
return main
class OtherApp(App):
def build(self):
Builder.load_file('B:\Python_Codes\Testing Grounds\shared.kv')
other = OtherRoot()
return other
def open_parent():
MainApp().run()
def open_child():
OtherApp().run()
if __name__ == '__main__':
a = multiprocessing.Process(target=open_parent)
b = multiprocessing.Process(target=open_child)
a.start()
b.start()
I'm not sure why it doesn't work with multiprocessing (I've never tried it), but it should at least work with subprocess. The reason your main window is locked is because subprocess.call blocks the thread that calls it while it waits for the subprocess to finish and return a result.
You want to use subprocess.Popen instead, which does not block.
bj0's answer regarding subprocess was correct.
Even better, I figured out how to do this via multiprocessing, which allows better communication and passing of information between apps. It wasn't working before because I did multiprocessing.Process(target=ChildApp().run()).start() when it should be multiprocessing.Process(target=ChildApp().run).start(). The following works
# filename: test.py
from kivy.app import App
from kivy.uix.button import Button
from test2 import ChildApp
import multiprocessing
class MainApp(App):
def build(self):
b = Button(text='Launch Child App')
b.bind(on_press=self.launchChild)
return b
def launchChild(self, button):
app = ChildApp()
p = multiprocessing.Process(target=app.run)
p.start()
if __name__ == '__main__':
MainApp().run()
# filename: test2.py
from kivy.app import App
from kivy.uix.label import Label
class ChildApp(App):
def build(self):
return Label(text='Child')
if __name__ == '__main__':
ChildApp().run()
Working on Ubuntu Python 3.10
Calling a subprocess in a multiprocess.
main.py
import multiprocessing
import subprocess
import shlex
#my kivy code..
def sub_window():
subprocess.call(shlex.split('python3 test.py'))
if __name__ == '__main__':
b = multiprocessing.Process(target=sub_window)
b.start()
MyApp().run()
test.py
#another kivy app script..
OtherApp().run()

Categories

Resources