How to change browser URL dynamically in kivy - python

My app works perfectly for below code. ie open google.com once button is clicked.
#!/usr/bin/kivy
import kivy
kivy.require('1.7.2')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
import webbrowser
Builder.load_string('''
<MenuScreen>:
GridLayout:
padding: 5
spacing: 5
cols: 1
padding: root.width*0.1
Button:
background_normal: ''
background_color:(0.862, 0.078, 0.235, 0.9)
text: 'PLAY'
font_size: '20sp'
on_press: root.val1()
''')
class MenuScreen(Screen):
def val1(self):
print "i am executed"
webbrowser.open("http://google.com/")
sm = ScreenManager()
menu = MenuScreen(name='menu')
sm.add_widget(menu)
class MainApp(App):
def build(self):
return sm
if __name__ == '__main__':
MainApp().run()
Now, suppose someone is using my app and after few days i want to change url from google.com to yahoo.com, what approach should i follow. I am completely clueless about it. Should i get a domain name and change it redirection like abc.com/test.html to redirect to google.com and then change the redirection to yahoo.com later or some other approach?

I can give you two idea for this:
keep a array of urls in your code and choose one randomly to use.
If you maintain a server, then you can use an static url from where your program will receive data which are nothing but url or url list and use it.

Related

How to repair an error "Pyperclip could not find a copy/paste mechanism in your device" in Python Kivy?

I am using Pyperclip library in Python in Kivy UI, and I want to be able to copy a text by pressing a button, but it gives me this error message:
pyperclip.PyperclipException:
Pyperclip could not find a copy/paste mechanism for your system.
For more information, please visit https://pyperclip.readthedocs.io/en/latest/index.html#not-implemented-error
My .py file is:
import kivy
import pyperclip
kivy.require("1.10.1")
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.app import App
class Screen1(Screen):
def copy_on_press(self):
pyperclip.copy("text_which_should_be_copied")
class Copy(App):
def build(self):
sm = ScreenManager()
sm.add_widget(Screen1(name = "scr1"))
return sm
app = Copy()
app.run()
My .kv file is:
<Screen1>:
id: scr1
orientation: "vertical"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: "Background.png"
Button:
text: "Copy"
on_press: scr1.copy_on_press()
Thanks for any answer.
I haven't found any informations which could solve my error.
I found similar errors, but their solutions didn't work for me.
Thanks to the comments, I've found it. The .py:
import kivy
from kivy.core.clipboard import Clipboard
kivy.require("1.10.1")
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.app import App
class Screen1(Screen):
def copy_on_press(self):
Clipboard.copy("text_which_should_be_copied")
class Copy(App):
def build(self):
sm = ScreenManager()
sm.add_widget(Screen1(name = "scr1"))
return sm
app = Copy()
app.run()
The .kv remains the same.

kivy._event.EventDispatcher.__init__ is raising the error "TypeError: object.__init__() takes exactly one argument (the instance to initialize)"

I'm relatively new to programming, little over 8 months or so, but I am learning kivy and python3 and I am attempting to create a password managing application and I would like for it to open a new screen when a button is pressed. but I am getting a Type Error.
import kivy
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.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import ScreenManager, Screen
class LoginScreen(Widget):
pass
class PasswordScreen(Widget):
pass
class PasswordApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(LoginScreen(name='login'))
sm.add_widget(PasswordScreen(name='passwords'))
return sm
if __name__ == '__main__':
PasswordApp().run()
heres the .kv code
<LoginScreen>:
GridLayout:
Button:
text: 'Goto passwords'
on_press: root.manager.current = 'passwords'
Button:
text: 'Quit'
<PasswordScreen>:
GridLayout:
Button:
text: 'My settings button'
Button:
text: 'logout'
on_press: root.manager.current = 'login'
Your LoginScreen and PasswordScreen extend Widget, and the Widget __init__() does not support a name property. Both those classes should extend Screen instead of Widget.

How to make kivy app from different py files

I am trying to make an app out of different .py files. But I don't know how to add them together, I have one main file, and one login file with plans to add a lot more, but with these I'm experimenting right now. They are pretty basic for now until I figure out this "bonding" between them and then I will start adding some more complex stuff. I tried couple of things and they didn't work, but I left them in code for you to see (I tried to make the app to start with MainWindow, and on press of the first button it goes to login page*). Here's the code and please help me.
*Right now when I press the button it gives me this error: OSError: exception: access violation writing 0x0000000080006010
this is main.py:
from kivy.lang import Builder
from kivy.app import App
import login
from kivy.uix.screenmanager import Screen
kv = Builder.load_string('''
<MainWindow>:
GridLayout:
cols:1
GridLayout:
rows:5
Button:
text:"NOVA ROBA"
on_release:
root.call_login()
Button:
text:"KUPCI"
Button:
text:"PRODATO"
Button:
text: "AGRONOMI"
Button:
text: "STANJE U MAGACINU"
''')
class MainWindow(Screen):
def call_login(self):
login.app().run()
pass
class main_app(App):
def build(self):
return MainWindow()
if __name__ == '__main__':
main_app().run()
this is login.py:
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.app import App
class Login(Screen, App):
def build(self):
return
pass
kv = Builder.load_string('''
<Login>:
name:"login"
GridLayout:
rows:2
GridLayout:
cols:2
Label:
text:"Password: "
TextInput:
id:passwd
multiline: False
Button:
text: "Submit"
on_release:
passwd.text = ""
''')
class app(App):
def build(self):
return Login()
if __name__ == "__main__":
app().run()
You are creating 2 apps, which is not needed. Instead of inheriting from both Screen and App in the Loginscreen, inherit only from Screen. Then create a ScreenManager in your main.py's build method and then add the imported loginscreen as a widget, to switch to the new screen, use self.manager.current = "login" in the call_login method of MainWindow
class app(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainWindow())
sm.add_widget(Login())
return sm

Kivy's ScreenManager and Popups don't want to work together

as stated in the title - I'm stuck. I've been playing with the code around and everything works as long as I keep ScreenManager and Popup separate. Once combined - they refuse to cooperate. Anyway, here is the simple app that shows the problem I'm having.
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import Screen, ScreenManager
class First(GridLayout,Screen):
def show_popup(self):
Popp().open()
pass
class Second(Screen):
pass
class Popp(Popup):
pass
class ScreenManagement(ScreenManager):
pass
app = Builder.load_file("main.kv")
class MainApp(App):
def build(self):
return app
if __name__ == "__main__":
MainApp().run()
And main.kv file
ScreenManagement:
First:
Second:
<First>:
name:"First"
rows: 2
Button:
text: "FirstButton"
on_release: app.root.current = "Second"
Button:
text: "Show popup"
on_release: root.show_popup()
<Second>:
name:"Second"
Button:
text: "BUTTON"
on_release: app.root.current = "First"
<Popp>:
title: "testing"
text: "Hello world"
size_hint: None,None
size: 400,400
auto_dismiss: False
Button:
text: "Okay"
on_press: root.dismiss()
App starts, first and second screen are working but when trying to get popup up I end up with:
kivy.uix.popup.PopupException: Popup can have only one widget as content
Somehow Screen is seen as a widget inside of Popp? Or am I terribly misinterpreting kivy docs?
It's a bug with loading kv file, it should throw an exception in this case.
What you are doing in the code is loading the kv file twice, what causes some weird behavior. Just delete the Builder.load_file(..) and it will work. The file is going to be loaded automatically.
Also, never do double subclassing of widgets like class First(GridLayout, Screen) as it might lead to some problems. Instead, create a grid layout inside the screen.
Put the elements in the Popup inside a layout, for example: Boxlayout.
Here's what I mean:
<Popp>:
title: "testing"
BoxLayout:
orientation: 'vertical'
size_hint: None,None
size: 400,400
Label:
text: "Hello world"
Button:
text: "Okay"
on_press: root.dismiss()
I have same problem with using kivy Builder.load_file and Popup, they dont work together.
the solution is simple, build popup in python code side. this is a loading popup example:
python:
from kivy.app import App
from kivy.uix.popup import Popup
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
import time, threading
buildKV = Builder.load_file("example.kv")
class ExampleApp(App):
def show_popup(self):
content = BoxLayout(orientation= "vertical")
image=Image(source= 'files/loading.gif', anim_delay= 0)
label=Label(text= 'Model is Running.\nBe Patient Please.')
content.add_widget(image)
content.add_widget(label)
self.popup = Popup(title='Model is Running.',
size_hint=(.250, .785),
content=content, auto_dismiss=False)
self.popup.open()
def process_button_click(self):
# Open the pop up
self.show_popup()
# Call some method that may take a while to run.
# I'm using a thread to simulate this
mythread = threading.Thread(target=self.something_that_takes_5_seconds_to_run)
mythread.start()
def something_that_takes_5_seconds_to_run(self):
thistime = time.time()
while thistime + 10 > time.time(): # 5 seconds
time.sleep(1)
# Once the long running task is done, close the pop up.
self.pop_up.dismiss()
if __name__ == "__main__":
ExampleApp().run()
kivy:
BoxLayout:
Button:
height: 40
width: 100
size_hint: (None, None)
text: 'Click Me'
on_press: app.process_button_click()

How to pass arguments to build() in kivy?

I have written a code with GridLayout which need to be added with buttons in Python file. So, the add_widget() mainpulation should be done in build(). I am getting errors and couldn't get it.Someone Please help me.
In short, instead of add_btn(), I need it in build() of MineApp class.
Thanks in advance.`
main.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
class MainLayout(BoxLayout):
def build(self):
pass
def add_btn(self,id):
for i in range(100):
id.add_widget(Button())
class MineApp(App):
def build(self):
return MainLayout()
if __name__ == '__main__':
MineApp().run()
mine.kv file:
<MainLayout>:
orientation:'vertical'
BoxLayout:
orientation:'horizontal'
height: '30px'
size_hint_y:None
TextInput:
id: tinput
text:'10'
Button:
text:'start'
on_press:root.add_btn(grid)
Label:
id:mylabel
text:'0'
GridLayout:
id: grid
cols:10
rows:10
It took some time but think I get what you're trying to say! You can get the same effect by passing the id parameter of Grid in the .py file like so...
class MainLayout(BoxLayout):
def build(self):
for i in range(100):
self.ids.grid.add_widget(Button())
Then, you can just take your start button and...
Button:
text:'start'
on_press:root.build()
This works because "self" in .py refers to the class while in the .kv a similar wording would be 'root' (while 'self' in .kv refers to the widget!) Is this what you kind of had in mind? Let me know! I tried it out myself and had no problem running it through :)
Also, it wasn't put explicitly here that to test the code you'd need to import Builder via:
from kivy.lang import Builder
and do...
Builder.load_file("mine.kv")
as your .py and .kv don't share the same name (which you'd still need to add a "#File name: main.py" to the .kv if they did match names! Other than that, it looks good!

Categories