Buildozer编译的apk不保持字体大小
Buildozer compiled apk doesn't keep font size
我正在尝试通过编写一个应用程序来学习 python 和 kivy,该应用程序动态创建用户输入的模块,以便使用 + 和 - 按钮进行计数。
我正在使用 buildozer 创建 apk 并将其部署到我的 phone(Samsung Galaxy S21 Ultra,Android 11)。
我遇到了两个问题:
- 虽然我运行在PyCharm虚拟环境下的代码没有问题,但是当我运行phone上的apk时,却没有保持我在代码中设置的文本大小;
- Pdf 文件正在 PyCharm 的虚拟环境中创建,但它使 phone 上的 apk 崩溃。
任何帮助将不胜感激。非常感谢。
这是完整的代码:
Python 文件:
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from fpdf import FPDF
class pdf(FPDF): # Setting the header and footer for the pdf document
def header(self):
self.image('inventory_management.png', 10, 8, 25)
self.set_font('helvetica', 'B', 20)
self.cell(0,10, app.root.ids.project_name.text, ln=True, align='C')
self.ln(20)
def footer(self):
self.set_y(-15)
self.set_font('helvetica', 'I', 10)
self.cell(0, 10, f'Page {self.page_no()}/{{nb}}', align='C')
class popup_empty(Popup): # Message box if user doesn't inputs a module name
pass
class popup_exist(Popup): # Message box if user inputs an existent module name
pass
class Row(BoxLayout): # Creates a row for each module
quantity = ObjectProperty()
entry = ObjectProperty()
def change_label(self): # Setting the module name with the user input
self.name_label.text = app.root.ids.name_input.text
def add_entry(self): # Function used by the + button to add to the quantity
self.quantity.text = str(int(self.quantity.text) + int(self.entry.text))
app.root.Lista_module[self.ids.name_label.text] = int(self.quantity.text)
def deduct_entry(self): # Function used by the - button to deduct from the quantity
self.quantity.text = str(int(self.quantity.text) - int(self.entry.text))
app.root.Lista_module[self.ids.name_label.text] = int(self.quantity.text)
def del_row(self): # Function used by the del button to remove a module row
del app.root.Lista_module[self.ids.name_label.text]
app.root.ids.rows_container.remove_widget(self)
class mainContainer(BoxLayout): # Main container which holds all the widgets
Lista_module = {}
def file_name(self): # replaces the spaces user inputs in the module name to create the pdf filename
name = self.ids.project_name.text
name = name.replace(" ", "_")
return name
def add_a_row(self): # function used to dynamically add rows to the scrollview
if self.ids.name_input.text != "":
name = self.ids.name_input.text
exist = False
for key in self.Lista_module.keys():
if key == name:
exist = True
if exist:
popup = popup_exist()
popup.open()
else:
temp_row = Row()
temp_row.change_label()
self.ids.rows_container.add_widget(temp_row)
key = self.ids.name_input.text
self.Lista_module[key] = 0
else:
popup = popup_empty()
popup.open()
pass
def print(self): # function used by the print button to create the pdf file
name = self.file_name() + '.pdf'
document = pdf('P', 'mm', 'A4')
document.add_page()
document.alias_nb_pages()
document.set_auto_page_break(auto=True)
document.set_font('times', '', 14)
for mod in self.Lista_module:
document.cell(0, 10, f'{mod}: {self.Lista_module[mod]}', border=True, ln=True)
document.output('I', name)
class lysuApp(App):
def build(self):
return mainContainer()
if __name__ == "__main__":
app = lysuApp()
app.run()
kv 文件:
<popup_exist>
size_hint: 0.5, 0.5
pos_hint: {"x":0.2, "top":0.9}
title: "Eroare nume"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Modul existent, reintrodu!"
Button:
text: "OK"
on_release: root.dismiss()
<popup_empty>
size_hint: 0.5, 0.5
pos_hint: {"x":0.2, "top":0.9}
title: "Eroare nume"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Trebuie sa introduci un nume!"
Button:
text: "OK"
on_release: root.dismiss()
<Row>
name_label: name_label
quantity: quantity
entry: entry
orientation: "horizontal"
size_hint_y: None
height: 30
id: root.module_name
Label:
id: name_label
font_size: 20
text: ""
Label:
font_size: 20
text: ":"
Label:
id: quantity
font_size: 20
text: "0"
TextInput:
id: entry
font_size: 20
text: "1"
Button:
font_size: 20
text: "-"
on_press: root.deduct_entry()
Button:
font_size: 20
text: "+"
on_press: root.add_entry()
Button:
font_size: 20
text: "del"
on_press: root.del_row()
<mainContainer>
id: mainpage
BoxLayout: # the main container
orientation: "vertical"
size: root.width, root.height
padding: 25
spacing: 20
BoxLayout: # Contains the title
orientation: "vertical"
size_hint: (1, .2)
spacing: 5
Label:
font_size: 20
text: "Creaza modulele si incepe editarea!"
size_hint: (1, .5)
BoxLayout: # Box for project name and print button
size_hint: (1, .5)
orientation: "horizontal"
Label:
font_size: 20
text: "Numeste proiectul: "
TextInput:
id: project_name
font_size: 20
Button:
font_size: 20
text: "Printeaza"
on_release: app.root.print()
ScrollView: # Will hold the dynamically created rows
BoxLayout:
size_hint_y: None
height: self.minimum_height
row_force_default: True
row_default_height: dp(40)
orientation: "vertical"
id: rows_container
spacing: 10
BoxLayout: # Bottom of the page used to input the name of the modules that will be dynamically created
orientation: "horizontal"
size_hint: (1, .1)
Label:
font_size: 20
text: "Nume modul"
TextInput:
id: name_input
font_size: 20
Button:
font_size: 20
text: "Adauga"
on_press:
root.add_a_row()
这是因为您是根据像素设置字体大小的,像素大小因屏幕而异。您可以根据测量值(英寸、厘米)或像素密度设置字体大小,如下所示:
在您的 .kv 文件中,使用 font_size: '20dp'
、font_size: '20cm'
或您想要的任何单位代替 font_size: 20
。
如果您想在 .py 文件中设置字体大小,请先从 kivy.metrics
导入所需的单位。例如,如果您想使用英寸,您可以编写 from kivy.metrics import inch
,然后将数字像素值替换为 inch(2)
、inch(1)
或您想要的任何值。
有关更多信息,请参阅 Metrics。
关于你的第二个问题,document.output('I', name)
行是一个拼写错误(如果你正在创建一个名为 name
的文件,它应该是 document.output(name, "F")
)。如果这不是问题的原因,请查看使用 logcat.
调试您的 APK
以后请将问题分成两个单独的帖子。
我 sub-classed TextInput 并给它自己的 on_size 回调,如下所示:
def on_size(self,instance,value):
# run parent on_size manually
super(MyTextInput,self).on_size(instance,value)
self.font_size = self.height*0.8
所以字体大小是 textInput 高度的一小部分,无论它在什么设备上 运行。 (请注意,可能有一种 better/correct 方法可以为 sub-class 中的 on_size 事件绑定回调,因此它与父回调并行工作,而不是 over-riding 它。)
我正在尝试通过编写一个应用程序来学习 python 和 kivy,该应用程序动态创建用户输入的模块,以便使用 + 和 - 按钮进行计数。 我正在使用 buildozer 创建 apk 并将其部署到我的 phone(Samsung Galaxy S21 Ultra,Android 11)。 我遇到了两个问题:
- 虽然我运行在PyCharm虚拟环境下的代码没有问题,但是当我运行phone上的apk时,却没有保持我在代码中设置的文本大小;
- Pdf 文件正在 PyCharm 的虚拟环境中创建,但它使 phone 上的 apk 崩溃。 任何帮助将不胜感激。非常感谢。 这是完整的代码:
Python 文件:
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from fpdf import FPDF
class pdf(FPDF): # Setting the header and footer for the pdf document
def header(self):
self.image('inventory_management.png', 10, 8, 25)
self.set_font('helvetica', 'B', 20)
self.cell(0,10, app.root.ids.project_name.text, ln=True, align='C')
self.ln(20)
def footer(self):
self.set_y(-15)
self.set_font('helvetica', 'I', 10)
self.cell(0, 10, f'Page {self.page_no()}/{{nb}}', align='C')
class popup_empty(Popup): # Message box if user doesn't inputs a module name
pass
class popup_exist(Popup): # Message box if user inputs an existent module name
pass
class Row(BoxLayout): # Creates a row for each module
quantity = ObjectProperty()
entry = ObjectProperty()
def change_label(self): # Setting the module name with the user input
self.name_label.text = app.root.ids.name_input.text
def add_entry(self): # Function used by the + button to add to the quantity
self.quantity.text = str(int(self.quantity.text) + int(self.entry.text))
app.root.Lista_module[self.ids.name_label.text] = int(self.quantity.text)
def deduct_entry(self): # Function used by the - button to deduct from the quantity
self.quantity.text = str(int(self.quantity.text) - int(self.entry.text))
app.root.Lista_module[self.ids.name_label.text] = int(self.quantity.text)
def del_row(self): # Function used by the del button to remove a module row
del app.root.Lista_module[self.ids.name_label.text]
app.root.ids.rows_container.remove_widget(self)
class mainContainer(BoxLayout): # Main container which holds all the widgets
Lista_module = {}
def file_name(self): # replaces the spaces user inputs in the module name to create the pdf filename
name = self.ids.project_name.text
name = name.replace(" ", "_")
return name
def add_a_row(self): # function used to dynamically add rows to the scrollview
if self.ids.name_input.text != "":
name = self.ids.name_input.text
exist = False
for key in self.Lista_module.keys():
if key == name:
exist = True
if exist:
popup = popup_exist()
popup.open()
else:
temp_row = Row()
temp_row.change_label()
self.ids.rows_container.add_widget(temp_row)
key = self.ids.name_input.text
self.Lista_module[key] = 0
else:
popup = popup_empty()
popup.open()
pass
def print(self): # function used by the print button to create the pdf file
name = self.file_name() + '.pdf'
document = pdf('P', 'mm', 'A4')
document.add_page()
document.alias_nb_pages()
document.set_auto_page_break(auto=True)
document.set_font('times', '', 14)
for mod in self.Lista_module:
document.cell(0, 10, f'{mod}: {self.Lista_module[mod]}', border=True, ln=True)
document.output('I', name)
class lysuApp(App):
def build(self):
return mainContainer()
if __name__ == "__main__":
app = lysuApp()
app.run()
kv 文件:
<popup_exist>
size_hint: 0.5, 0.5
pos_hint: {"x":0.2, "top":0.9}
title: "Eroare nume"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Modul existent, reintrodu!"
Button:
text: "OK"
on_release: root.dismiss()
<popup_empty>
size_hint: 0.5, 0.5
pos_hint: {"x":0.2, "top":0.9}
title: "Eroare nume"
BoxLayout:
orientation: "vertical"
size: root.width, root.height
Label:
text: "Trebuie sa introduci un nume!"
Button:
text: "OK"
on_release: root.dismiss()
<Row>
name_label: name_label
quantity: quantity
entry: entry
orientation: "horizontal"
size_hint_y: None
height: 30
id: root.module_name
Label:
id: name_label
font_size: 20
text: ""
Label:
font_size: 20
text: ":"
Label:
id: quantity
font_size: 20
text: "0"
TextInput:
id: entry
font_size: 20
text: "1"
Button:
font_size: 20
text: "-"
on_press: root.deduct_entry()
Button:
font_size: 20
text: "+"
on_press: root.add_entry()
Button:
font_size: 20
text: "del"
on_press: root.del_row()
<mainContainer>
id: mainpage
BoxLayout: # the main container
orientation: "vertical"
size: root.width, root.height
padding: 25
spacing: 20
BoxLayout: # Contains the title
orientation: "vertical"
size_hint: (1, .2)
spacing: 5
Label:
font_size: 20
text: "Creaza modulele si incepe editarea!"
size_hint: (1, .5)
BoxLayout: # Box for project name and print button
size_hint: (1, .5)
orientation: "horizontal"
Label:
font_size: 20
text: "Numeste proiectul: "
TextInput:
id: project_name
font_size: 20
Button:
font_size: 20
text: "Printeaza"
on_release: app.root.print()
ScrollView: # Will hold the dynamically created rows
BoxLayout:
size_hint_y: None
height: self.minimum_height
row_force_default: True
row_default_height: dp(40)
orientation: "vertical"
id: rows_container
spacing: 10
BoxLayout: # Bottom of the page used to input the name of the modules that will be dynamically created
orientation: "horizontal"
size_hint: (1, .1)
Label:
font_size: 20
text: "Nume modul"
TextInput:
id: name_input
font_size: 20
Button:
font_size: 20
text: "Adauga"
on_press:
root.add_a_row()
这是因为您是根据像素设置字体大小的,像素大小因屏幕而异。您可以根据测量值(英寸、厘米)或像素密度设置字体大小,如下所示:
在您的 .kv 文件中,使用 font_size: '20dp'
、font_size: '20cm'
或您想要的任何单位代替 font_size: 20
。
如果您想在 .py 文件中设置字体大小,请先从 kivy.metrics
导入所需的单位。例如,如果您想使用英寸,您可以编写 from kivy.metrics import inch
,然后将数字像素值替换为 inch(2)
、inch(1)
或您想要的任何值。
有关更多信息,请参阅 Metrics。
关于你的第二个问题,document.output('I', name)
行是一个拼写错误(如果你正在创建一个名为 name
的文件,它应该是 document.output(name, "F")
)。如果这不是问题的原因,请查看使用 logcat.
以后请将问题分成两个单独的帖子。
我 sub-classed TextInput 并给它自己的 on_size 回调,如下所示:
def on_size(self,instance,value):
# run parent on_size manually
super(MyTextInput,self).on_size(instance,value)
self.font_size = self.height*0.8
所以字体大小是 textInput 高度的一小部分,无论它在什么设备上 运行。 (请注意,可能有一种 better/correct 方法可以为 sub-class 中的 on_size 事件绑定回调,因此它与父回调并行工作,而不是 over-riding 它。)