I need to embed a webview inside my kivy app or with some other python app framework that supports this for both android and IOS. I am looking to also save cookies for log in so users do not have to log in more than once. Is this possible or should I look for another way to accomplish this? Thanks for any responses in advance!
Unfortunately there is no "universal" method to do this. It should however still be possible. There unfortunately isn't a kivy "native" method either.
Android:
For android you can use webview-android:
from kivy.uix.widget import Widget
from kivymd.app import MDApp
from webview import WebView
from kivy.lang.builder import Builder
from kivymd.uix.button import MDFlatButton
from kivymd.uix.screen import MDScreen
Builder.load_string("""
<MyWebView>
MDFlatButton:
text: "Push"
pos_hint: {"center_x": .5, "center_y": .4}
on_press: root.Push()
""")
class MyWebView(MDScreen):
def Push(self):
WebView("https://www.google.com")
class MyWebApp(MDApp):
def build(self):
return MyWebView()
if __name__ == '__main__':
MyWebApp().run()
Furthermore, you can use jnius to access the java classes, that would do this normally:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.utils import platform
from kivy.uix.widget import Widget
from kivy.clock import Clock
from jnius import autoclass
from android.runnable import run_on_ui_thread
WebView = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity = autoclass('org.kivy.android.PythonActivity').mActivity
class Wv(Widget):
def __init__(self, **kwargs):
super(Wv, self).__init__(**kwargs)
Clock.schedule_once(self.create_webview, 0)
#run_on_ui_thread
def create_webview(self, *args):
webview = WebView(activity)
webview.getSettings().setJavaScriptEnabled(True)
wvc = WebViewClient();
webview.setWebViewClient(wvc);
activity.setContentView(webview)
webview.loadUrl('http://www.google.com')
class ServiceApp(App):
def build(self):
return Wv()
if __name__ == '__main__':
ServiceApp().run()
iOS:
Unfortunately I don't own an iOS device, so I can not test any of this.
The kivy-ios module seems to contain methods for accomplishing this:
import ios
url = "http://www.google.com"
ios.IOSWebView().open(url, width, height)
Another solution would be to use pyobjus to access the Objective-C classes, that would normally implement the webview on iOS. I don't want to paste untested code, so I suggest you check out Michael Galaxy and Julez' answers on the bottom of this google group.
Related
I am trying to open Google Earth within my Python Kivy app. I have tried:
webbrowser.open ("https://www.google.com/earth/")
However, this opens Google Earth in a separate tab. I want it to open the link within the app rather than it redirecting elsewhere. Researching this I came across this code:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.utils import platform
from kivy.uix.widget import Widget
from kivy.clock import Clock
from jnius import autoclass
from android.runnable import run_on_ui_thread
WebView = autoclass('android.webkit.WebView')
WebViewClient = autoclass('android.webkit.WebViewClient')
activity =
autoclass('org.kivy.android.PythonActivity').mActivity
class Wv(Widget):
def __init__(self, **kwargs):
super(Wv, self).__init__(**kwargs)
Clock.schedule_once(self.create_webview, 0)
#run_on_ui_thread
def create_webview(self, *args):
webview = WebView(activity)
webview.getSettings().setJavaScriptEnabled(True)
wvc = WebViewClient();
webview.setWebViewClient(wvc);
activity.setContentView(webview)
webview.loadUrl('http://www.google.com')
class ServiceApp(App):
def build(self):
return Wv()
if __name__ == '__main__':
ServiceApp().run()
https://github.com/kivy/kivy/wiki/Android-native-embedded-browser
However, this will not let me make this import statement:
from android.runnable import run_on_ui_thread
from android.runnable import run_on_ui_thread
ModuleNotFoundError: No module named 'android'
I am learning Kivy and I'm not used to .kv, so I am trying to learn the "hard way" first.
Problem: there is not a lot of documentation for interaction with Kivy except .kv.
I'm stuck with the import of the NavigationLayout, I tried to find it on the official Github, but I failed !
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.toolbar import MDToolbar
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.app import MDApp
#from kivy import road.to.navigationlayout import NavigationLayout
class App(MDApp):
def build(self):
screen_manager = ScreenManager()
main_screen = Screen()
main_box = BoxLayout()
main_toolbar = MDToolbar()
main_toolbar.title = "Hello there !"
#navigation_layout = NavigationLayout()
screen_manager.add_widget(main_screen)
main_screen.add_widget(main_box)
main_box.add_widget(main_toolbar)
return screen_manager
App().run()
PS: If you have tips to find out where objects are situated in new libraries, I would be happy to heard them!
It was in the MDKivy library. (I found it with this other stack overflow post)
from kivymd.uix.navigationdrawer import NavigationLayout
Kv language has a way to import names from other files using the following syntax:
#:import name x.y.z
# The same as `from x.y import z as name` in Python code
But it doesn't mention how to import the values from the same module where that kv language is used.
Let's say I have the following code:
from kivy.app import App
from kivy.lang import Builder
from kivy.atlas import Atlas
from kivy.uix.button import Button
theme = Atlas('path/to/atlas')
Builder.load_string('''
<MyWidget>:
background_normal: theme['widget_bg']
''')
class MyWidget(Button):
pass
class TestApp(App):
def build(self):
return MyWidget()
TestApp().run()
I'd like to import the theme Atlas object into the kv code to set the proper background. How could this be done?
You can refer to your current module as __main__
#:import theme __main__.theme
<MyWidget>:
background_normal: theme['widget_bg']
I created a simple text-to-speech app with Kivy, using the FloatLayout option but am having trouble changing the color of the GUI without actually creating a .kv file (which I do not wish to do). The code of my app is here:
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
import requests
from threading import Thread
import os
class ButtonApp(App):
def talk(self):
self.info.text = self.text.text
command = "say %s" % (self.text.text)
os.system(command)
def say(self,instance):
t = Thread(target=self.talk)
t.start()
def build(self):
self.b = FloatLayout()
self.info = Label(text="Hello!", pos=(20,400) ,size_hint=(1,0.5), font_size="40sp")
self.text = TextInput(text='Hello!', pos=(20,200), size_hint=(1,0.5))
self.submit = Button(on_press=self.say,text='Submit',pos=(20,100), size_hint=(1,0.5))
self.b.add_widget(self.info)
self.b.add_widget(self.text)
self.b.add_widget(self.submit)
self.b.bind()
return self.b
if __name__ == "__main__":
ButtonApp().run()
Like I mentioned beforehand, all the suggestions I found doing prior research involved either Canvas (which I am not using), or creating a .kv file. Is there a pure python-kivy method of changing the color of a GUI?
You can do anything in pure python, though the reason you see so many kv examples is because it's easier and more concise due to being a more domain specific language, so I don't recommend avoiding it.
What kind of change do you actually want to make? For instance, you can change the background image of the Button with the background_normal or background_down properties (which take a filepath to an image), or tint its colour by setting its background_color to e.g. (1, 0, 0, 1) for red.
I don't have any idea to find a solution of my problem.
I have make an application with Carousel Widget. In this Carousel I have 4 slides.
welcomeSlide -> DVDSlide -> DVDPretSlide --> CategorySlide
I have make a class for each slides.
I use a ListAdpter to display the data extracted from an Sqlite3 Database.
My pblem is about the refresh of the list, when I modify a DVD (add name to pret) in the DVDSlide, when I slide to the DVDPret, the DVD do not appears because the List is not refresh.
Like the doccumentation for the carousel I don't find the event when slide change. It will be the best if an event exist to get the current slide index.
Have you got any Idea ?
Thanks,
You can observe index property:
from kivy.uix.carousel import Carousel
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
Label:
text: str(id(root))
<Carousel>
on_index: print("slide #{}".format(args[1]))
''')
class Page(BoxLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()
Or you can observe current_slide property:
from kivy.uix.carousel import Carousel
from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
label_id: label_id
Label:
id: label_id
text: str(id(root))
<Carousel>
on_current_slide: print(args[1].label_id.text)
''')
class Page(BoxLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in range(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()
If you want a pure python solution rather than a Kivy Language solution you can create your own carousel that inherits from the Kivy carousel as follows.
import kivy
from kivy.uix.carousel import Carousel
class MyCarousel(Carousel):
# This class is a carousel that runs script
# when a slide gets focus (except first load).
def on_index(self, *args):
print('the slide is', self.index)
# YOUR CODE GOES HERE
Carousel.on_index(self, *args)