Kivy copy button text to clipboard - python

This is my first Kivy app, surprisingly there wasn't the usual amount of documentation on copy/paste button text with the clipboard which I assume because it is simple, however I get a traceback saying ValueError embedded null character.
I thought that it was because the button produces text of recently hashed text and it still was contained in a byte string, but when decoding it acts if its already decoded and states string doesn't have a decode attribute. I apologize in advance for any "playing" in my code and if the answer has been staring at me
kivy clipboard doc:
https://kivy.org/docs/api-kivy.core.clipboard.html#
** Update
I believe I found the issue, regardless of the data type that is passed to the clipboard function there is a Value error, I took a look at the kivy file for the clipboard "clipboard_winctypes.py" and under the put() function the function msvcrt.wcscpy_s() is called. When this is commented out the clipboard will copy the button text however, I receive weird things like ⫐ᵄƅ
also under the put() function where text is set to text += u'x00', if this is commented out and msvcrt.wscpy_s() is left uncommented to be called it executes without error but nothing is copied to the clipboard however msvcrt is an object of ctypes.cdll.msvcrt and I don't where to go from here
clipboard_winctypes.py:
'''
Clipboard windows: an implementation of the Clipboard using ctypes.
'''
__all__ = ('ClipboardWindows', )
from kivy.utils import platform
from kivy.core.clipboard import ClipboardBase
if platform != 'win':
raise SystemError('unsupported platform for Windows clipboard')
import ctypes
from ctypes import wintypes
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32
msvcrt = ctypes.cdll.msvcrt
c_char_p = ctypes.c_char_p
c_wchar_p = ctypes.c_wchar_p
class ClipboardWindows(ClipboardBase):
def get(self, mimetype='text/plain'):
GetClipboardData = user32.GetClipboardData
GetClipboardData.argtypes = [wintypes.UINT]
GetClipboardData.restype = wintypes.HANDLE
user32.OpenClipboard(user32.GetActiveWindow())
# 1 is CF_TEXT
pcontents = GetClipboardData(13)
if not pcontents:
return ''
data = c_wchar_p(pcontents).value.encode(self._encoding)
user32.CloseClipboard()
return data
def put(self, text, mimetype='text/plain'):
text = text.decode(self._encoding) # auto converted later
text += u'\x00'
SetClipboardData = user32.SetClipboardData
SetClipboardData.argtypes = [wintypes.UINT, wintypes.HANDLE]
SetClipboardData.restype = wintypes.HANDLE
GlobalAlloc = kernel32.GlobalAlloc
GlobalAlloc.argtypes = [wintypes.UINT, ctypes.c_size_t]
GlobalAlloc.restype = wintypes.HGLOBAL
CF_UNICODETEXT = 13
user32.OpenClipboard(user32.GetActiveWindow())
user32.EmptyClipboard()
hCd = GlobalAlloc(0, len(text) * ctypes.sizeof(ctypes.c_wchar))
msvcrt.wcscpy_s(c_wchar_p(hCd), len(text), c_wchar_p(text))
SetClipboardData(CF_UNICODETEXT, hCd)
user32.CloseClipboard()
def get_types(self):
return ['text/plain']
cry_hash.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.label import Label
import hashlib
class Hasher:
def __init__(self, to_hash, hash_alg, hash_length):
if to_hash != type(bytes):
self.to_hash = bytes(to_hash, encoding='utf-8')
else:
self.to_hash = to_hash
self.hash_alg = hash_alg
self.hash_length = int(hash_length)
def create_hash(self):
hash_object = hashlib.new(self.hash_alg)
hash_object.update(self.to_hash)
result = hash_object.hexdigest()[:self.hash_length]
del hash_object
return result
class LabelBackground(Label):
pass
class CryHashWidgetBoxLayout(BoxLayout):
def get_hash(self, user_hash, hash_length):
tb = next((t for t in ToggleButton.get_widgets('hash_type') if t.state == 'down'), None)
hash_alg = tb.text if tb else None
krypt_tool = Hasher(user_hash, hash_alg, hash_length)
hashed_input = krypt_tool.create_hash()
self.ids.hash_return.text = hashed_input
def reset(self, text_reset):
incoming = text_reset
del incoming
incoming = ''
self.ids.hash_return.text = incoming
class CryHashApp(App):
def build(self):
return CryHashWidgetBoxLayout()
if __name__ == '__main__':
CryHashApp().run()
KV file: cryhash.kv
#File name: cry_hash.py
#:import utils kivy.utils
#:import Clipboard kivy.core.clipboard.Clipboard
<ToggleButton>:
background_color: utils.get_color_from_hex('#E00000')
<TextInput>:
background_color: utils.get_color_from_hex('#5F9B9F')
<Label>
font_name: 'fonts/arialbd.ttf'
<CryHashWidgetBoxLayout>:
orientation: 'vertical'
Label:
font_name: 'fonts/welga.ttf'
color: utils.get_color_from_hex('#E00000')
text: 'Welcome to Cry Hash!'
font_size: 80
Button:
id: hash_return
background_color: utils.get_color_from_hex('#F15E92')
font_size: 40
text: ''
on_release:
Clipboard.copy(hash_return.text)
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'vertical'
Label:
id: bg_hash
color: utils.get_color_from_hex('#E00000')
text: 'Enter text to hash'
TextInput:
id: user_hash
multiline: False
text: ''
Label:
id: bg_length
color: utils.get_color_from_hex('#E00000')
text: 'Enter length'
TextInput:
id: get_hash_length
multiline: False
text: '10'
Button:
id: get_data
background_color: utils.get_color_from_hex('#1900FF')
text: 'get hash!'
on_release: root.get_hash(user_hash.text, get_hash_length.text)
BoxLayout:
orientation: 'vertical'
ToggleButton:
id: SHA256
text: 'SHA256'
state: 'down'
group: 'hash_type'
ToggleButton:
id: SHA512
text: 'SHA512'
group: 'hash_type'
ToggleButton:
id: SHA1
text: 'SHA1'
group: 'hash_type'
ToggleButton:
id: MD5
text: 'MD5'
group: 'hash_type'

To summarize other answers:
Issue:
"ValueError: embedded null character" when using copy to clipboard (Kivy)
Solution:
pip install pyperclip
pyperclip.copy('text that you want into clipboard')

I have found a work around, I believe that is just simply a bug in the Kivy framework, if someone can find a true solution in the kivy code please let me know, otherwise I simply imported pyperclip, created a pyperclip copy function in the .py file and called to the function in the .kv file. Works flawlessly!
cry_hash.py:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.label import Label
import hashlib
import pyperclip
class Hasher:
def __init__(self, to_hash, hash_alg, hash_length):
if to_hash != type(bytes):
self.to_hash = bytes(to_hash, encoding='utf-8')
else:
self.to_hash = to_hash
self.hash_alg = hash_alg
self.hash_length = int(hash_length)
def create_hash(self):
hash_object = hashlib.new(self.hash_alg)
hash_object.update(self.to_hash)
result = hash_object.hexdigest()[:self.hash_length]
del hash_object
return result
class LabelBackground(Label):
pass
class CryHashWidgetBoxLayout(BoxLayout):
def get_hash(self, user_hash, hash_length):
tb = next((t for t in ToggleButton.get_widgets('hash_type') if t.state == 'down'), None)
hash_alg = tb.text if tb else None
krypt_tool = Hasher(user_hash, hash_alg, hash_length)
hashed_input = krypt_tool.create_hash()
self.ids.hash_return.text = str(hashed_input)
def reset(self, text_reset):
incoming = text_reset
del incoming
incoming = ''
self.ids.hash_return.text = incoming
def copy_text(self, text):
pyperclip.copy(text)
class CryHashApp(App):
def build(self):
return CryHashWidgetBoxLayout()
if __name__ == '__main__':
CryHashApp().run()
cryhash.kv:
#File name: cry_hash.py
#:import utils kivy.utils
#:import Clipboard kivy.core.clipboard.Clipboard
<ToggleButton>:
background_color: utils.get_color_from_hex('#E00000')
<TextInput>:
background_color: utils.get_color_from_hex('#5F9B9F')
<Label>
font_name: 'fonts/arialbd.ttf'
<CryHashWidgetBoxLayout>:
orientation: 'vertical'
Label:
font_name: 'fonts/welga.ttf'
color: utils.get_color_from_hex('#E00000')
text: 'Welcome to Cry Hash!'
font_size: 80
Button:
id: hash_return
background_color: utils.get_color_from_hex('#F15E92')
font_size: 40
text: ''
on_release: root.copy_text(hash_return.text)
BoxLayout:
orientation: 'horizontal'
BoxLayout:
orientation: 'vertical'
Label:
id: bg_hash
color: utils.get_color_from_hex('#E00000')
text: 'Enter text to hash'
TextInput:
id: user_hash
multiline: False
text: ''
Label:
id: bg_length
color: utils.get_color_from_hex('#E00000')
text: 'Enter length'
TextInput:
id: get_hash_length
multiline: False
text: '10'
Button:
id: get_data
background_color: utils.get_color_from_hex('#1900FF')
text: 'get hash!'
on_release: root.get_hash(user_hash.text, get_hash_length.text)
BoxLayout:
orientation: 'vertical'
ToggleButton:
id: SHA256
text: 'SHA256'
state: 'down'
group: 'hash_type'
ToggleButton:
id: SHA512
text: 'SHA512'
group: 'hash_type'
ToggleButton:
id: SHA1
text: 'SHA1'
group: 'hash_type'
ToggleButton:
id: MD5
text: 'MD5'
group: 'hash_type'

Related

KivyMD sharing variables/data through Screens

I'm currently building a small program that converts an Excel sheet into a JSON format. I want that every time a change or update is made, the excel file gets updated with a Login and Date information of the person who made the change.
I have created Two screens using KivyMD, one for the login data and another one for the excel functionality. My current issue is that I want to acquire the login information from the previous screen, but I'm having a hard time understanding how to get the data.
I have tried to create a "login" variable within my "Update" screen referencing the id from the "Log" screen by using this line I found on a previous post: "login = self.manager.screens[1].ids.login.text"
But that line is giving me the following error : "
login = self.manager.screens[1].ids.login.text
File "kivy\properties.pyx", line 863, in kivy.properties.ObservableDict.getattr
AttributeError: 'super' object has no attribute 'getattr'
"
I'm very new to KivyMD and I'm pretty sure that there is something over here that I'm not seeing or just missing. I would appreciate any help given.
Here is my .py file:
import os.path
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.lang import Builder
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from helpers import screen_helper_2
from kivy.core.window import Window
from datetime import datetime
import json
import functions as function
Window.size = (400, 500)
# AlbacoreLog Screen Fully Functional
class AlbacoreLogScreen(Screen):
def show_login(self, *args):
close_button = MDFlatButton(text='Close', on_release=self.close_dialog)
if self.ids.login.text is "":
check_string = 'Please enter Login or Name'
self.dialog = MDDialog(text=check_string,
size_hint=(0.7, 1),
buttons=[close_button])
self.dialog.open()
else:
self.manager.current = 'function'
def close_dialog(self, obj):
self.dialog.dismiss()
class AutoUpdateScreen(Screen):
def albacorize_update(self, *args):
def close_ext(*args):
dialog_ext.dismiss()
def close_ext_2(*args):
dialog_5.dismiss()
def close_update(*args):
dialog_update.dismiss()
close_button_ext_2 = MDFlatButton(text='Close', on_release=close_ext_2)
close_button_ext = MDFlatButton(text='Close', on_release=close_ext)
close_button_update = MDFlatButton(text='Close', on_release=close_update)
if self.ids.change.text is "":
dialog_update = MDDialog(text='Also, make sure to add your update',
size_hint=(0.7, 1),
buttons=[close_button_update])
dialog_update.open()
self.back_to_update()
if self.ids.ms.text is "":
dialog_ext = MDDialog(text='Please enter Master Sheet name and extension',
size_hint=(0.7, 1),
buttons=[close_button_ext])
dialog_ext.open()
self.back_to_update()
elif type(self.ids.ms.text) is str:
ms = self.ids.ms.text
update = self.ids.change.text
if os.path.isfile(ms):
login = self.manager.screens[1].ids.login.text
now = datetime.now()
time_date = now.strftime("%d/%m/%Y %H:%M:%S")
print("File exist")
q_and_a_section = function.question_answer_build(ms)
node_section = function.section_build(ms)
function.updates(ms, login, time_date, update) ##I want to pass the login data to a different module on my program in order to build the new excel sheet.
else:
print("File not exist")
dialog_5 = MDDialog(text='MS does not have extension or is not in current root folder',
size_hint=(0.7, 1),
buttons=[close_button_ext_2])
dialog_5.open()
self.manager.current = 'msautomap'
def back_to_function(self, *args):
self.manager.current = 'function'
def back_to_update(self, *args):
self.manager.current = 'msautoupdate'
sm = ScreenManager()
sm.add_widget(AlbacoreLogScreen(name='log'))
sm.add_widget(AutoUpdateScreen(name='msautoupdate'))
class AlbacorizerApp(MDApp):
def build(self):
self.theme_cls.primary_palette = "Yellow"
self.theme_cls.primary_hue = "A700"
self.theme_cls.theme_style = "Dark"
screen = Builder.load_string(screen_helper_2)
return screen
AlbacorizerApp().run()
And here is my .kv file:
screen_helper_2 = """
Screen:
NavigationLayout:
ScreenManager:
AlbacoreLogScreen:
AutoUpdateScreen:
<AlbacoreLogScreen>:
name: 'log'
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: 'Albacorizer Log'
left_action_items: [["lighthouse", lambda x: nav_drawer.toggle_nav_drawer()]]
elevation: 10
Widget:
MDTextField:
id: login
hint_text: "Enter login"
helper_text: "or enter name"
helper_text_mode: "on_focus"
icon_right: "lighthouse-on"
icon_right_color: app.theme_cls.primary_color
pos_hint:{'center_x':0.5, 'center_y':0.7}
size_hint_x: None
size_hint_y: None
width: 300
MDRectangleFlatButton:
text: 'Go !'
pos_hint: {'center_x':0.5,'center_y':0.4}
on_release:
root.show_login()
Widget:
<AutoUpdateScreen>:
name: 'msautoupdate'
BoxLayout:
orientation: 'vertical'
MDToolbar:
title: 'MS Automap Update'
left_action_items: [["lighthouse", lambda x: nav_drawer.toggle_nav_drawer()]]
elevation: 10
Widget:
MDTextField:
id: ms
hint_text: "What is the MS name and extension?"
helper_text: "don't forget the extension"
helper_text_mode: "on_focus"
icon_right: "lighthouse-on"
icon_right_color: app.theme_cls.primary_color
pos_hint:{'center_x': 0.5, 'center_y': 0.5}
size_hint_x: None
width: 300
MDTextFieldRect:
id: change
hint_text: "Summary of changes to MS"
mode: "rectangle"
pos_hint:{'center_x': 0.5, 'center_y': 0.5}
size_hint_x: None
width: 200
height: "100dp"
Widget:
MDRectangleFlatButton:
text: 'Albacorize !'
pos_hint: {'center_x':0.5,'center_y':0.2}
on_release:
root.albacorize_update()
Widget:
MDRectangleFlatButton:
text: 'Back'
pos_hint: {'center_x':0.5,'center_y':0.3}
on_release:
root.back_to_function()
root.manager.transition.direction = 'right'
Widget:
"""
Try changing:
login = self.manager.screens[1].ids.login.text
to:
login = self.manager.get_screen('log').ids.login.text
Using self.manager.screens[1] makes your code depend on the order of Screens in the screens list (and [1] is the wrong one). Using get_screen('log') makes your code independent of the order of the Screens (and gets the correct one).

Kivy updating label when using function via button fails

I'm trying to build an App thats uses certain input Parameters and when hitting a submit button it uses a logic to generate output paramters. I managed to build the app and the input and the triggering via a submit button. Now i want to generate the output, for beginning with an easy logic. I looked up several similar solutions, but somehow they don't work for me.
For some reason my .kv file doen't get the updated value for the label text with the error: "ValueError: Label.text accept only str" Eventough everything is declared as a string in the .py. If i change it in the kv to str("...") I get some code line which i guess is the intern id of the attribute but not the assigned value i want to get.
I hope you can help. Pls don't be too harsh, I#M new to python and kivy...
main .py, shuldn't be part of the problem
Peenomat.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.core.text import LabelBase
Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')
#Layout
class Peenomat(AnchorLayout):
pass
class PeenomatApp(App):
def build(self):
return Peenomat()
if __name__=="__main__":
PeenomatApp().run()
.py with the classes and methods for the logic
StatusBar.py
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.app import App
class InputParameters(GridLayout):
verfahren = ObjectProperty(None)
def on_state(self, togglebutton):
tb = togglebutton
if tb.state == 'down':
self.verfahren = tb.text
self.verfahren = tb.text
print(self.verfahren)
return self.verfahren
class StatusBar(BoxLayout):
#InputGrößen
group_mode = False
prozess = ObjectProperty(None)
vorbehandlung = ObjectProperty(None)
material = ObjectProperty(None)
haerte = ObjectProperty(None)
rauheit = ObjectProperty(None)
#OutputGrößen
frequenz = StringProperty(None)
def btn_submit(self):
ip = App.get_running_app().root.ids._input_parameters
print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text, "Vorbehandlung:", ip.vorbehandlung.text)
if ip.haerte.value < 50:
self.frequency = str(180)
elif ip.haerte.value < 60:
self.frequency = str(200)
else:
self.frequency = str(220)
#control to see if right value is taken
print(self.frequency, "Hz")
def btn_clear(self):
np = App.get_running_app().root.ids._input_parameters
np.pro1.state = "normal"
np.pro2.state = "normal"
np.pro3.state = "normal"
np.material.text = "Auswahl treffen"
np.haerte.value = 55
np.rauheit.value = 5.5
the .kv file that can't get the label text:
outputparameters.kv
#: import statusbar StatusBar
<OutputParameters#GridLayout>
#Initialisierung .py zu .kv
frequenz: _frequenz
Label:
text:'Frequenz:'
font_size:
Label:
id: _frequenz
text: root.frequenz
font_size: 20
the .kv file with the submit button, shouldn't be part of the problem either, worked perfectly fine before implementing the part ehre i try to update the text
statusbar.kv
#: import statusbar StatusBar
<StatusBar#BoxLayout>
orientation:'horizontal'
Button:
text: 'Clear'
on_press: root.btn_clear()
Button:
text: 'Submit'
on_press: root.btn_submit()
the file where i put in all the inputparameters, rather important:
Inputparameters.kv
#: import statusbar StatusBar
<InputParameters#GridLayout>
#Initialisierung .py zu .kv Ids
prozess: _prozess
pro1: _prozess1
pro2: _prozess2
pro3: _prozess3
vorbehandlung: _vorbehandlung
material: _material
haerte: _haerte
rauheit: _rauheit
#Prozess
Label:
text:'Prozess:
BoxLayout:
orientation: 'horizontal'
id: _prozess
ToggleButton:
id:_prozess1
text:'P-MOH'
group: "proc_group"
on_state: root.on_state(self)
ToggleButton:
id:_prozess2
text:'E-MOH'
group: "proc_group"
on_state: root.on_state(self)
ToggleButton:
id:_prozess3
text:'PE-MOH'
group: "proc_group"
on_state: root.on_state(self)
#Material
Label:
text: 'Material:'
Spinner:
id: _material
text: ""
values:
# Herstellschritte
Label:
text:'Fertigungsschritte:'
Spinner:
id: _vorbehandlung
text:
values:
# Haerte
Label:
text:'Haerte:'
BoxLayout:
orientation: 'vertical'
Label:
text: str(_haerte.value)
Slider:
id: _haerte
# Rauheit
Label:
text:'Rauheit:
BoxLayout:
orientation: 'vertical'
Label:
text:
Slider:
id: _rauheit
and the file where my layout is embedded (also rather necessary)
peenomat.kv
<Peenomat>
AnchorLayout:
anchor_x: 'left'
anchor_y: 'bottom'
GridLayout:
cols: 1
canvas.before:
Color:
Rectangle:
pos: self.pos
size: self.size
InputParameters:
id:_input_parameters
StatusBar:
id:_status_bar
OutputParameters:
id:_output_parameters
I really hope you can help, have been struggeling with this for a while and it should rather be easy...thanks in advance!
In your kv rule for <OutputParameters#GridLayout> you have a line:
frequenz: _frequenz
which sets frequenz to be a reference to the Label with the id of _frequenz. Then in that Label you are setting text using:
text: root.frequenz
So, you are trying to set the text of the Label to a reference to that Label
I suggest trying something like this:
<OutputParameters#GridLayout>
#Initialisierung .py zu .kv
frequenz: _frequenz
frequency: ''
And change the Label to:
Label:
id: _frequenz
text: root.frequency
font_size: 20
But to actually change the value shown in the label, you will need a reference to the instance of OutputParameters, using something like:
App.get_running_app().root.ids._output_parameters.frequency = str(500)

kivy for python: communication between popup and previous page

Once again fiddling with kivy and encountering problems.
How do I communicate a variable (the text from a spinner) into a popup's button (it has two and has to be custom made) OR communicate said variable to another page? I need this to run a song on a piano, the other scripts are mostly all done and working.
Thanks in advance, here is the popup's code:
<Custpopup#Popup>:
size_hint: .8, .8
auto_dismiss: False
title: 'Play me a song'
BoxLayout:
spacing: 10
Button:
id: play
text: 'Play'
on_press:
# what to do here?
Button:
id: close
text: 'Close popup'
on_press:
root.dismiss()
print('closed')
Edit: Smallest reproducible example here: https://pastebin.com/y7sW8ByH
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.app import App
from os import listdir
DEBUG = False
Builder.load_string('''
<Custpopup#Popup>:
size_hint: .7, .6
auto_dismiss: False
title: 'Play me a song'
BoxLayout:
spacing: 10
Button:
id: play
text: 'Play'
on_press:
# what to do here?
Button:
id: close
text: 'Close popup'
on_press:
root.dismiss()
print('closed')
<JukeBoxMode>:
name: 'juke'
id: jukebox
FloatLayout:
id: layout
Button:
id: back
text: 'Return'
size_hint: None, None
size: 150, 44
pos: 0, layout.height - self.height
on_press: print('Pressed RETURN button')
on_release:
print(app.root.current)
Spinner:
id: spin
size_hint: None, None
size: 400, 44
pos: (layout.center_x - self.width/2, layout.height - self.height)
text: 'Music'
values: root.musicList
on_text:
root.selMus(self.text)
''')
class CustPopup(Popup):
pass
class JukeBoxMode(Screen):
musicList = []
musdir = r'/home/pi/Desktop/Music21/midi/'
muslist = listdir(musdir)
for file in muslist:
if file.endswith('.mid'):
musicList.append(file[:-4])
if DEBUG:
print(musicList)
musicList.sort()
if DEBUG:
print(musicList)
def selMus(self,sel):
custpop = CustPopup()
if sel != 'Music':
custpop.open()
def playPiano(self):
dicmusic = {self.musicList.index(self.ids['spin'].text): self.ids['spin'].text}
if DEBUG:
print(dicmusic)
song, fin, instr, seq = infoMorceau(dicmusic[0])
print(song, fin, instr, seq)
class HudPianoApp(App):
def build(self):
return JukeBoxMode()
if __name__ == '__main__':
HudPianoApp().run()
Not sure exactly what you want to do, but modifyingyour selMus() method to use the sel in your CustPopup might help:
def selMus(self,sel):
print(sel)
custpop = CustPopup()
if sel != 'Music':
# Use 'sel' in the Popup
custpop.ids.play.text = 'Play ' + sel
custpop.ids.play.on_release = partial(self.do_something, sel)
custpop.open()
def do_something(self, sel):
# Do whatever you want with `sel` here
print('do something with', sel)

Button to print the the Text Input is not working

The whole code is working well. But when u go to:
student > Add New student > > Fill all columns of new student > then submit
it's not working and I can't figure out the issue. Here is the following code. Any help will be appreciated
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen ,FadeTransition
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
import csv
from kivy.uix.textinput import TextInput
Builder.load_string("""
<MenuScreen>:
BoxLayout:
Button:
text: 'Teacher'
on_press: root.manager.current = 'screen1'
Button:
text: 'Student '
on_press:root.manager.current = 'screen2'
Button:
text: 'Quit'
<Screen1>:
BoxLayout:
Button:
text: 'Teacher Info'
#on_press:root.manager.current = 'login'
Button:
text: 'Teacher Attandance'
Button:
text: 'Add New Teacher'
on_press:root.manager.current = 'add_teacher'
Button:
text: 'Back'
on_press:root.manager.current ='menu'
<add_new_teacher>:
GridLayout:
cols:2
Label:
text:'Name'
TextInput:
id: name_input
multiline: False
Label:
text:'Father Name'
TextInput:
id: name_input
multiline: False
Label:
text: 'Mother Name'
TextInput:
id: name_input
multiline: False
Label:
text: 'Class'
TextInput:
id: name_input
multine: False
Label:
text:'Roll no.'
text: 'Student Info'
on_press:root.csv_std()
Button:
text: 'Student Attandance'
# on_press:root.manager.current ='login'
Button:
text: 'Add New Student'
on_press:root.manager.current = 'add_student'
Button
text: 'Back'
on_press:root.manager.current = 'menu'
<add_new_student>:
GridLayout:
cols:2
Label:
text:'Name'
TextInput:
id: self.name
multiline: False
Label:
text:'Father Name'
TextInput:
id: self.fname
multiline: False
Label:
text: 'Mother Name'
TextInput:
id: self.mname
multiline: False
Label:
text: 'Class'
TextInput:
id: self.c
multine: False
Label:
text:'Roll no.'
TextInput:
id: self.r
multiline:False
Button:
text:'Print'
Button:
text:'Submit'
on_press:root.print_text()
Button:
text:'Back'
on_press:root.manager.current= 'screen2'
""")
# Declare both screens
class MenuScreen(Screen):
pass
class add_new_teacher(Screen):
pass
class Screen1(Screen):
pass
class Screen2(Screen):
def csv_std(self):
f = open("a.csv", 'r')
reader = csv.reader(f)
for row in reader:
print(" ".join(row))
pass
class add_new_student(Screen):
def print_text(self):
for child in reversed(self.children):
if isinstance(child, TextInput):
print child.text
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(add_new_teacher(name='add_teacher'))
sm.add_widget(add_new_student(name='add_student'))
sm.add_widget(Screen1(name='screen1'))
sm.add_widget(Screen2(name='screen2'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
You code formatting was horrible, but at least you didn't use backticks. For future cases, copy&paste your whole example you want to show here, then select that example(whole) and press Ctrl + K, which will indent all selected lines, so that it'd look ok.
The code works exactly how it supposed to work, because root.print_text() targets add_new_student class and its children - not GridLayout which you want to access.
Edit the line with for to this: for child in reversed(self.children[0].children): and you are good to go. :)
Or more efficient solution would be to get that Screen to behave as a layout too, which you can get with inheritting both from Screen and some layout, but ensure the layout is first:
class add_new_student(GridLayout, Screen):
def print_text(self):
for child in reversed(self.children):
if isinstance(child, TextInput):
print child.text
kv:
<add_new_student>:
cols:2
Label:
text:'Name'

Showing widget before SOAP connection

Problem is in LoginForm.log_in() (code below)
I would like in that order:
clear widgets
show MenuWindow widget
connect via SOAP.
Unfortunately I can't. I don't know why but my app first tries to connect to SOAP server and then cleans widget tree and creates new.
main.py:
# coding=utf-8
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.factory import Factory
from kivy.storage.jsonstore import JsonStore
from suds.client import Client
import sys
import os
import time, threading
class LoginForm(BoxLayout):
login_input = ObjectProperty()
password_input = ObjectProperty()
def log_in(self):
self.clear_widgets()
menu = Factory.MenuWindow()
self.add_widget(menu)
MenuWindow.change_caption(MenuWindow)
def show_settings(self):
self.clear_widgets()
pokaz = Factory.SettingsWindow()
self.add_widget(pokaz)
def set_written_data_ip():
store = JsonStore('anakonda_mobile.json')
if store.exists('Adres'):
print(store.get('Adres'))
if store.get('Adres')['ip'].strip() != '':
return store.get('Adres')['ip']
else:
return ''
def set_written_data_port():
store = JsonStore('anakonda_mobile.json')
if store.exists('Adres'):
if store.get('Adres')['port'].strip() != '':
return store.get('Adres')['port']
else:
return ''
class SettingsWindow(BoxLayout):
ip_value = ObjectProperty(set_written_data_ip())
port_value = ObjectProperty(set_written_data_port())
def show_logging(self):
self.clear_widgets()
self.add_widget(LoginForm())
def save_ip_port(self):
store = JsonStore('anakonda_mobile.json')
store.put('Adres', ip=self.ip_input.text, port=self.port_input.text)
python = sys.executable
os.execl(python, python, *sys.argv)
class MenuWindow(BoxLayout):
def soap_connect(self):
try:
self.a = Client('http://192.168.1.1:7789/ASOAPService?wsdl')
except Exception as g:
return ''
def change_caption(self):
self.soap_connect(self)
return 'SOAP connected'
class MobileApp(App):
pass
if __name__ == '__main__':
MobileApp().run()
mobile.kv
LoginForm:
<LoginForm>:
login_input: _login
password_input: _password
orientation: "vertical"
BoxLayout:
height: "40dp"
size_hint_y: None
Label:
text: 'Login: '
TextInput:
focus: True
multiline: False
id: _login
Label:
text: 'Hasło: '
TextInput:
multiline: False
id: _password
password: True
BoxLayout:
height: "40dp"
size_hint_y: None
Button:
text:'Zaloguj'
on_press: root.log_in()
Button:
text: 'Ustawienia'
on_press: root.show_settings()
BoxLayout:
<SettingsWindow>:
ip_input: _ip
port_input: _port
orientation: 'vertical'
BoxLayout:
height: "40dp"
size_hint_y: None
Label:
text: 'IP: '
TextInput:
focus: True
multiline: False
id: _ip
text: root.ip_value
Label:
text: 'Port: '
TextInput:
multiline: False
id: _port
text: root.port_value
Button:
text: 'Cofnij'
on_press: root.show_logging()
Button:
text: 'Zapisz'
on_press: root.save_ip_port()
<MenuWindow>
orientation: 'vertical'
BoxLayout:
BoxLayout:
height: "40dp"
size_hint_y: None
Label:
id: _napis
text: 'polaczenie'
#text: root.change_caption()
Button:
text: 'Cofnij'

Categories