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()