Python Kivy. My program should append the textfile, but is does not - python

Textfile should look like this :
e.g
Walking 61.0/2018-09-04 79.0/2018-10-04
Running 24.0/2018-09-04 33.0/2018-10-04
The point of this function is to append the textfile with the new value of the slider or to change one.
There are some names for the slider and each of them can have many values which consist of a slider.value and the current date. If today is not the date of the last value - then we append the file.
If today is the same date as the date of the last value - then it is supposed to change it(I did not do it yet, but this is not a problem, i will do it myself after I solve this problem).
Here is the full Python file and Kivy files, nothing but def save_values matters. Everything else is just to make the program working for you.
Python
from kivy.app import App
import time
import datetime
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.lang import Builder
from kivy.uix.slider import Slider
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.config import Config
screen_width = 450
screen_height = 800
Config.set("graphics", "resizable","1")
Config.set("graphics", "width", screen_width)
Config.set("graphics", "height", screen_height)
languages = ["Reading","Writing","Running","Climbing"]
spawned_List = ["False"]
class MenuScreen(Screen):
pass
class JobChoiceScreen(Screen):
def changing_screen(self, instance, *args):
self.manager.current= "sliderScreen"
screenSlider = self.manager.get_screen('sliderScreen')
text = str(instance.text)
screenSlider.changing_label(text)
def on_pre_enter(self, *args):
if spawned_List[0] == "False":
for x in range(0,len(languages)):
word = languages[x]
word = str(word)
btn = Button(text = word, size_hint=(None, None), size = (140,70),
font_size = 18, bold = True, color = [0,1,1,1], background_color = (.156, .172, .24, 0.7),
on_release = self.changing_screen)
self.ids.container.add_widget(btn)
spawned_List[0] = "True"
self.ids.boxLayBottom.add_widget(Widget(size_hint=(1, .4)))
self.ids.datesContainer.add_widget(Button(text = "Day back", size_hint=(.28, 1), font_size = 18, bold = True, color = [0,1,1,1], background_color = (.176, .192, .44, 0.7)))
self.ids.datesContainer.add_widget(Widget(size_hint=(.44, 1)))
self.ids.datesContainer.add_widget(Button(text = "Day forward", size_hint=(.28, 1), font_size = 18, bold = True, color = [0,1,1,1], background_color = (.176, .192, .44, 0.7)))
class SliderScreen(Screen):
def save_values(self, *args, **kwargs):
date = (datetime.datetime.now().strftime("%y-%m-%d"))
written = (str(self.ids.my_slider.value)+ "/" + date + " ")
print("started save_values")
with open('values.txt', 'r') as fileValues:
lines = fileValues.readlines()
print("opened the file")
with open('values.txt', 'a') as fileValues:
for i, line in enumerate(lines):
if line.startswith(self.ids.my_label.text) and line.find(date) == -1:
line = line + ((self.ids.my_label.text) + " " + written)
print(line)
if not line.startswith(self.ids.my_label.text) and line.find(date) == -1:
line = (" " + written)
print(line)
print("hello bill")
def changing_label(self, text):
self.ids.my_label.text = text
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("manager.kv")
class MainApp(App):
def build(self):
return presentation
if __name__ == "__main__":
MainApp().run()
Kivy
ScreenManagement:
#transition: FadeTransition()
MenuScreen:
JobChoiceScreen:
SliderScreen:
<MenuScreen>:
canvas:
Rectangle:
source:"background.jpg"
pos: self.pos
size: self.size
name: "menu"
BoxLayout:
padding: [10,10,10,10]
orientation: "vertical"
Widget:
size_hint: [1,0.2]
BoxLayout:
Button:
bold: True
color: [0,1,1,1]
on_release: app.root.current = "list_of_jobs"
text: "Change"
size_hint: [0.28,1]
font_size: 20
background_color: (.156, .172, .24, 0.7)
Widget:
size_hint: [0.44,1]
Button:
bold: True
color: [.5,0, .8, .7]
text: "View \n Progress"
size_hint: [0.28,1]
font_size: 20
halign: "center"
valign: "center"
background_color: (.156, .172, .24, 0.7)
on_release: app.root.current = "sliderScreen"
Widget:
size_hint: [1,0.2]
<JobChoiceScreen>:
canvas:
Rectangle:
source:"background.jpg"
pos: self.pos
size: self.size
name: "list_of_jobs"
BoxLayout:
orientation: "vertical"
padding: [10,10,10,10]
BoxLayout:
orientation: "vertical"
id: boxLayBottom
size_hint: (1,.1)
BoxLayout:
id: datesContainer
orientation: "horizontal"
size_hint: (1,.6)
AnchorLayout:
anchor_x: "center"
acnhor_y: "top"
size_hint: (1,.8)
GridLayout:
id: container
cols: 3
spacing: 5
BoxLayout:
orientation: "vertical"
id: boxContainer
size_hint: (1,.1)
Button:
text: "Back to Menu"
on_release: app.root.current = "menu"
bold: True
color: [0,1,1,1]
background_color: (.176, .192, .44, 0.7)
<SliderScreen>:
canvas:
Rectangle:
source:"background.jpg"
pos: self.pos
size: self.size
name: "sliderScreen"
BoxLayout:
padding: [10,10,10,10]
orientation: "vertical"
id: my_label_container
Slider:
id: my_slider
min: 0
max: 100
value: 0
orientation: "vertical"
size_hint: [1, 0.7]
step: 1
Label:
id: my_label
size_hint: [1, 0.2]
bold: True
font_size: 40
text: ""
Button:
size_hint: [1, 0.1]
bold: True
on_release: app.root.current = "menu"
text : "Back Home"
font_size: 20
halign: "center"
valign: "center"
background_color: (.156, .172, .24, 0.7)
on_press: root.save_values()
def save_values
def save_values(self, *args, **kwargs):
date = (datetime.datetime.now().strftime("%y-%m-%d"))
written = (str(self.ids.my_slider.value)+ "/" + date + " ")
print("started save_values")
with open('values.txt', 'r') as fileValues:
lines = fileValues.readlines()
print("opened the file")
with open('values.txt', 'a') as fileValues:
for i, line in enumerate(lines):
if line.startswith(self.ids.my_label.text) and line.find(date) == -1:
line = line + ((self.ids.my_label.text) + " " + written)
print(line)
if not line.startswith(self.ids.my_label.text) and line.find(date) == -1:
line = (" " + written)
print(line)
print("hello bill")

I see two problems with your code:
In your save_values() method, You are opening the values.txt file twice at the same time with the same name, but with different modes. I think you need to unindent the second with open block, remove the second with open statement, and modify the mode in the first with open statement to r+. So your code should look something like:
with open('values.txt', 'r+') as fileValues:
lines = fileValues.readlines()
print("opened the file")
for i, line in enumerate(lines):
You never call any write routine, so nothing gets written. When you want to append line/lines to values.txt, you need to call fileValues.write() or fileValues.writelines().
I have not looked at your code logic, so I will not comment on that.

Related

How to pass an instance of a Button in Kivy Builder

I would like to pass the instance of a button when clicked, to obtain its information - more importantly the text information. For now I have one screen with a list of songs as buttons. When clicked, I would like to open a text file with the name of the button and display its contents in a new screen. However, I don't know how to get the button that was pressed on the new screen. Any help is appreciated.
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.lang import Builder
import os
def get_song_list():
songs = [x for x in os.listdir("../data/") if ".txt" in x]
string = ""
for song in songs:
name = song.replace("_", " ").replace(".txt", "")
string += f"""Button:
text: "{name}"
background_color: 0, 0, 0, 0
size_hint: 0.5, None
height: 40
on_press:
root.manager.transition.direction = 'left'
root.manager.current = 'midi_sheet'\n\t\t\t"""
return string
def get_notes_in_song(song):
string = ""
with open(song) as f:
lines = f.readlines()
for line in lines:
string += line+"\n"
return string
class Home(Screen):
pass
class MidiSheet(Screen):
pass
Builder.load_string(f"""
<Home>:
ScrollView:
size_hint: 1, None
size: root.width, root.height
GridLayout:
cols: 1
spacing: 10
size_hint_y: None
{get_song_list()}
<MidiSheet>
ScrollView:
size_hint: 1, None
size: root.width, root.height
GridLayout:
cols: 1
spacing: 10
size_hint_y: None
Button:
text: "Back"
on_press:
root.manager.transition.direction = 'right'
root.manager.current = 'home'
Label:
text: "You opened "
""")
sm = ScreenManager(transition=SlideTransition())
sm.add_widget(Home(name="home"))
sm.add_widget(MidiSheet(name="midi_sheet"))
class Localiser(App):
def build(self):
return sm

Changing a label nested in a different screen in Kivy with screenmanager

I'm trying but failing on a simple task of changing a label nested in a different screen in Kivy with screenmanager.
I want to show "f_path" variable on "lbl_file_path" label. "lbl_file_path" label is on "W_MainMenu" screen. "f_path" is created on "W_FileSelector" screen.
How can I do this ? Any help is greatly appreciated. You may find the code below;
from logging import root
from charset_normalizer import from_path
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.properties import ObjectProperty
f_path = ""
class MyWinMan(ScreenManager):
pass
class W_MainMenu(Screen):
def transform_to_filechooser(self):
Window.size = (700, 950)
Window.top = 50
Window.left = 100
self.lbl_file_path.text = f_path
class W_FileSelector(Screen):
def transform_to_main(self):
Window.size = (700, 280)
Window.top = 50
Window.left = 100
def selected(self, filename):
try:
print(filename[0])
global f_path
f_path = filename[0]
except:
pass
kv = Builder.load_string("""
MyWinMan:
W_MainMenu:
W_FileSelector:
<W_MainMenu>:
lbl_file_path: lbl_file_path_k
name: "win_Main"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 40
spacing: 10
BoxLayout:
orientation: "horizontal"
size: root.width, root.height
padding: 0
spacing: 10
Button:
text:'Browse for Source Excel File'
font_size: 20
on_release:
app.root.current = "win_FS"
root.manager.transition.direction = "up"
root.transform_to_filechooser()
Image:
source:""
size_hint: ( 0.2, 1)
Label:
text:'Selected Excel File Path'
size_hint: ( 1, 0.4)
font_size: 18
color: ( 180/255, 180/255, 180/255, 1)
background_color: ( 50/255,50/255,50/255,1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
Label:
text: "Initial Text"
# text: f_path
id: lbl_file_path_k
size_hint: ( 1, 0.4)
font_size: 18
color: ( 50/255, 50/255, 50/255,1)
background_color: ( 180/255, 180/255, 180/255, 1)
canvas.before:
Color:
rgba: self.background_color
Rectangle:
pos: self.pos
size: self.size
<W_FileSelector>:
name: "win_FS"
id: my_widget
BoxLayout:
orientation: "vertical"
size: root.width, root.height
padding: 50
spacing: 20
Label:
text:'Please select the file...'
size_hint: ( 1, 0.1)
font_size: 20
FileChooserListView:
id: filechooser
path: "."
on_selection:
my_widget.selected(filechooser.selection)
Button:
text:'OK'
font_size: 20
size_hint: ( 1, 0.1)
on_release:
app.root.current = "win_Main"
root.manager.transition.direction = "down"
root.transform_to_main()
""")
Window.size = (700, 280)
Window.top = 50
Window.left = 100
class MyApp(App):
def build(self):
self.title = "Data Importer"
return kv
if __name__ == '__main__':
MyApp().run()
You just need to access the right screen and its contents. One of the many ways would be using the method get_screen as follows,
def selected(self, filename):
try:
# Access the target screen.
main_screen = self.manager.get_screen("win_Main")
# Access its target label.
file_path_label = main_screen.ids.lbl_file_path_k
# Set the text.
file_path_label.text = filename[0]
print(filename[0])
# global f_path
f_path = filename[0]
except:
pass
Other ways include binding directly from FileChooserListView, defining custom variable in that class or in the App's class etc.

how can i create a table in python kivy

I'm writing a python program to compute few values in two textinput, but The Result should be in a table ... I created it as a label but it doesn't practical.
how can i create a table !
Thank you very much
from kivy.lang import Builder
from kivy.uix.label import Label
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.textinput import TextInput
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.clock import Clock
Window.clearcolor = (0.5, 0.5, 0.5, 1)
class WindowManager(ScreenManager):
pass
class BestWindow(Screen):
my_result = StringProperty("")
inpt_one = ObjectProperty(None)
result_layout = ObjectProperty(None)
result_layout1 = ObjectProperty(None)
result_layout2 = ObjectProperty(None)
result_layout5 = ObjectProperty(None)
test3 = ObjectProperty(None)
def __init__(self, **kwargs):
super(BestWindow, self).__init__(**kwargs)
Window.bind(on_key_down=self._on_keyboard_down)
def _on_keyboard_down(self, instance, keyboard, keycode, text, modifiers):
if self.test3.focus and keyboard== 13: # 32 - Cpace key presssed Ascii
self.calculate()
def calculate(self):
self.result_layout.clear_widgets()
self.result_layout1.clear_widgets()
nums_one = self.inpt_one.text.strip().split(" ")
nums_two = self.inpt_two.text.strip().split(" ")
if(len(nums_one) < len(nums_two)):
for _ in range(len(nums_two)-len(nums_one)):
nums_one.append(0)
elif(len(nums_two) < len(nums_one)):
for _ in range(len(nums_one)-len(nums_two)):
nums_two.append(0)
result = [(int(x) + int(y)) for x,y in zip(nums_one, nums_two) ]
aList = []
for f in range(len(nums_one)):
aList.append(f)
self.ids.result_layout5.add_widget(Label(text='Num: {} '.format(f)))
bList = []
for i in range(len(nums_one)):
self.ids.result_layout1.add_widget(Label(text='1.Gas: %{} '.format(nums_one[i])))
bList.append(i)
cList = []
for j in range(len(nums_two)):
bList.append(j)
self.ids.result_layout2.add_widget(Label(text='2.Gas: %{} '.format(nums_two[j])))
dList = []
for res in result:
res = int(res)
dList.append(res)
self.ids.result_layout.add_widget(Label(text='Sum: %{} '.format(res)))
self.inpt_one.text = ''
self.inpt_two.text = ''
kv = Builder.load_file("MyMain.kv")
class TestApp(App):
def build(self):
b1 = WindowManager()
return b1
if __name__ == "__main__":
TestApp().run()
the user should enter the first value in the first box and then space then the second value and so on.
then he presses enter .. and can then continue first value in second box space then the second value.
MyMain.kv file
<CustButton#Button>:
font_size: 40
<WindowManager>:
BestWindow:
<BestWindow>:
name: "erst"
inpt_one: inpt_one
inpt_two: inpt_two
result_layout: result_layout
result_layout1:result_layout1
result_layout2:result_layout2
result_layout5:result_layout5
test3: test3
GridLayout:
spacing: 10
cols:1
Label:
text: "das Gas 1"
background_color: 1, 0, 0, 1
TextInput:
id:inpt_one
focus : True
text: ' '
width: 100
multiline: False
on_text_validate: inpt_two.focus = True
Label:
text: "das Gas 2"
background_color: 1, 0, 0, 1
TextInput:
id:inpt_two
focus : True
text: ' '
width: 100
multiline: False
on_text_validate:
test3.background_normal = ''
test3.background_color = [0, 0, 1, 0.5] # 50% translucent blue
test3.focus = True
Button:
id : test3
focus: False
text: "Table!"
on_press:
root.calculate()
BoxLayout:
orientation: "horizontal"
BoxLayout:
id: result_layout5
orientation: "horizontal"
BoxLayout:
orientation: "horizontal"
BoxLayout:
id: result_layout1
orientation: "horizontal"
BoxLayout:
orientation: "horizontal"
BoxLayout:
id: result_layout2
orientation: "horizontal"
BoxLayout:
orientation: "horizontal"
BoxLayout:
id: result_layout
orientation: "horizontal"
Yes tables are a bit clunky. Although I'm not sure if you need all those box layouts, isn't the grid layout sufficient? But otherwise, a quick and easy table can be made on a single Label widget with formatted strings and a mono-spaced font, because Label does process \n for new line. The only awkwardness is that Label doesn't likewise support \t for tab spacing between the columns, so the \t escapes have to be rendered in advance in python. This can be done with expandtabs string method.
Label(text='l1c1\tl1c2\nll2c1\tll2c2'.expandtabs(8),font_name='UbuntuMono-R')

Python/Kivy : Remove space using python

I am using python-2.7 and kivy. I am trying to hide TextInput with blank space.
At this time i am using opacity property for hiding Textinput
self.row.abc.opacity = 0
Using this code TextInput is hiding but blank space not removed. Can someone tell me how to remove blank space or another better solution for hiding Textinput with blank space.
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty, StringProperty, ObjectProperty
Window.size = (450, 425)
class display(Screen):
def __init__(self, **kwargs):
super(display, self).__init__(**kwargs)
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
id = ObjectProperty(None)
col_data = ListProperty(["", ""])
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.row = Row(button_text=str(self.row_count))
self.row.abc.opacity = 0
self.row.col_data[1] = 'Test1'
self.add_widget(self.row)
class test(App):
def build(self):
return self.root
if __name__ == '__main__':
test().run()
test.kv
<Row>:
abc: abc
#state1 : state1
orientation: "horizontal"
spacing: 0, 5
Button:
text: root.button_text
size_hint_x: .2
TextInput:
id : abc
size_hint_x: .8
text : root.col_data[0]
TextInput:
size_hint_x: .8
text : root.col_data[1]
display:
BoxLayout:
orientation: "vertical"
padding : 20, 20
BoxLayout:
orientation: "horizontal"
Button:
size_hint_x: .2
text: "+Add More"
valign: 'bottom'
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
Label:
size_hint_x: .2
text: "SN"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value1"
valign: 'bottom'
Label:
size_hint_x: .8
text: "Value2"
valign: 'bottom'
Rows:
id: rows

Kivy Removing elements from a Stack- / GridLayout

I made a pop-up. It is basically some rows of options (max. 5 rows).
If I press the '+' button, there will be a new line of options.
If I press the '-' button the last row should diasappear. Unfortunatelly it doesn't.
I tried already the followings out in root.remove():
--> widget_path.pop(0) :
no visual change, I see n rows instead of n-1 .
--> widget_path.pop() :
It removes the first line instead of the last one.
--> Gridlayout (cols: 4) instead of StackLayout: similar results
Could you help me?
Here is my code:
.kv -file;
<FormPopup>:
size_hint: None, None
size: '361pt', '220pt'
BoxLayout:
orientation: 'vertical'
BoxLayout:
size_hint: 1, None
height: '20pt'
orientation: 'horizontal'
Label:
text: 'column1'
Label:
text: 'column2'
Label:
text: 'column3'
Label:
text: 'column4'
# list of sensors
StackLayout:
padding: 0
spacing: 1
orientation: 'lr-tb'
pos_hint: {'center_x': .5, 'center_y': .5}
height: self.minimum_height
id: measure_stack
BoxLayout:
orientation: 'horizontal'
MyButton:
text: '+'
on_release: root.add()
MyButton:
text: '-'
on_release: root.remove()
my .py class:
class FormPopup(Popup):
"""Class: Popup for comments"""
def __init__(self):
super().__init__()
self.error = 0
self.linenumber = 0
self.add()
def add(self):
"""add a new option-line"""
widget_path = self.ids
if self.linenumber < 5 :
sensor_id = 'sensor_' + str(self.linenumber)
widget_path['measure_stack'].add_widget(Spinner(id = sensor_id, size_hint=(None,None), height='20pt', width='85pt', text = '---', values= ('A','B','C') ))
measurand_id = 'measurand_' + str(self.linenumber)
widget_path['measure_stack'].add_widget(Spinner(id = measurand_id, size_hint=(None,None), height='20pt', width='85pt', text = '---', values= ('A','B','C') ) )
branchwise_id = 'branchwise_' + str(self.linenumber)
widget_path['measure_stack'].add_widget(Spinner(id = branchwise_id, size_hint=(None,None), height='20pt', width='85pt', text = '---', values= ('A','B','C')))
procedure_id = 'procedure_' + str(self.linenumber)
widget_path['measure_stack'].add_widget(Spinner(id = procedure_id, size_hint=(None,None), height='20pt', width='85pt', text = '---', values= ('A','B','C')))
self.linenumber += 1
def remove(self):
"""remove one option-line"""
widget_path = self.ids.measure_stack.children
# do not remove if there is only one line
if len(widget_path) > 4:
self.linenumber -= 1
for i in range(4):
widget_path.pop(0)
Get the widget, and remove it.
An example of that:
from kivy.app import App
from kivy.lang import Builder
root = Builder.load_string('''
BoxLayout:
GridLayout:
id: grid
cols: 1
rows: 5
Label:
text: "label 1"
Label:
text: "label 2"
Label:
text: "label 3"
Label:
text: "label 4"
Button:
text: "Remove last item"
on_release: grid.remove_widget(grid.children[0])
''')
class MyApp(App):
def build(self):
return root
MyApp().run()

Categories

Resources