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.
Related
This is my first question, so sorry if butcher it.
I'm making an application, that will allow for a more efficient protocol creation for other people at my job.
The problem is, that I'm trying to update created RecycleView, but for some reason it doesn't work. Some solutions on the web advise using .refresh_from_data() method, but it did not work, and all the other solutions are too complicated (or I'm too dumb).
I have this function - add_entry that adds information from two TextInputs as a dictionary inside protocol list.
At the current moment my RecycleView just shows numbers, because no solution have worked, and I actually really struggled to even make a Recycle View.
Here is relevant part of Python code:
class DrillingInfoPage(Screen):
rod = 1
dist = 3
protocol = ListProperty() # {Rod:_,Distance:_,Proc:_,Depth:_}
def add_entry(self, proc, depth):
self.protocol.append({'Rod': 0, 'Distance': 0, 'Proc': 0, 'Depth': 0})
self.protocol[self.rod-1]['Proc'] = proc
self.protocol[self.rod-1]['Depth'] = depth
self.protocol[self.rod-1]['Rod'] = self.rod
self.protocol[self.rod-1]['Distance'] = self.dist
self.rod += 1
self.dist += 3
print(self.protocol)
return self.protocol
class Profile(Screen):
pass
class WindowManager(ScreenManager):
pass
class ColorsPopup(Screen):
popupWindow = None
class Recycle(RecycleView):
def __init__(self, **kwargs):
super(Recycle, self).__init__(**kwargs)
self.data = [{'text': str(x)} for x in range(50)]
kv = Builder.load_file("my.kv")
class MyApp(App):
def build(self):
return kv
if __name__ == '__main__':
MyApp().run()
And here is a relevant part of KV file:
<DrillingInfoPage>:
name: 'third'
BoxLayout:
orientation: 'vertical'
Label:
size_hint: 1, .4
text: 'Drilling Info Page'
GridLayout:
size_hint: 1, .1
cols:3
GridLayout:
cols:2
Label:
text: 'BG'
TextInput:
id: start
multiline: False
GridLayout:
cols:2
Label:
text: 'BG'
TextInput:
id: end
multiline: False
Button:
text: 'Confirm'
on_release: drilling_holes.text = 'BG' + start.text + ' -----> ' + 'BG' + end.text
GridLayout:
size_hint: 1, .1
cols:3
GridLayout:
cols:2
Label:
text: '%:'
TextInput:
id: proc
multiline: False
GridLayout:
cols:2
Label:
text: 'Depth:'
TextInput:
id: depth
multiline: False
Button:
text: 'Add'
on_release: root.add_entry(proc.text, depth.text)
Label:
id: drilling_holes
size_hint: 1, .2
text: ''
Recycle:
id: drilling_data
data: self.data
viewclass: 'Label'
RecycleBoxLayout:
default_size: None, '25dp'
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Label:
size_hint: 1, .2
text: ''
GridLayout:
size_hint: 1, .17
cols:2
Button:
text: 'Go Back'
on_release:
app.root.current = 'second'
root.manager.transition.direction = 'down'
Button:
text: 'Confirm'
on_release:
app.root.current = 'last'
root.manager.transition.direction = 'up'
I've tried creating some functions inside RecycleView class that would refresh the data, as well as inside the DrillingInfoPage class, but nothing seems to work.
I'm new to Python and especially Kivy, therefore hoping someone wise can guide me in the right direction :)
Here how the screen itself looks right now, ideally it should be empty at first and pressing 'Add' button should add a new line
You just have to add the new information to the data list of the RecycleView. It's not clear exactly what you want to add to the RecycleView, but you can just add a line to your add_entry() method like this:
self.ids.drilling_data.data.append({'text': proc}) # add new entry to data list
And that method does not need a return statement
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)
I have an App with three toggle buttons in a fixed header that is an outside indented layout for screen manager. On initialisation, the Import screen must show i.e. self.ids.scrn_man.current = 'import_scn" and when a toggle button is pushed a next screen should show i.e. on_state: scrn_man.current = "settings_scrn".
But for some reason, only the header is showing and the screens do not want to transition. I don't get any errors.
I tried different layouts as my Apps main class inheritance including, FloatLayout, StackLayout and BoxLayout. I also made the header fixed with AnchorLayout and use a different layout as the inline layout for ScreenManager. If I remove the ScreenManager I see my widgets, but of course, I cannot transition. I did at first try using TabbedPanel to house my different widgets but I encountered a constant RefError: weak object reference if I added too many widgets (but that's not for now). So I re-designed with something I knew worked on a previous App albeit less complex.
Here is my faulty code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import StringProperty, ObjectProperty
Builder.load_string("""
<RoundedButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.6,0,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<RoundedCancelButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.2,.2,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<RoundedAcceptButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (.2,1,.6,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<TabbedContainer#ToggleButton>:
background_color: (1, .5, 0, 1)
background_normal: ''
size_hint_y: None
height: 50
size_hint_x: (1 / 3)
spacing: 30
<Tab>:
canvas.before:
Color:
rgba: (.89, .89, .89, 1)
Rectangle:
size: self.size
pos: self.pos
orientation: 'lr-tb'
BoxLayout:
orientation: 'horizontal'
size_hint_y: None
height: 30
canvas.before:
Color:
rgba: (1, .3, 0, 1)
Rectangle:
size: self.size
pos: self.pos
Label:
text: 'Test'
color: (1, 1, 1, 1)
size_hint_x: 1
StackLayout:
orientation: 'lr-tb'
Label:
text: ''
size_hint_x: 1
size_hint_y: None
height: 10
TabbedContainer:
id: import_tog
text: 'Import'
state: 'down'
group: 'admin_navs'
on_state: root.change_screen(self)
TabbedContainer:
id: calculate_tog
text: 'Calculate'
group: 'admin_navs'
on_state: root.change_screen(self)
TabbedContainer:
id: settings_tog
text: 'Settings'
group: 'admin_navs'
on_state: root.change_screen(self)
BoxLayout:
id: ui_content
padding: 10
ScreenManager: #Problem here I think
id: scrn_man
Screen:
id: import_scrn
name: 'import_scrn'
StackLayout:
orientation: 'lr-tb'
Label:
text: ''
size_hint_x: 1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Choose File'
size_hint_x: 0.2
TextInput:
id: get_file
readonly: True
size_hint_x: 0.5
Label:
text: ''
size_hint_x: 0.1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Import'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.6
StackLayout:
id: import_data_content
orientation: 'lr-tb'
size_hint_y: None
height: 90
Screen:
id: calculate_scrn
name: 'calculate_scrn'
Screen:
id: settings_scrn
name: 'settings_scrn'
StackLayout:
orientation: 'lr-tb'
size_hint_x: 0.5
Label:
text: ''
size_hint_x: 0.1
Button:
text: 'Add Employee'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.2
Button:
text: 'CSV'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.3
BoxLayout:
orientation: 'horizontal'
size_hint_x: 0.5
Label:
text: 'In Time'
size_hint_x: 0.7
TextInput:
size_hint_x: 0.3
Label:
text: 'Out Time'
size_hint_x: 0.7
TextInput:
size_hint_x: 0.3
""")
class TabbedContainer(ToggleButton):
pass
class FileChoosePopup(Popup):
load = ObjectProperty()
class RoundedButton(Button):
pass
class RoundedCancelButton(Button):
pass
class RoundedAcceptButton(Button):
pass
class Tab(StackLayout):
file_path = StringProperty("No file chosen")
the_popup = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
#load import window on initialisation
import_window = self.ids.import_scrn
self.ids.scrn_man.current = 'import_scrn'
def change_screen(self, instance):
if instance.text == 'Import':
self.ids.scrn_man.current = 'import_scrn'
elif instance.text == 'Calculate':
self.ids.scrn_man.current = 'calculate_scrn'
else:
self.ids.scrn_man.current = 'settings_scrn'
class TestApp(App):
def build(self):
return Tab()
if __name__ == '__main__':
TestApp().run()
I expect that the import screen must show on initialisation and screens transition on toggle button state: down. Can someone please give me some advice on how to make my App act as explained above?
Your screens are loading correctly according to your settings. You need to review your entire kv string looking at your size_hint settings. Check each item that contains children and make sure that the total of size_hint_x for its children is less than or equal to 1.0 and the same for size_hint_y.
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)
I am making an app where there is a profile screen in which you can enter generic profile information (name, height, weight, ect..) using textinput boxes. I know there is a way to put a button next to each textinput box to save the information and another button to load the information. I am wondering if there is a way to automatically load this information when the user opens the app rather than manually loading the information by hitting a button.
<Phone>:
result: _result
h: _h
w: _w
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
ScreenManager:
size_hint: 1, .9
id: _screen_manager
Screen:
name: 'home'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: "/home/aaron/Desktop/main.png"
Label:
markup: True
text: '[size=100][color=ff3333]Welcome to [color=ff3333]Diabetes Manager[/color][/size]'
Screen:
name: 'menu'
GridLayout:
cols: 2
padding: 50
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: "/home/aaron/Desktop/main.png"
Button:
text: 'My Profile'
on_press: _screen_manager.current = 'profile'
Button:
text: 'History'
on_press: _screen_manager.current = 'history'
Button:
text: 'New Entry'
on_press: _screen_manager.current = 'new_entry'
Button:
text: 'Graph'
on_press: _screen_manager.current = 'graph'
Button:
text: 'Diet'
on_press: _screen_manager.current = 'diet'
Button:
text: 'Settings'
on_press: _screen_manager.current = 'settings'
Screen:
name: 'profile'
GridLayout:
cols: 1
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=40][color=0000ff]Name[/color][/size]'
TextInput:
id: _name
hint_text: 'Name'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=40][color=0000ff]Gender[/color][/size]'
TextInput:
id: _gender1
hint_text: 'Gender'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=34][color=0000ff]Type of Diabetes[/color][/size]'
TextInput:
id: _type
hint_text: 'Type of Diabetes'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=40][color=0000ff]Height (in)[/color][/size]'
TextInput:
id: _h
hint_text: 'Height in inches'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=40][color=0000ff]Weight (lb)[/color][/size]'
TextInput:
id: _w
hint_text: 'Weight in pounds'
BoxLayout:
Button:
text: 'Calculate BMI'
on_press: root.product(*args)
Label:
size_hint_x: 4.5
id:_result
bold: True
markup: True
text: '[size=40][color=0000ff]BMI[/color][/size]'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=30][color=0000ff]List of Medications[/color][/size]'
TextInput:
id: _meds
hint_text: 'List of Medications'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=38][color=0000ff]Insulin Times[/color][/size]'
TextInput:
id: _times
hint_text: 'Please Enter Times to Take Insulin'
Screen:
name: 'history'
GridLayout:
cols:1
Screen:
name: 'new_entry'
GridLayout:
cols:1
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=40][color=0000ff]Time[/color][/size]'
TextInput:
id: _time
hint_text: 'Current Time'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=28][color=0000ff]Blood Sugar (mg/dL)[/color][/size]'
TextInput:
id: _glucose_reading
hint_text: 'Current Blood Sugar'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=40][color=0000ff]Carbs[/color][/size]'
TextInput:
id: _food
hint_text: 'Total Carbs for meal'
BoxLayout:
Label:
size_hint_x: 0.22
bold: True
markup: True
text: '[size=30][color=0000ff]Medications Taken[/color][/size]'
TextInput:
id: _meds_taken
hint_text: 'Please Enter Any Medications Taken'
Screen:
name: 'graph'
GridLayout:
cols: 3
padding: 50
Label:
markup: True
text: '[size=24][color=dd88ff]Your Graph[/color][/size]'
Screen:
name: 'diet'
GridLayout:
cols: 3
padding: 50
Label:
markup: True
text: '[size=24][color=dd88ff]Reccomended Diet[/color][/size]'
Screen:
name: 'settings'
GridLayout:
cols: 3
padding: 50
Label:
markup: True
text: '[size=24][color=dd88ff]Settings[/color][/size]'
AnchorLayout:
anchor_x: 'center'
anchor_y: 'bottom'
BoxLayout:
orientation: 'horizontal'
size_hint: 1, .1
Button:
id: btnExit
text: 'Exit'
on_press: app.stop()
Button:
text: 'Menu'
on_press: _screen_manager.current = 'menu'
You can save the info in a json (import json) file, and load it using on_start event method.
Kivy uses a subclass of ConfigParser to parse standard ini files. Documentation on how to use this to load app-specific settings is on the kivy.app doc page.
From the docs:
class TestApp(App):
def build_config(self, config):
config.setdefaults('section1', {
'key1': 'value1',
'key2': '42'
})
def build(self):
config = self.config
return Label(text='key1 is %s and key2 is %d' % (
config.get('section1', 'key1'),
config.getint('section1', 'key2')))
Well, each App starts with build() function expecting a root widget to be returned, so either you can make a simple file loading with a function inside your App class and push values to each widget through ids or through root's widget children
or do the same loading function inside __init__() of your class where the widget values you want to update are.
For example class MyBox(BoxLayout) is a class with children which values you want to update. Then you call your loading function inside MyBox.__init__(). You can simplify it even more: use the loading function inside __init__() and create a list/dictionary/variables where you'll pass the values. Inside kv file you'll just access the variables through for example root.<variable>.