Buildozer编译的apk不保持字体大小

Buildozer compiled apk doesn't keep font size

我正在尝试通过编写一个应用程序来学习 python 和 kivy,该应用程序动态创建用户输入的模块,以便使用 + 和 - 按钮进行计数。 我正在使用 buildozer 创建 apk 并将其部署到我的 phone(Samsung Galaxy S21 Ultra,Android 11)。 我遇到了两个问题:

  1. 虽然我运行在PyCharm虚拟环境下的代码没有问题,但是当我运行phone上的apk时,却没有保持我在代码中设置的文本大小;
  2. 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 它。)