as far as I know, my codes are good because there is no error from the IDE, and I used the same code on another project and it works. I read from SO posts that say, maybe the object don't have the .text() method, that would give me an error, but I don't have an error. Another post that say could come from not set the table to an object. As far as I know, I referenced everything correctly.
does it have to do with the data type? thanks again for some insight.
main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.lang.builder import Builder
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Rectangle, Color
import socket
class Screen_Manager(ScreenManager):
screen_1 = ObjectProperty()
class Screen_1(Screen):
main_display = ObjectProperty()
def __init__(self, **kwargs):
super(Screen_1, self).__init__(**kwargs)
def get_host(self):
self.s = socket.gethostbyname(socket.gethostname())
return self.s
class MainApp(App):
def build(self):
self.title = "Number Display App"
self.sm = Screen_Manager()
return self.sm
if __name__=="__main__":
MainApp().run()
main.ky
<Screen_Manager>:
Screen_1:
<Screen_1>:
id: screen_1
name: "first"
main_display: display_1
Label:
id: display_1
text: root.get_host()
font_size: "30sp"
It looks like you don't set the text of your label to anything but " ".
Related
I'm using Kivy for a user interface to a control application. As such, the UI is subsidiary to the essential functionality. For modularity/tidyness, I've been trying to place all the Kivy code in a separate source file and to call it as the last step in Main.
However, if I do this, I find that some things don't work properly (for example, creating labels programatically and updating their text by scheduled events).
Is this something which should be possible?
Is there a 'trick' of which I should be aware?
If the detail of my question is not clear, I can put up some test code to illustrate.
Monolithic code, which works as expected:
cat test.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import StringProperty
from kivy.clock import Clock
import random
Builder.load_string('''
<YourWidget>:
BoxLayout:
id: Box1
size: root.size
Button:
id: button1
text: "Change text"
on_release: root.change_text()
''')
class YourWidget(Screen):
random_number = StringProperty()
def __init__(self, **kwargs):
super(YourWidget, self).__init__(**kwargs)
label = Label(
id= 'label1',
text = self.random_number
)
self.ids.Box1.add_widget(label)
self.random_number = 'ini'
Clock.schedule_interval(self.change_text,1)
def change_text(self, *largs):
self.random_number = str(random.randint(1, 100))
class updatetestapp(App):
def build(self):
sm = ScreenManager(transition=NoTransition())
sm.add_widget(YourWidget(name='d_analogs'))
return YourWidget()
if (True):
updatetestapp().run()
If I then attempt to modularise my code, placing all the Kivy processing in a user function,everything works except the display of the ransom number variable. The variable persists through successive callbacks, as shown by calls to print, but it simply doesn't display. I'm guessing that this is something to do with the scope or context of the variable - Kivy isn't displaying the same variable which is being updated in the callback.
cat Main.py
#from mytest import mytest
import threading
import time
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import StringProperty
from kivy.clock import Clock
from display import *
def main():
Display()
if __name__ == "__main__":
main()
cat display.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.properties import StringProperty
from kivy.clock import Clock
import random
Builder.load_string('''
<YourWidget>:
BoxLayout:
id: Box1
size: root.size
Button:
id: button1
text: "Change text"
on_release: root.change_text()
''')
class YourWidget(Screen):
random_number = StringProperty()
def __init__(self, **kwargs):
super(YourWidget, self).__init__(**kwargs)
label = Label(
id= 'label1',
text = self.random_number
)
self.ids.Box1.add_widget(label)
self.random_number = 'ini'
Clock.schedule_interval(self.change_text,1)
def change_text(self, *largs):
self.random_number = str(random.randint(1, 100))
class test(App):
def build(self):
sm = ScreenManager(transition=NoTransition())
sm.add_widget(YourWidget(name='d_analogs'))
return YourWidget()
def Display():
test().run()
You don't have any code that would change the text of your Label. Although you update self.random_number, you don't update the Label's text property, therefore you don't see any change.
I've got a python file(root.py) and another python file(button.py). When I define a button with an attribute (such as size_hint:0.1,1) in button.py using the kv language, root.py doesnt seem to be able to access that information.
When I define the same information using python in button.py, root.py seems to be able to access it.
ROOT.PY
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
from buttons import *
Builder.load_string("""
<Root>:
ButtonBar:
""")
class BtnBar(ButtonBar):
print(self.size_hint) # prints [1,1] instead of [0.1,1]
class Root(FloatLayout):
pass
class AppDev(App):
def build(self):
return Root()
BUTTON.PY
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
Builder.load_string("""
<ButtonBar>:
size_hint: 0.1,1
""")
class ButtonBar(FloatLayout):
pass
Root.py should be able to access any information I declare in button.py's Builder.load_string
After the object is instantiated, the right data will be accessable. You can use clock to make sure you get it after instantiation.
Also in your kv string, you probably want BtnBar instead of ButtonBar
Here is your root.py rewritten to do this.
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.lang.builder import Builder
from kivy.clock import Clock
from buttons import *
Builder.load_string("""
<Root>:
BtnBar: # corrected to BtnBar
""")
class BtnBar(ButtonBar):
def __init__(self, **kwargs):
super(BtnBar, self).__init__(**kwargs)
Clock.schedule_once(self.get_data)
def get_data(self, dt):
print(self.size_hint) # prints on second frame
class Root(FloatLayout):
pass
class AppDev(App):
def build(self):
return Root()
AppDev().run()
i want popup effect for references in kivy reStructuredText renderer, in default when we press any reference it scrolls to the reference, here i want to replace scroll with a popup, i have been searching for this for a long time but in vain, today i found goto(ref, *largs)in kivy docs, is it possible to call a reference popup using this? is it possible to redefine RstDocument fuctions in another class and use it?? i am a beginner.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
Builder.load_string("""
<RSTGUI>:
RstDocument:
text: root.doc
goto: # Any Popup aur bubble with reference
""")
class RSTGUI(BoxLayout):
doc="""
.. _top:
Hello world
===========
This is an **emphased text**, some ``interpreted text``.
And this is a reference to top_::
$ print("Hello world")
"""
class RST(App):
def build(self):
return RSTGUI()
if __name__=='__main__':
RST().run()
After little research i have figured it out, Alhumdolillah.
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.uix.rst import RstDocument
from kivy.uix.popup import Popup
Builder.load_string("""
<RSTGUI>:
MyRST:
text: root.doc
<about_us_popup>:
size_hint: 0.8,0.6
title: "About Us"
BoxLayout:
orientation:'vertical'
RstDocument:
text: "MyText"
Button:
text:"OK"
size_hint: 1,0.1
on_press:root.dismiss()
""")
class RSTGUI(BoxLayout):
doc="""
.. _top:
Hello world
===========
This is an **emphased text**, some ``interpreted text``.
And this is a reference to top_::
$ print("Hello world")
"""
class MyRST(RstDocument):
def __init__(self, **kwargs):
super(MyRST, self).__init__(**kwargs)
self.about_us_popup = about_us_popup()
def goto(self, ref, *largs):
self.about_us_popup.open()
class RST(App):
def build(self):
return RSTGUI()
class about_us_popup(Popup):
pass
if __name__=='__main__':
RST().run()
I am learning Kivy and having trouble connecting my objects declared in the .kv file to the python class in order to update their properties. No matter which way I try I get this error:
self.kbCompressionLabel.text = 'Hello World'
AttributeError: 'NoneType' object has no attribute 'text'
The app loads all the kivy files fine, and only breaks when I try to update from the Class.
I've dumbed down the current code to the minimum to illustrate how it is setup. Any help is much appreciated.
Main app entry
import kivy
kivy.require('1.10.0')
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager
Builder.load_file('appscreenmanager.kv')
Builder.load_file('compressorscreen.kv')
Builder.load_file('slidersview.kv')
class AppScreenManager(ScreenManager):
pass
class AppManager(App):
def build(self):
return AppScreenManager()
if __name__ == "__main__":
AppManager().run()
Dumed down appscreenmanager.kv
#:kivy 1.10.0
<AppScreenManager>:
CompressorScreen:
...
compressorscreen.kv
<CompressorScreen>:
name: 'compressor'
GridLayout:
rows: 4
cols: 1
SlidersView:
...
This is where the issue is happening: simplified slidersview.kv
#:kivy 1.10.0
#:import slidersview slidersview
<slidersView>:
cols: 4
rows: 2
id: sliders
kbCompressionLabel: kbCompressionLabel
Label:
id: kbCompressionLabel
text: 'test'
slidersview.py
import kivy
kivy.require('1.10.0')
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class SlidersView(GridLayout):
# properties
sliders = ObjectProperty(None)
kbCompressionLabel = ObjectProperty(None)
def __init__(self, **kwargs):
self.kbCompressionLabel.text = 'Hello World'
super(SlidersView, self).__init__(**kwargs)
UPDATE
I had to add a delay into the init function then things worked. However, this feels pretty wonky to me. Is this the expected behavior?
Updated slidersview.py
import kivy
kivy.require('1.10.0')
from kivy.clock import mainthread
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
class SlidersView(GridLayout):
# properties
kbCompressionLabel = ObjectProperty(None)
def __init__(self, **kwargs):
super(SlidersView, self).__init__(**kwargs)
#mainthread
def delayed():
self.kbCompressionLabel.text = 'Hello World'
delayed()
The KV definitions are applied only when you call __init__ of the base classes...
reverse the order and you'll be fine...
class SlidersView(GridLayout):
# properties
sliders = ObjectProperty(None)
kbCompressionLabel = ObjectProperty(None)
def __init__(self, **kwargs):
super(SlidersView, self).__init__(**kwargs) #first!
self.kbCompressionLabel.text = 'Hello World' #2nd!
I have a basic text input box with some text in it. When the user attempts to copy the text, I want to execute a function that modifies the text first then returns it. An on_copy event would be perfect. However, I do not see an obvious way to do this in Kivy.
You can create TextInput subclass that overrides the copy() method:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.clock import Clock
Builder.load_string("""
<MyWidget>:
MyTextInput:
MyTextInput:
""")
class MyTextInput(TextInput):
def copy(self, data=''):
# wrap copied text with ---
if data:
data = "--- {} ---".format(data)
else:
data = "--- {} ---".format(self.selection_text)
return super(MyTextInput, self).copy(data)
class MyWidget(BoxLayout):
pass
class ClientApp(App):
def build(self):
return MyWidget()
if __name__ == '__main__':
ClientApp().run()
You should probably override cut() method too.