从Kivy应用程序中获取用户输入,并使用Python将其附加到谷歌工作表中



我正在尝试制作一个简单的Python-Kivy应用程序(使用布局的kv文件(,我将使用它来保存我的零件库存以备工作之用。我对python和kivy很陌生,所以我需要一点指导。

其中一个基本功能是允许用户在"键盘"上输入一个新部件;将部件添加到库存中";屏幕(四个屏幕之一(。用户输入由四个项目组成(零件名称、序列号、现有数量和所需的最小数量(。

一旦用户输入这些信息并按下"提交"按钮,我希望将这些数据附加到谷歌工作表中的新行,我正在使用google Drive/Sheets API(我能够使用它(作为后端数据库。

我在网上发现的大多数示例应用程序只有一个屏幕,并且只处理一种类型的用户输入(通常是文本,而我的输入将是文本和整数(。

我很困惑我需要把我的id放在kv文件的哪里(我假设在AddPartWindow布局下(,如何在按下不在根类中的按钮时调用函数,如何将用户输入存储到列表中,因为我不确定ObjectProperty函数到底在做什么,最后,如何将该列表附加到我的谷歌工作表中的新行。

我不是在寻找一个剪切粘贴的答案,只是一些方向会很好,因为我还没有找到一个很好的参考资料来准确地描述我要做的事情。我的主要困惑在于有多个屏幕,以及如何在不同的屏幕和它们各自的类之间传输数据。数据应该只通过一个根类进行传递吗?或者每个类都可以用来处理来自应用程序中各自屏幕(窗口(的数据吗?ObjectProperty函数究竟在做什么?我发现kivy网站在描述属性类时有点复杂。

如有任何帮助/指导,我们将不胜感激。

这是主.py代码:

import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.properties import ObjectProperty
import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('My_First_Project-3d753d98320e.json', scope)
client = gspread.authorize(creds)
iQue_sheet = client.open("InventoryBackend").sheet1
#root layout
class InventoryWindow(Screen):
pass
#Layout in question
class AddPartWindow(Screen):
#Is there anything else I need to do with these before saving into a list or dictionary?

part_name = ObjectProperty(None)
serial_number = ObjectProperty(None)
on_hand_cnt = ObjectProperty(None)
min_needed = ObjectProperty(None)
#This function should save the user input into a list, np, and then append to the google sheet iQue_sheet
#Wasn't sure if it should be a list or a dictionary.
#I'm assuming .text is type-casting each object to a string.  Can this be used for numerical inputs?

def new_part(self):
np = [self.part_name.text, self.serial_number.text, self.on_hand_cnt.text, self.min_needed.text]
iQue_sheet.append(np)
class OnOrderWindow(Screen):
pass
class OrderFormWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class InventoryApp(App):
def build(self):
#These are used to enable going back and forth between screens using buttons
sm = ScreenManager()
sm.add_widget(InventoryWindow(name='inv_window'))
sm.add_widget(OnOrderWindow(name='on_order_window'))
sm.add_widget(AddPartWindow(name='add_part_window'))
sm.add_widget(OrderFormWindow(name='order_form_window'))
return sm
if __name__ == "__main__":
InventoryApp().run()

这是我的.kv布局文件,Add Part窗口是最后一个布局:

WindowManager:
InventoryWindow:
OnOrderWindow:
OrderFormWindow:
AddPartWindow:
<ItemLabel@Label>
font_size: '15sp'
halign: 'left'
valign: 'middle'
text_size: self.size
<ItemButton@Button>
pos_hint: {'center_x':0.5, 'center_y':0.5}
size_hint: 0.65, 0.2

<ItemButton2@Button>
pos_hint: {'center_x':0.5, 'center_y':0.5}
size_hint: 0.65, 0.2
on_release:
app.root.current = "order_form_window"

<InventoryWindow>:
name: "inv_window"
add_probe: add_probe
FloatLayout:
Label:
text: 'Inventory'
font_size: '25sp'
size_hint: (1, 0.17)
pos_hint: {'x': 0, 'y': 0.87}
GridLayout:
cols: 4
padding:[10, 65, 10, 10]
spacing: 5
BoxLayout:
orientation: 'vertical'
ItemLabel:
text:'iQue3: Probe/Tubing'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Add'
on_release:
root.new_part()
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Sub'
BoxLayout:
orientation: 'vertical'
ItemButton2:
text:'Order'
BoxLayout:
orientation: 'vertical'
ItemLabel:
text:'Gen2: Probe/Tubing'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Add'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Sub'
BoxLayout:
orientation: 'vertical'
ItemButton2:
text:'Order'
BoxLayout:
orientation: 'vertical'
ItemLabel:
text:'Beads'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Add'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Sub'
BoxLayout:
orientation: 'vertical'
ItemButton2:
text:'Order'
BoxLayout:
orientation: 'vertical'
ItemLabel:
text:'iQue3 Fluid Maint. Kit'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Add'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Sub'
BoxLayout:
orientation: 'vertical'
ItemButton2:
text:'Order'
BoxLayout:
orientation: 'vertical'
ItemLabel:
text:'Screener Fluid Maint. Kit'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Add'
BoxLayout:
orientation: 'vertical'
ItemButton:
text:'Sub'
BoxLayout:
orientation: 'vertical'
ItemButton2:
text:'Order'
BoxLayout:
orientation: 'vertical'

GridLayout:
cols: 2
size_hint: 1, 0.15
padding: [10, 0, 10, 10]

BoxLayout:
Button:
text: 'Add Part to Inventory'
font_size: '18sp'
size_hint: (1, 0.75)
on_release:
app.root.current = "add_part_window"
root.manager.transition.direction = "right"
Button:
text: 'On Order'
font_size: '18sp'
size_hint: (1, 0.75)
on_release:
app.root.current = "on_order_window"
root.manager.transition.direction = "left"

<OnOrderWindow>:
name: "on_order_window"
FloatLayout:
Label:
text: 'On Order'
font_size: '25sp'
size_hint: (1, 0.17)
pos_hint: {'x': 0, 'y': 0.87}
GridLayout:
cols: 2
size_int: 1, .15
padding:[10, 510, 10, 10]
Button:
text: "Inventory"
font_size: '18sp'
size_hint: (1, 0.6)
on_release:
app.root.current = "inv_window"
root.manager.transition.direction = "right"
Button:
text:"Add Part to Inventory"
size_hint: (1, 0.6)
font_size: '18sp'
on_release:
app.root.current = "add_part_window"
root.manager.transition.direction = "left"

<OrderFormWindow>
name: "order_form_window"
FloatLayout:
Label:
text: 'Order Form'
font_size: '25sp'
size_hint: (1, 0.17)
pos_hint: {'x': 0, 'y': 0.87}
GridLayout:
cols:2
padding: [50, 50, 50, 120]
ItemLabel:
text: "Part: "
ItemLabel:
text: "Populate Part Here"
ItemLabel:
text: "Serial Number: "
ItemLabel:
text: "Populate SN Here"
ItemLabel:
text: "On Hand: "
ItemLabel:
text: "Populate On Hand Count Here"
ItemLabel:
text: "Minimum Needed: "
ItemLabel:
text: "Populate Min Needed Here"
ItemLabel:
text: "Order Quantity"
TextInput:
halign: 'left'
valign: 'middle'
input_type: 'number'
input_filter: 'int'
multiline:False
GridLayout:
cols:2
size_hint: 1, 0.15
padding: [10, 0, 10, 10]
Button:
text:"Cancel"
on_release: app.root.current = "inv_window"
Button:
text:"Submit Order"
on_release: app.root.current = "on_order_window"

#This is the add part screen layout I'm referring to
<AddPartWindow>
name: "add_part_window"
#These are the id's I was referring to:

part_name: part_name
serial_number: serial_number
on_hand_cnt: on_hand_cnt
min_needed: min_needed
FloatLayout:
Label:
text: 'Add Part to Inventory'
font_size: '25sp'
size_hint: (1, 0.17)
pos_hint: {'x': 0, 'y': 0.86}
GridLayout:
cols:2
padding: [50, 100, 50, 120]
spacing: 5
ItemLabel:
text: "Name of Part: "
TextInput:
id: part_name
halign: 'left'
valign: 'middle'
multinline:False
ItemLabel:
text: "Serial Number: "
TextInput:
id: serial_number
halign: 'left'
valign: 'middle'
multiline:False
ItemLabel:
text: "How Many On Hand?: "
TextInput:
id: on_hand_cnt
halign: 'left'
valign: 'middle'
multinline:False
ItemLabel:
text: "Minimum Needed?: "
TextInput:
id: min_needed
halign: 'left'
valign: 'middle'
multiline:False
GridLayout:
cols:2
size_hint: 1, 0.15
padding: [10, 0, 10, 10]
Button:
text:"Cancel"
on_release:
app.root.current = "inv_window"
root.manager.transition.direction = "left"
#Here is the button I'm referring to, I realize that putting "root." in front of new_part() is not 
#the correct thing to put, so it's a placeholder for now:

Button:
text:"Submit"
on_release:
root.new_part()
app.root.current = "inv_window"
root.manager.transition.direction = "left"

这是添加部件屏幕的屏幕截图

当我在四个字段中输入输入并点击提交按钮时,我得到的当前错误是:

File "C:Usersedr27kivy_venvlibsite-packageskivyuixbehaviorsbutton.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy_event.pyx", line 705, in kivy._event.EventDispatcher.dispatch
File "kivy_event.pyx", line 1248, in kivy._event.EventObservers.dispatch
File "kivy_event.pyx", line 1132, in kivy._event.EventObservers._dispatch
File "C:Usersedr27kivy_venvlibsite-packageskivylangbuilder.py", line 57, in custom_callback
exec(__kvlang__.co_value, idmap)
File "C:Usersedr27PycharmProjectspythonProjectinventory.kv", line 345, in <module>
root.new_part()
File "C:Usersedr27PycharmProjectspythonProjectmain.py", line 35, in new_part
np = [self.part_name.text, self.serial_number.text, self.on_hand_cnt.text, self.min_needed.text]
AttributeError: 'NoneType' object has no attribute 'text'

编辑:

以下是我如何实现Oussama的答案,以便使其发挥作用,我所要做的就是更新AddPartWindow类:

class AddPartWindow(Screen):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.np = []
def submit(self):
self.part_name = self.ids.part_name.text
self.serial_number = self.ids.serial_number.text
self.on_hand_cnt = self.ids.on_hand_cnt.text
self.min_needed = self.ids.min_needed.text
self.np = [self.part_name, self.serial_number, self.on_hand_cnt, self.min_needed]
iQue_sheet.append_row(self.np)

我还做了这个更改,以便将附加到工作簿的第3页,而不是第1页

iQue_sheet = client.open("InventoryBackend").get_worksheet(2)

this main.py可以随意导入您需要的内容。这是你想做什么的一个简单例子

from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.app import App
Builder.load_file('the.kv')
class fscreen(widget):
def __init__(self, **kwargs):
supper().__init__(**kwargs)
self.np = []        
def submit(self):

self.part_name = self.ids.Pname.text
self.serial_number = self.ids.Snumber.text
self.on_hand_cnt = self.ids.onhabdcnt.text
self.min_needed = self.ids.minneeded.text
self.np = [self.part_name, self.serial_number, self.on_hand_cnt, self.min_needed]
iQue_sheet.append(self.np)

class secscreen(widget):
def __init__(self, **kwargs):
supper().__init__(**kwargs)
pass
class thscreen(widget):
def __init__(self, **kwargs):
supper().__init__(**kwargs)
pass
class theapp(App):
def build(self):
self.screenm = ScreenManager()
self.screen = Screen(name = "first screen")
screen.add_widget(self.fscreen)
self.screenm.add_widget(screen)
if __name__ = "__main__":
theapp.run()

这是.kv文件

<fscreen>
TextInput:
id: Pname
hint_text: 'partname'
TextInput:
id: Snumber
hint_text: 'serialnumber'
TextInput:
id: onhandcnt
hint_text: 'on hand cnt'
TextInput:
id: minneeded
hint_text: 'min nedded' 
Button:
text: 'Submit'
on_press: root.submit()

相关内容

  • 没有找到相关文章

最新更新