Python/Kivy :从一个 class 调用函数到另一个 class 并在 Python 中显示小部件
Python/Kivy : Call function from one class to another class and show widget in Python
我正在使用 Python-2.7 和 Kivy。当我 运行 test.py 然后显示按钮显示。当我单击显示按钮时,会显示一个标签和值。我正在从数据库中获取它,但现在我将它定义为静态数组。
当我点击 Item1 标签然后调用 def open_form 并在使用 id 调用 EditPopup(self)
后传递 id 11 并显示一个带有值的弹出窗口。
之后我更改 itemCode
并单击确定按钮,然后它更新数据库中的数据。
之后我调用 Invoice().abc()
然后它在 Pycharm
控制台中打印更新的数据但不在 layout.add_widget
中显示最新数据(弹出窗口 window)。
谁能告诉我哪里出错了?
test.py
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.core.window import Window
from functools import partial
from kivy.uix.popup import Popup
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
import sqlite3 as lite
#con = lite.connect('test.db')
#con.text_factory = str
#cur = con.cursor()
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)
class MyLabel(Label):
pass
class EditPopup(Popup):
mode = StringProperty("")
label_rec_id = StringProperty("Id")
col_data = ListProperty(["?", "?", "?"])
index = NumericProperty(0)
def __init__(self, obj, **kwargs):
super(EditPopup, self).__init__(**kwargs)
if obj.mode == "Update":
#cur.execute("SELECT * FROM `item` WHERE itemId=?", (edit_id,))
#row = cur.fetchone()
row = (11, 'Item1', '1001')
print(row[0])
self.col_data[0] = str(row[0])
self.col_data[1] = row[1]
self.col_data[2] = row[2]
def update(self,obj):
#cur.execute("UPDATE `item` SET itemName=?, itemCode=? WHERE itemId=?",
#('Item1', 9999, 11))
#con.commit()
Invoice().abc()
class Invoice(Screen):
def __init__(self, **kwargs):
super(Invoice, self).__init__(**kwargs)
def abc(self):
#fetching from database
#cur.execute("SELECT * FROM `item` order by itemId asc")
#rows = cur.fetchall()
rows = [(11, 'Item1', '1001'), (12, 'Item2', '2001'), (13, 'Item3', '102')]
print(rows)
layout = self.ids['invoices']
for row in rows:
layout.add_widget(MyLabel(text=str('[ref=world]' + row[1]) + '[/ref]',
size_hint_x=.35,
halign='left',
markup=True,
on_ref_press=partial(self.open_form, row[0])))
def open_form(self, id, *args):
global edit_id
edit_id = id
self.mode = "Update"
popup = EditPopup(self)
popup.open()
class Test(App):
def build(self):
return Invoice()
if __name__ == '__main__':
Test().run()
test.kv
<Button@Button>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
<MyLabel>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
text_size: self.size
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
<EditPopup>:
title: self.mode + " Item"
size_hint: None, None
title_size: 20
title_font: "Verdana"
size: 400, 275
auto_dismiss: False
BoxLayout:
orientation: "vertical"
GridLayout:
cols: 2
#backgroun_color: 0, 0.517, 0.705, 1
spacing: 10, 10
padding: 20, 20
Label:
text: root.label_rec_id
text_size: self.size
Label:
id: itemId
text: root.col_data[0]
text_size: self.size
Label:
text: "Item Name"
text_size: self.size
valign: 'middle'
TextInput:
id: itemName
text: root.col_data[1]
text_size: self.size
Label:
text: "State Code"
text_size: self.size
valign: 'middle'
TextInput:
id: itemCode
text: root.col_data[2]
text_size: self.size
GridLayout:
cols: 2
padding: 10, 0, 10, 10
spacing: 10, 10
row_default_height: '20dp'
size_hint: .55, .3
pos_hint: {'x': .25, 'y':.65}
Button:
size_hint_x: .5
text: "Ok"
on_release:
root.update(root)
root.dismiss()
Button:
size_hint_x: .5
text: "Cancel"
on_release: root.dismiss()
<Invoice>:
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
GridLayout:
id: invoices
cols: 2
#orientation: "horizontal"
padding : 5, 0
spacing: 10, 0
#size: 500, 30
size_hint: 1, 1
pos: self.pos
size: self.size
您正在创建一个新的 Invoice
实例,而不是使用现有实例。
Invoice().abc()
试试看:
class EditPopup(Popup):
mode = StringProperty("")
label_rec_id = StringProperty("Id")
col_data = ListProperty(["?", "?", "?"])
index = NumericProperty(0)
def __init__(self, obj, **kwargs):
super(EditPopup, self).__init__(**kwargs)
self.obj = obj # will need it later...
def update(self,obj):
#cur.execute("UPDATE `item` SET itemName=?, itemCode=? WHERE itemId=?",
#('Item1', 9999, 11))
#con.commit()
self.obj.abc() # was Invoice().abc()
问题
您正在通过在 class EditPopup 中的方法更新时调用 Invoice().abc() 来实例化 class Invoice 的第二个实例。
解决方案
1) test.py
在 class EditPopup 的方法更新处注释掉 Invoice().abc() 并添加 pass.
def update(self, obj):
#cur.execute("UPDATE `item` SET itemName=?, itemCode=? WHERE itemId=?",
#('Item1', 9999, 11))
#con.commit()
# Invoice().abc()
pass
2) test.kv
在 class EditPopup 调用方法更新后添加对方法 abc 的调用。
Button:
size_hint_x: .5
text: "Ok"
on_release:
root.update(root)
app.root.abc()
root.dismiss()
输出
我正在使用 Python-2.7 和 Kivy。当我 运行 test.py 然后显示按钮显示。当我单击显示按钮时,会显示一个标签和值。我正在从数据库中获取它,但现在我将它定义为静态数组。
当我点击 Item1 标签然后调用 def open_form 并在使用 id 调用 EditPopup(self)
后传递 id 11 并显示一个带有值的弹出窗口。
之后我更改 itemCode
并单击确定按钮,然后它更新数据库中的数据。
之后我调用 Invoice().abc()
然后它在 Pycharm
控制台中打印更新的数据但不在 layout.add_widget
中显示最新数据(弹出窗口 window)。
谁能告诉我哪里出错了?
test.py
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.core.window import Window
from functools import partial
from kivy.uix.popup import Popup
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
import sqlite3 as lite
#con = lite.connect('test.db')
#con.text_factory = str
#cur = con.cursor()
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)
class MyLabel(Label):
pass
class EditPopup(Popup):
mode = StringProperty("")
label_rec_id = StringProperty("Id")
col_data = ListProperty(["?", "?", "?"])
index = NumericProperty(0)
def __init__(self, obj, **kwargs):
super(EditPopup, self).__init__(**kwargs)
if obj.mode == "Update":
#cur.execute("SELECT * FROM `item` WHERE itemId=?", (edit_id,))
#row = cur.fetchone()
row = (11, 'Item1', '1001')
print(row[0])
self.col_data[0] = str(row[0])
self.col_data[1] = row[1]
self.col_data[2] = row[2]
def update(self,obj):
#cur.execute("UPDATE `item` SET itemName=?, itemCode=? WHERE itemId=?",
#('Item1', 9999, 11))
#con.commit()
Invoice().abc()
class Invoice(Screen):
def __init__(self, **kwargs):
super(Invoice, self).__init__(**kwargs)
def abc(self):
#fetching from database
#cur.execute("SELECT * FROM `item` order by itemId asc")
#rows = cur.fetchall()
rows = [(11, 'Item1', '1001'), (12, 'Item2', '2001'), (13, 'Item3', '102')]
print(rows)
layout = self.ids['invoices']
for row in rows:
layout.add_widget(MyLabel(text=str('[ref=world]' + row[1]) + '[/ref]',
size_hint_x=.35,
halign='left',
markup=True,
on_ref_press=partial(self.open_form, row[0])))
def open_form(self, id, *args):
global edit_id
edit_id = id
self.mode = "Update"
popup = EditPopup(self)
popup.open()
class Test(App):
def build(self):
return Invoice()
if __name__ == '__main__':
Test().run()
test.kv
<Button@Button>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
<MyLabel>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
text_size: self.size
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
<EditPopup>:
title: self.mode + " Item"
size_hint: None, None
title_size: 20
title_font: "Verdana"
size: 400, 275
auto_dismiss: False
BoxLayout:
orientation: "vertical"
GridLayout:
cols: 2
#backgroun_color: 0, 0.517, 0.705, 1
spacing: 10, 10
padding: 20, 20
Label:
text: root.label_rec_id
text_size: self.size
Label:
id: itemId
text: root.col_data[0]
text_size: self.size
Label:
text: "Item Name"
text_size: self.size
valign: 'middle'
TextInput:
id: itemName
text: root.col_data[1]
text_size: self.size
Label:
text: "State Code"
text_size: self.size
valign: 'middle'
TextInput:
id: itemCode
text: root.col_data[2]
text_size: self.size
GridLayout:
cols: 2
padding: 10, 0, 10, 10
spacing: 10, 10
row_default_height: '20dp'
size_hint: .55, .3
pos_hint: {'x': .25, 'y':.65}
Button:
size_hint_x: .5
text: "Ok"
on_release:
root.update(root)
root.dismiss()
Button:
size_hint_x: .5
text: "Cancel"
on_release: root.dismiss()
<Invoice>:
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
GridLayout:
id: invoices
cols: 2
#orientation: "horizontal"
padding : 5, 0
spacing: 10, 0
#size: 500, 30
size_hint: 1, 1
pos: self.pos
size: self.size
您正在创建一个新的 Invoice
实例,而不是使用现有实例。
Invoice().abc()
试试看:
class EditPopup(Popup):
mode = StringProperty("")
label_rec_id = StringProperty("Id")
col_data = ListProperty(["?", "?", "?"])
index = NumericProperty(0)
def __init__(self, obj, **kwargs):
super(EditPopup, self).__init__(**kwargs)
self.obj = obj # will need it later...
def update(self,obj):
#cur.execute("UPDATE `item` SET itemName=?, itemCode=? WHERE itemId=?",
#('Item1', 9999, 11))
#con.commit()
self.obj.abc() # was Invoice().abc()
问题
您正在通过在 class EditPopup 中的方法更新时调用 Invoice().abc() 来实例化 class Invoice 的第二个实例。
解决方案
1) test.py
在 class EditPopup 的方法更新处注释掉 Invoice().abc() 并添加 pass.
def update(self, obj):
#cur.execute("UPDATE `item` SET itemName=?, itemCode=? WHERE itemId=?",
#('Item1', 9999, 11))
#con.commit()
# Invoice().abc()
pass
2) test.kv
在 class EditPopup 调用方法更新后添加对方法 abc 的调用。
Button:
size_hint_x: .5
text: "Ok"
on_release:
root.update(root)
app.root.abc()
root.dismiss()