Kivy Sending text from spinner to another function - python

I've been trying to figure out how to get the value selected in a spinner into another function. I basically need a user to select some option and then press "save" prompting another function to write the data to a file (right now I just have it setup to print). When I run the form.finkle function it prints kivy.uix.button.Button object at 0x02C149D0
I'm sure its an easy fix, but I've been stuck on it for days.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.textinput import TextInput
from kivy.uix.spinner import Spinner
condspin = Spinner(text='Condition',values=('Good','Fair','Poor','Missing'))
typespin = Spinner(text='Type', values=('Metal','Wood','Pin','Missing'))
commlabel = Label(text='Comment')
commtext = TextInput(text="")
class Goose(App):
def build(self):
layout = GridLayout(cols=2,rows=6,padding=10,spacing=10)
layout.add_widget(Button(text='Hunter Parking'))
layout.add_widget(Button(text='Boat Launch'))
layout.add_widget(Button(text='ETRAP'))
layout.add_widget(Button(text='Monument',on_press=form.monform))
layout.add_widget(Button(text='Camp Site'))
layout.add_widget(Button(text='Sign'))
layout.add_widget(Button(text='Building'))
layout.add_widget(Button(text='Trail Head'))
layout.add_widget(Button(text='Dam'))
layout.add_widget(Button(text='Day Use'))
layout.add_widget(Button(text='Pavilion'))
layout.add_widget(Button(text='Misc Point'))
return layout
class form():
def finkle(condtest):
print condtest
def monform(self):
monbox = GridLayout(cols=2,rows=8,padding=20,spacing=20)
monpopup = Popup(title="Monument",content=monbox)
closebut = Button(text="Close")
closebut.bind(on_press=monpopup.dismiss)
savebut = Button(text="Save Point")
savebut.bind(on_press=form.finkle)
condtest = condspin.text
monbox.add_widget(condspin)
monbox.add_widget(typespin)
monbox.add_widget(commlabel)
monbox.add_widget(commtext)
monbox.add_widget(savebut)
monbox.add_widget(closebut)
monpopup.open()
Goose().run()

Since you have made the spinner global, you could just do print(condspin.text). More generally, you could pass the spinner as an argument, e.g.
from functools import partial
savebut.bind(on_press=partial(self.finkle, condspin))
and redefine the finkle method as
def finkle(self, spinner, button)
Note that I changed form.finkle to self.finkle and added both the self and spinner arguments. It's bad practice to call the method via the class like that.
There are some significant other bad style things in your code, and I would recommend some other changes. Mostly I would make use of kv language for basically everything, it will make the widget trees much clearer, more robust to changes later, and also make this binding very simple (you'd be able to refer to the spinner text via a kv id). Also, the form class is semi-unnecessary, you could replace it with a FormWidget that is the GridLayout you make in the monform function, adding all its children and behaviour in kv.

Related

os.system() don't let updating image source in kivy python

I am trying to update the image source on a changeImageSource function it changes the source instantly but when I use time.sleep() method in that function, function executes but doesn't update the source of the image. updates after time.sleep() call completed.
from kivy.app import App
from kivy.uix.image import AsyncImage
from kivy.uix.button import Button
from kivy.uix.widget import Widget
import time
# creating the App class
class MyApp(App):
def build(self):
parent = Widget()
#creating and adding image to widget
self.img = AsyncImage(
source='http://kivy.org/logos/kivy-logo-black-64.png')
self.img.pos = (400,400)
#creating btn and adding press handler
self.change_img_btn = Button(text="Change Image ")
self.change_img_btn.bind(on_press = self.changeImageSource)
#adding widget to Widget instance
parent.add_widget(self.img)
parent.add_widget(self.change_img_btn)
return parent;
def changeImageSource(self,*args):
self.img.source = "https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a"
time.sleep(4)
# run the App
MyApp().run()
One: The "return parent;" should be "return parent"
Two: Why do you need time.sleep()?
You can also try flipping line 29 and 30.

First character not getting printed in kivy

I am learning to code in Kivy using python
But my Label is not showing the first character
Can anyone help me
The kv File is as follows:
<MyGrid>
Label:
text: "Techy Matanhelia"
The python file is as Follows:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.uix.widget import Widget
class MyGrid(Widget):
pass
class MyApp(App):
def build(self):
return MyGrid()
if __name__ == '__main__':
MyApp().run()
Also Can anyone tell me how to edit kivy files on pycharm2020.2.2
That is because your MyGrid class extends Widget. A simple Widget has no capability to handle positioning or sizing of its children, so the Label gets assigned the default size of (100,100) and the default position of (0,0). which results in the first letter of the Label being off the screen. Try making MyGrid extend a Layout, perhaps like this:
class MyGrid(FloatLayout):
pass

Kivy TabbedPanel switch_to work inconsistently

I am writing a code which starts the frontend, runs the backend and then loads the frontend. The frontend consists of TabbedPanel, and the currently displayed tab may be change by backend.
Here's the MRE:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelHeader
def button(instance):
instance.parent.parent.switch_to(instance.parent.parent.tab_2) # accessing TabbedPanel without messing with sending
# a variable
def backend(frontend):
# this class represents main backend function. In the result of its execution there might be a need to switch to
# another tab
frontend.switch_to(frontend.tab_2)
class MyTabbedPanel(TabbedPanel):
def __init__(self, **kwargs):
super().__init__()
self.tab_1 = TabbedPanelHeader()
self.tab_2 = TabbedPanelHeader()
self.tab_1.content = Button(text='Tab 1')
self.tab_1.content.bind(on_release=button)
self.tab_2.content = Label(text='Tab 2')
self.add_widget(self.tab_1)
self.add_widget(self.tab_2)
class Application(App):
def build(self):
frontend = MyTabbedPanel()
backend(frontend)
return frontend
Application().run()
The button, which I have added to compare, to switch from tab 1 to tab 2 works just fine, however, the auto swith when starting the app does not work.
What is the problem? Thank you in advance.
At the time that you're calling backend, there is no root widget returned by the build method, let alone a tab to switch to.
One way to solve this, is to schedule the call to the backend for after the build ends, using the Clock module.
def build(self):
frontend = MyTabbedPanel()
# backend(frontend)
from functools import partial
from kivy.clock import Clock
Clock.schedule_once(partial(backend, frontend))
return frontend
You also have to add an args argument to the backend method, because Clock sends a dt value:
def backend(frontend, *args):

How to Bind on_press to GridLayout in kivy python

i was trying to bind on_press method to gridLayout in kv language but i got this error AttributeError: pressed. I did some research even in the kivy doc but no help .So if any one has a solution to this problem please you may be a good resource
here is my testApp.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class screendb(BoxLayout):
def mycall_back(self):
print('hello')
class testApp(App):
def build(self):
return screendb()
if __name__=='__main__':
testApp().run()
here is my testApp.kv
<Screendb#BoxLayout>:
GridLayout:
on_pressed:root.Mycall_back()
In your py file:
# Behaviors let you add behavior from one widget to another widget
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.gridlayout import GridLayout
# We create a new widget that is a GridLayout with access to Button Behaviors
# Like Button's 'on_press' method
class ButtonGrid(ButtonBehavior, GridLayout):
pass
class screendb(BoxLayout):
def mycall_back(self):
print('hello')
class testApp(App):
def build(self):
return screendb()
In your kv file:
# We create a Root Widget for the ButtonGrid
<ButtonGrid>:
<Screendb#BoxLayout>:
# We add an instance of the ButtonGrid class to our main layout
ButtonGrid:
# We can now use on_press because it is a part of the ButtonBehavior class, that makes up your ButtonGrid class.
on_press:root.mycall_back()
Note: There were a few minor mistakes in your post as well. For example, there is no method 'on_pressed', only 'on_press', you also wrote your callback as 'mycall_back' in your py file while writing it as 'Mycall_back' in your kv file, which refers to a different method that exists. Make sure your letter cases match.
video example

Python for kivy:Pass values between multiple screens

I am developing a kivy app in which ,there are two screens
1.LoginScreen
and 2.HomeScreen.
What required is -
A value 'xyz' which is computed in class LoginScreen, to be passed to the method 'insertdata' of class HomeScreen and want to display that value on a label.
For this I tried following code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import Screen, ScreenManager
class loginScreen(Screen):
def __init__(self,**kwargs):
super(HomeScreen, self).__init__(**kwargs)
def auth(self):
xyz=1
self.manager.current="home"
obj=HomeScreen()
# 1. To Pass 'xyz' to method scrn2
HomeScreen.insertdata(obj)
class HomeScreen(Screen):
def __init__(self,**kwargs):
super(LoginScreen, self).__init__(**kwargs)
if (a==1):
# 2. To display label
self.scrn2()
def insertdata(self):
print "screen 2"
label=Label(text="good moring")
self.add_widget(label)
class ScreenApp(App):
pass
if __name__ == '__main__':
ScreenApp().run()
Here:
insertdata is called from method auth
1)the 1st way is proper , as it is passing 'xyz' and calling the method insertdata but it dosen't display label
2) in 1st way I have to create to create an object of HomeScreen ,to call insertdata, which in turn calls the ___init__ of Homescreen and init calls insertdata
insertdata called from __init__
1) It loads data before user authentication at loginscreen
insertdata gets total 3 calls, which is affecting app launch time.
Suggest me any simple and effective way for this.
Thanks in advance.
You can use Screen.manager() method to get an manager object from one screen, use it to retrieve another one with its ScreenManager.get_screen() method and then pass the value directly. For an working example check an answer of this question: Kivy - Slider Class value change on another screen

Categories