I am encountering some strange/unexpected behaviour when displaying content in a Textinput field (Initially used for new record input - subsequently for show record data). Data is available in a dictionary and is assigned to Textinput fields. For short data the characters will be hidden sometimes:
It seems that the cursor is at the end of the string and all characters are at the left side and 'hidden'(?) behind the label. After mouseclick in the field and arrow left, the characters appear.
What is wrong in my kv definitions? :
BoxLayout:
orientation: "horizontal"
height: 25
size_hint_y: None
Label:
id: _socialsource_label
size_hint: 0.35,1
text: "Social access token:"
size: self.texture_size
halign: 'left'
valign: 'middle'
font_size: 14
color: .3,.3,.3,1
TextInput:
id: socialsource
padding: 4,2,4,0
size_hint: 0.65,1
font_size: 14
multiline: False
readonly: False
text_size: self.width, None
halign: 'left'
foreground_color: .3,.3,.3,1
disabled_foreground_color: .3,.3,.3,1
background_normal: './images/tinputBGnormal.png'
background_active: './images/tinputBGactive.png'
background_disabled_normal: './images/tinputBGdisnormal.png'
background_disabled_active: './images/tinputBGdisactive.png'
In the python code the data is assigned by:
self.socialchnl.text = projdict[0]['PRJSocchnl:']
self.socialsource.text = projdict[0]['PRJSocsrc:']
self.socialprovdr.text = projdict[0]['PRJSocprv:']
You hint_text instead of text for your TextInputs. Something like
MyTextInput:
id: social
hint_text: some_social_name
After gaining more experience with kivy, I came up with the following solution:
Just set the cursor position at the same time you assign new data to the textinput:
self.socialsource.text = projdict[0]['PRJSocsrc:']
self.socialsource.cursor = (0, 0)
Related
I'm trying to use this id "self.ids.input_tornillo.text" and put it inside a variable in my main.py but when running this code I got this Error: "NameError: name 'self' is not define". I think the word self just work inside a function. But I don't know if it really necessary create a funcion for this or I can do it in another way. Pls someone can give me a hand? -
main.py
class FirstWindow(Screen):
#Variables Shopping Cart
var1= StringProperty("images/shoppingcart.png")
var2= StringProperty("images/shoppingcart2.png")
#Variables Items
variable= self.ids.input_tornillo.text
#Here is the problem with self, How can I put it in a variable?
main.kv
<FirstWindow>:
name: "Catalogue"
BoxLayout:
orientation:'vertical'
pos_hint: {'top': 1}
size: root.width, root.height
size_hint_y: .55
GridLayout:
size:(root.width, root.height)
size_hint_x: None
size_hint_y: None
cols:4
height: self.minimum_height
Label:
text: "Items"
#font_size: 25
Label:
text: "Number"
Label:
text: "Price"
Label:
text: "Add to Cart"
ScrollView:
size_hint_y: .80
pos_hint: {'x':0, 'y': .11}
do_scroll_x: True
do_scroll_y: True
GridLayout:
size:root.width, root.height
size_hint_x: None
size_hint_y: None
cols:4
#height: self.minimum_height
#Label:
# text: "Items"
#font_size: 25
#Label:
# text: "Number"
#Label:
# text: "Price"
#Label:
# text: "Add to Cart"
Label:
text: "Tornillos"
text_size: self.size
halign: 'center'
valign: 'bottom'
Image:
id: image_tornillos
allow_stretch: True
keep_ratio: True
size_hint: 0.2,0.2
width: 60
height: 80
#pos_hint: {'center_x':1, 'center_y':1}
source: "images/tornillo.png"
center_x: self.parent.center_x
center_y: self.parent.center_y+10
TextInput:
id: input_tornillo #I need to put this id in a variable in my main.py
text: ""
halign: "right"
font_size: 18
multiline: True
#size_hint: (1, .15)
I was thinking create a function too and make it like this
class FirstWindow(Screen):
#Variables Shopping Cart
var1= StringProperty("images/shoppingcart.png")
var2= StringProperty("images/shoppingcart2.png")
#Variables Items
def list_items(self):
tornillo= self.ids.input_tornillo.text
tornillo1= float(tornillo) * 0.10
tornillo2= str(tornillo1)
but I don't how to call my variable "tornillo2" in my main.kv either
TextInput:
id: input_tornillo
text: ""
halign: "right"
font_size: 18
multiline: True
#size_hint: (1, .15)
Label:
id: label_tornillo
#text: root.ids.input_tornillo.text*2
text: root.tornillo2
root.tornillo2 is giving me this error...
AttributeError: 'FirstWindow' object has no attribute 'tornillo2'
In the python code, define a property for the variable "tornillo2"
tornillo2 = StringProperty("")
Now you can use it in the kv file as you did it already
(text: root.tornillo2)
Essentially, I have multiple screens, being controlled by the screen manager (primarily for logins), however on the main screen, I have it broken up with a header, nav bar, and a section for the body. In the body section is where I want to be able to call different layouts that I have classes for, and add and remove these as buttons on the nav bar are pressed.
Im using kivy to control all aspects of the gui, but am rather new to it. At the moment I have:
Builder.load_string('''
<MainMenu>:
FloatLayout:
canvas.before:
Color:
rgba: 0.235, 0.271, 0.302, 1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
orientation: 'vertical'
rows: 4
Label:
size_hint: 1,0.12
text: "ProductName"
text_size: self.size
halign: 'left'
valign: 'middle'
font_size: 32
color: [0.114,0.18,0.224,1]
StackLayout:
size_hint: 1,0.10
orientation: 'lr-tb'
#Purchase Order System
Button:
id: butpos
text: "Purchase Order"
size_hint: 0.166,1
on_press: spaceholder.add_widget(pos)
#Asset Assignment System
Button:
id: butaas
text: "Asset Assignment"
size_hint: 0.166,1
#Review and Revise System
Button:
id: butrrs
text: "Review"
size_hint: 0.166,1
#Administrative System
Button:
id: butadm
text: "Administration"
size_hint: 0.166,1
#Analytics and Reporting System
Button:
id: butars
text: "Analytics"
size_hint: 0.166,1
#Placeholder, possibly documentation
Button:
id: butbut
text: "Placeholder"
size_hint: 0.166,1
Label:
canvas.before:
Color:
rgba: 0.259, 0.643, 0.937, 1
Rectangle:
pos: self.pos
size: self.size
size_hint: 1,0.005
Widget:
id: spaceholder
<PurchaseOrder>
id: pos
orientation: 'lr-tb'
#Asset Details
Label:
BoxLayout:
orientation: 'vertical'
Label:
text: "Asset Requirements"
Label:
text: "Asset1: "
TextInput:
id: as1count
Label:
text: "Asset2: "
TextInput:
id: as2count
''')
class MainMenu(Screen):
pass
class PurchaseOrder(StackLayout):
pass
class MainApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MainMenu(name='mainmenu'))
return sm
if __name__ == '__main__':
MainApp().run()
PurchaseOrder is a class that Id like to be added or removed, much like classes I intend to set up for the other navigation options. Ive tried a number of methods, but I think im missing something. Im either being thrown with 'pos' is not defined, or that 'spaceholder' has wrong attributes when ive tried different combinations.
You can make that work by modifying the Purchase Order Button:
on_press: spaceholder.add_widget(Factory.PurchaseOrder())
That requires an addition to your kv to import Factory:
#:import Factory kivy.factory.Factory
I would recommend using a Layout for your spaceholder to take advantage of their sizing and positioning capabilities. For example, using an AnchorLayout automatically centers its child (but is limited to a single child). Like this:
AnchorLayout:
id: spaceholder
I'm creating a kivy app right now. I'm quite new to Kivy and kv lang and there doesn't seam to be much rumour about it although i find it great to seperate code logic and layout, especially after some pygame development.
So to my actuall problem: I have a wiki-style screen for screenmanager, consisting out of a BoxLayout:
Title as Label
Scrollable Label for the Text (later , there shall be displayed a nested kv file)
Buttons for Navigation (scroll up and go back to main screen)
Now I'm recreating the Navigation buttons to be floating type as known from many webpages and apps. Problem is, I suddendly cant reference my ScrollView anymore. Any help or suggestions?
<Wiki>:
name: "wiki"
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: "picture.jpg"
BoxLayout:
id: box
orientation: "vertical"
padding: 10
spacing: 10
Label:
font_size: 20
size_hint_y: .1
text: root.country_text
ScrollView:
id: scrlvw
BackgroundLabel:
background_color: 220,220,220, 0.5
size_hint_y: None
text_size: self.width, None
height: self.texture_size[1]
halign: "left"
valign: "top"
text: root.wiki_text
FloatLayout:
size_hint_y: .1
Button:
size_hint_x: .2
pos_hint: {"center_x": .25, "center_y": .5}
text: "Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
FloatButton:
size_hint_x: .2
pos_hint: {"center_x": .75, "center_y": .5}
text: "Up"
on_release:
widget = BoxLayout()
widget.ids.scrlvw.scroll_y = 0
Before, when it worked, it was:
BoxLayout:
FloatLayout:
size_hint_y: .1
Button:
size_hint_x: .2
pos_hint: {"center_x": .25, "center_y": .5}
text: "Back"
on_release:
app.root.current = "main"
root.manager.transition.direction = "right"
Button:
size_hint_x: .2
pos_hint: {"center_x": .75, "center_y": .5}
text: "Up"
on_release:
scrlvw.scroll_y = 0
Well as its just a design question, I guess i temporary have to dismiss the floating design. But I would be so pleased if you could help me understand this language better.
As long as the 'kv' code described as "when it worked" is still in the same <Wiki> rule, it should still work. The newer kv code will never work as you are trying to create a new BoxLayout and reference an id in it. That has two problems:
The newly created BoxLayout is not the BoxLayout instance that appears in your GUI, so any changes to it will have no effect on what appears in the display.
Unless you have a <BoxLayout> rule in your kv, the newly created BoxLayout will not have a scrlvw id.
The ids defined within a kv rule are available for use only within that rule. See the documntation.
I added a checkbox on my sign-in screen for saving the username and password information so the user will not have to enter them every time. I thought about creating a text file that will store this information, but maybe there is a better approach. I'm not able to save it properly; this is what I have so far. In the init method of my class, I'm checking to see if there is a text file with the information. If so, I want to extract the username and password to fill in the TextInputs on my screen. If not, I'll leave them empty and let the user fill in the two TextInputs. The Textinputs are taking care of in my next method add_user(). I get this error: AttributeError: 'super' object has no attribute '__getattr__'. I haven't figured out the checkbox behavior since I already an error. Does anyone have an idea?
try.py
class SigninWindows(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
if os.path.isfile('prev_details.txt'):
with open('prev_details.txt', 'r') as f:
d = f.read().split(',')
self.ids.username_field.text = d[0]
self.ids.pwd_field.text = d[1]
else:
self.ids.username_field.text = ''
self.ids.pwd_field.text = ''
def add_user(self):
uname = self.ids.username_field.text
passw = self.ids.pwd_field.text
info = self.ids.info
table_name = uname.replace('#', '_').replace('.', '_')
try.kv
<SigninWindows>:
id: signin_page
name: "signin_page"
orientation: "vertical"
spacing: 10
space_x: self.size[0]/5.5
canvas.before:
Color:
rgba: (0,0,0,1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
id: data_signin
orientation: 'vertical'
size_hint_x: 1
BoxLayout:
Image:
id: ds_im
orientation: 'vertical'
source: 'ds.png'
allow_stretch: True
BoxLayout:
id: validate_info
orientation: "vertical"
size_hint: 1,0.8
padding: 80, 10
Label:
id: info
text: ''
markup: True
TextInput:
id: username_field
text: ''
hint_text: "Username"
hint_text_color: 0.5,0.5,0.5,1
multiline: False
focus: True
on_text_validate: pwd_field.focus = True
size_hint: 1, .8
foreground_color: 0.5,0.5,0.5,1
background_color: .1,.1,.1,1
write_tab: False
TextInput:
id: pwd_field
text: ''
hint_text: "Password"
hint_text_color: 0.5,0.5,0.5,1
multiline: False
password: True
on_text_validate: root.validate_user()
size_hint: 1,0.8
foreground_color: 0.5,0.5,0.5,1
background_color: .1,.1,.1,1
BoxLayout:
id: remember_section
orientation : 'horizontal'
size_hint_x: None
width: 80
size_hint_y: None
height: 50
padding: 80, 10
CheckBox:
text: ''
size_hint_x: None
width: 25
size_hint_y: None
height: 25
canvas.before:
Color:
rgba: (1, 1, 1, 1)
Rectangle:
size: self.size
pos: self.pos
Label:
text: 'Remember User id?'
font_size: 20
size_hint_x: None
width: 220
The ids dictionary of SigninWindows has not yet been created when the __init__() method is running. You can move that code into another method and call it using Clock.schedule_once(). That will delay its execution very slightly until the ids are available.
There is not a much better way to do this rather than a text file. Import the OS module and do os.readfile(filepath and or if it is in the same folder as your .py file just the name) and read from there the rest is straight forward.
So I have this chatting app like structure I have made using Kivy's RecycleView to instantiate a custom widget (named 'Row') and I pass it values however I wish.
It works fine if the Row custom widget only contains a Label child, the moment I add an Image and a Button (I'll explain why in a sec), there are weird spacing and positioning problems which shouldn't exist because I am using a BoxLayout and have tried proper size_hint: and height: techniques to get them to look right.
Relevant KV code:
<Row#BoxLayout>:
orientation: 'vertical'
text: ''
source: 'res/icon.png'
buttontext: ''
Label:
markup: True
text_size: self.size
text: root.text
Image:
size: self.size
source: root.source
allow_stretch: True
Button:
text: root.buttontext #contains a link
on_press: app.root.stuff(self.text) #opens that link
# Relevant Screen where I am using the RecycleView
<ChatBotScreen>
BoxLayout:
ti_userinput: ti_userinput
orientation: 'vertical'
ScrollView:
size_hint_y: 85
RecycleView:
id: chatbase_list
viewclass: 'Row'
data: []
RecycleBoxLayout:
padding: "15dp", "45dp", "15dp", "15dp"
default_size: None, dp(25)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
TextInput:
size_hint_y: None
height: "40dp"
id: ti_userinput
multiline: False
on_text_validate: root.on_user_enter_text()
Since my custom widget Row is extending BoxLayout and I am using a vertical orientation, why aren't the child widgets (Label, Image and Button) overlapping?
This is the class & function via which I am calling to pass the data inside the RecycleView
class ChatBotScreen(Screen):
nickname = StringProperty()
rvList = []
def display_bot_output(self, botOutput):
# Initialize an empty dictionary
tempDict = {}
textToDisplay = '' + botOutput
# Update the dictionary with properties:values and then pass it as a list to RecycleView's data
tempDict.update({'text':textToDisplay, 'buttontext':'https://google.com'})
self.rvList.append(tempDict)
self.ids.chatbase_list.data = self.rvList
What I want to be visible on screen is:
The text I send through the textToDisplay variable in the Label
Underneath the Label, Image should be displayed the source of which I can pass, if no source passed, no image displayed
Underneath the Image, a button with a link should be displayed which I pass through buttontext, if not passed, no button should be displayed.
I am able to render all that but the spacing and all is all messed up.
Screenshot below:
Here I first sent data with only Label text info and Image, thus the Button text is empty (it still shows up), then I send another data (2nd Row widget) with Label text info, Image as well as a Button text (which is google link).
Any help is greatly appreciated. Thanks!
<ChatBotScreen>
BoxLayout:
ti_userinput: ti_userinput
orientation: 'vertical'
ScrollView:
# to have the screen get bigger not lliek what you have
size: root.size
RecycleView:
id: chatbase_list
viewclass: 'Row'
data: []
RecycleBoxLayout:
padding: "15dp", "45dp", "15dp", "15dp"
default_size: None, dp(25)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
# add this so you can scroll
row_default_height: 60
orientation: 'vertical'
TextInput:
size_hint_y: None
height: "40dp"
id: ti_userinput
multiline: False
on_text_validate: root.on_user_enter_text()