kivy android打包buildozer.spec GUI配置

這個適合剛剛學習kivyd的道友使用,后面看情況更新

代碼

import tkinter as tk
from tkinter import ttk, filedialog, messagebox, simpledialog
import configparser
import os
import json  # 新增導入class BuildozerConfigTool:def __init__(self, master):self.master = mastermaster.title("Buildozer配置工具")# 創建主容器框架self.left_frame = ttk.Frame(master)self.left_frame.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")self.right_frame = ttk.Frame(master)self.right_frame.grid(row=0, column=1, padx=5, pady=5, sticky="nsew")# 調整各部分的父容器self.create_basic_settings(self.left_frame)self.create_advanced_settings(self.right_frame)self.create_dependencies_section(self.left_frame)self.create_permissions_section(self.left_frame)self.create_file_selection(self.right_frame)self.create_action_buttons(master)# 配置網格布局權重master.columnconfigure(0, weight=1)master.columnconfigure(1, weight=1)master.rowconfigure(0, weight=1)# 初始化配置解析器self.config = configparser.ConfigParser()# 新增配置存儲路徑self.config_path = os.path.expanduser("~/.buildozer_gui_config.json")# 更新默認權限列表(去掉前綴)self.default_permissions = ["INTERNET","ACCESS_WIFI_STATE","WRITE_EXTERNAL_STORAGE","READ_EXTERNAL_STORAGE","CAMERA","BLUETOOTH","BLUETOOTH_ADMIN","ACCESS_COARSE_LOCATION","ACCESS_FINE_LOCATION","QUERY_ALL_PACKAGES"]self.default_dependencies = ["kivy","requests","https://github.com/kivymd/KivyMD/archive/master.zip","python3","asynckivy","asyncgui","exceptiongroup","materialyoucolor"]# 初始化時加載默認權限(移動到load_last_config之前)for perm in self.default_permissions:self.permissions_list.insert(tk.END, perm)# 初始化時加載默認依賴(在load_last_config之前)for dep in self.default_dependencies:self.dependencies_list.insert(tk.END, dep)self.load_last_config()  # 加載上次配置(會覆蓋默認值)def create_basic_settings(self, parent):frame = ttk.LabelFrame(parent, text="基本設置")frame.pack(fill="x", padx=5, pady=5)# 調整條目,移除源碼目錄entries = [("應用標題:", "title_entry", 30),("包名:", "package_entry", 30),("包域名:", "package_domain_entry", 30),("版本號:", "version_entry", 15),("包含擴展:", "include_exts_entry", 40)  # 僅保留包含擴展]for i, (label, var, width) in enumerate(entries):row = i // 2col = i % 2ttk.Label(frame, text=label).grid(row=row, column=col*2, sticky="w")entry = ttk.Entry(frame, width=width)entry.grid(row=row, column=col*2+1, padx=2, pady=2, sticky="ew")setattr(self, var, entry)# 確保包含擴展默認值初始化(保留文本僅修改顏色)self.include_exts_entry.delete(0, tk.END)self.include_exts_entry.insert(0, "py,png,jpg,kv,ttf")self.include_exts_entry.config(foreground="gray")# 調整焦點事件綁定self.include_exts_entry.bind("<FocusIn>", lambda e: self.clear_placeholder(self.include_exts_entry, "py,png,jpg,kv,ttf"))self.include_exts_entry.bind("<FocusOut>", lambda e: self.restore_placeholder(self.include_exts_entry, "py,png,jpg,kv,ttf"))def create_dependencies_section(self, parent):frame = ttk.LabelFrame(parent, text="依賴管理")frame.pack(fill="both", expand=True, padx=5, pady=5)# 列表高度調整self.dependencies_list = tk.Listbox(frame, height=5)self.dependencies_list.pack(fill="both", expand=True)# 按鈕布局btn_frame = ttk.Frame(frame)btn_frame.pack(fill="x")ttk.Button(btn_frame, text="添加依賴", command=self.add_dependency).pack(side=tk.LEFT)ttk.Button(btn_frame, text="刪除選中", command=self.remove_dependency).pack(side=tk.LEFT)def create_permissions_section(self, parent):frame = ttk.LabelFrame(parent, text="Android權限")frame.pack(fill="both", expand=True, padx=5, pady=5)self.permissions_list = tk.Listbox(frame, height=5)self.permissions_list.pack(fill="both", expand=True)btn_frame = ttk.Frame(frame)btn_frame.pack(fill="x")ttk.Button(btn_frame, text="添加權限", command=self.add_permission).pack(side=tk.LEFT)ttk.Button(btn_frame, text="刪除選中", command=self.remove_permission).pack(side=tk.LEFT)def create_file_selection(self, parent):frame = ttk.LabelFrame(parent, text="靜態文件包含")frame.pack(fill="both", expand=True, padx=5, pady=5)self.file_listbox = tk.Listbox(frame, height=8)self.file_listbox.pack(fill="both", expand=True)btn_frame = ttk.Frame(frame)btn_frame.pack(fill="x")ttk.Button(btn_frame, text="選擇文件", command=self.select_files).pack(side=tk.LEFT)ttk.Button(btn_frame, text="清除列表", command=self.clear_files).pack(side=tk.LEFT)def create_action_buttons(self, parent):btn_frame = ttk.Frame(parent)btn_frame.grid(row=1, column=0, columnspan=2, pady=5)ttk.Button(btn_frame, text="生成配置文件", command=self.generate_config).pack(side=tk.LEFT, padx=10)ttk.Button(btn_frame, text="初始化配置", command=self.reset_to_default).pack(side=tk.LEFT, padx=10)ttk.Button(btn_frame, text="退出", command=self.master.quit).pack(side=tk.LEFT, padx=10)def create_advanced_settings(self, parent):frame = ttk.LabelFrame(parent, text="顯示設置")frame.pack(fill="x", padx=5, pady=5)# 僅保留顯示相關設置ttk.Label(frame, text="屏幕方向:").grid(row=0, column=0, sticky="w")self.orientation_var = tk.StringVar(value="portrait")ttk.Combobox(frame, textvariable=self.orientation_var,values=["portrait", "landscape"], width=18).grid(row=0, column=1)ttk.Label(frame, text="全屏模式:").grid(row=1, column=0, sticky="w")self.fullscreen_var = tk.BooleanVar(value=False)ttk.Checkbutton(frame, variable=self.fullscreen_var).grid(row=1, column=1, sticky="w")# 以下是各功能方法實現def add_dependency(self):dep = simpledialog.askstring("添加依賴", "輸入Python依賴項:")if dep:self.dependencies_list.insert(tk.END, dep)def remove_dependency(self):for i in reversed(self.dependencies_list.curselection()):self.dependencies_list.delete(i)def add_permission(self):perm = simpledialog.askstring("添加權限", "輸入Android權限:")if perm:# 自動去除android.permission.前綴if perm.startswith("android.permission."):perm = perm[len("android.permission."):]self.permissions_list.insert(tk.END, perm)def remove_permission(self):for i in reversed(self.permissions_list.curselection()):self.permissions_list.delete(i)def select_files(self):files = filedialog.askopenfilenames(title="選擇靜態文件",filetypes=[("All files", "*.*")])for f in files:# 轉換為相對路徑并統一路徑分隔符rel_path = os.path.relpath(f).replace("\\", "/")self.file_listbox.insert(tk.END, rel_path)def clear_files(self):self.file_listbox.delete(0, tk.END)def save_current_config(self):config_data = {"title": self.title_entry.get(),"package": self.package_entry.get(),"version": self.version_entry.get(),"dependencies": list(self.dependencies_list.get(0, tk.END)),"permissions": list(self.permissions_list.get(0, tk.END)),"files": list(self.file_listbox.get(0, tk.END)),"package_domain": self.package_domain_entry.get(),"include_exts": self.include_exts_entry.get()}try:with open(self.config_path, "w", encoding='utf-8') as f:json.dump(config_data, f, ensure_ascii=False, indent=2)except Exception as e:messagebox.showwarning("配置保存失敗", f"保存配置時出錯: {str(e)}")def load_last_config(self):if os.path.exists(self.config_path):try:with open(self.config_path, encoding='utf-8') as f:config = json.load(f)# 處理可能包含前綴的歷史權限配置stored_permissions = config.get("permissions", [])cleaned_perms = []for p in stored_permissions:if p.startswith("android.permission."):cleaned_perms.append(p.split(".")[-1])else:cleaned_perms.append(p)combined_perms = list(set(cleaned_perms + self.default_permissions))self.permissions_list.delete(0, tk.END)for perm in combined_perms:self.permissions_list.insert(tk.END, perm)self.title_entry.insert(0, config.get("title", ""))self.package_entry.insert(0, config.get("package", ""))self.version_entry.insert(0, config.get("version", ""))# 處理依賴加載邏輯saved_deps = config.get("dependencies", [])if saved_deps:self.dependencies_list.delete(0, tk.END)  # 清空默認依賴for dep in saved_deps:self.dependencies_list.insert(tk.END, dep)for f in config.get("files", []):self.file_listbox.insert(tk.END, f)self.package_domain_entry.insert(0, config.get("package_domain", ""))# 處理包含擴展的加載邏輯saved_exts = config.get("include_exts", "")if saved_exts:self.include_exts_entry.delete(0, tk.END)self.include_exts_entry.insert(0, saved_exts)self.include_exts_entry.config(foreground="black")else:# 保留默認值但顯示為灰色self.include_exts_entry.delete(0, tk.END)self.include_exts_entry.insert(0, "py,png,jpg,kv,ttf")self.include_exts_entry.config(foreground="gray")except Exception as e:messagebox.showwarning("配置加載失敗", f"無法加載歷史配置: {str(e)}")def generate_config(self):try:# 固定源碼目錄為當前目錄source_dir = "."# 處理包含擴展(空值時使用默認)include_exts = self.include_exts_entry.get()if not include_exts or include_exts == "py,png,jpg,kv,ttf":include_exts = "py,png,jpg,kv,ttf"# 驗證必填字段required_fields = {"應用標題": self.title_entry.get(),"包名": self.package_entry.get(),"版本號": self.version_entry.get(),"包域名": self.package_domain_entry.get()}missing = [name for name, value in required_fields.items() if not value]if missing:messagebox.showwarning("缺少必填項", f"請填寫以下必填字段:\n{', '.join(missing)}")returnself.config["app"] = {"title": required_fields["應用標題"],"package.name": required_fields["包名"],"version": required_fields["版本號"],"package.domain": required_fields["包域名"],"source.dir": source_dir,  # 硬編碼為當前目錄"source.include_exts": include_exts,"log_level":2,"warn_on_root":1,"android.allow_backup":True,"osx.kivy_version":"1.9.1","osx.python_version":3}# 處理可選的文件包含配置include_patterns = self.file_listbox.get(0, tk.END)if include_patterns:self.config["app"]["source.include_patterns"] = ", ".join(include_patterns)else:self.config["app"]["#source.include_patterns"] = "(未配置文件包含模式)"# 添加默認注釋的Android配置self.config["app"]["#android.api"] = "33"self.config["app"]["#android.minapi"] = "21"self.config["app"]["#android.sdk"] = "24"self.config["app"]["#android.ndk"] = "23b"self.config["app"]["#android.ndk_api"] = "21"self.config["app"]["android.archs"] = "arm64-v8a, armeabi-v7a"# 修改默認權限列表(保持無前綴)default_permissions = ["ACCESS_NETWORK_STATE","INTERNET","CAMERA","BLUETOOTH","BLUETOOTH_ADMIN"]# 合并權限(直接使用無前綴格式)user_permissions = list(self.permissions_list.get(0, tk.END))all_permissions = list(set(default_permissions + user_permissions))# 新增依賴項配置(添加這部分代碼)requirements = list(self.dependencies_list.get(0, tk.END))if requirements:self.config["app"]["requirements"] = ", ".join(requirements)else:self.config["app"]["#requirements"] = "(未配置依賴項)"# 添加屏幕方向配置self.config["app"]["orientation"] = self.orientation_var.get()# 新增全屏配置(添加這行代碼)self.config["app"]["fullscreen"] = "1" if self.fullscreen_var.get() else "0"# Android權限配置(直接使用無前綴)self.config["app"]["android.permissions"] = ", ".join(all_permissions)# 保存文件save_path = filedialog.asksaveasfilename(defaultextension=".spec",filetypes=[("Buildozer spec", "*.spec")])if not save_path:  # 用戶取消保存returnwith open(save_path, "w") as f:self.config.write(f)# 保存當前配置self.save_current_config()messagebox.showinfo("成功", "配置文件已生成!")except Exception as e:messagebox.showerror("錯誤", f"生成配置失敗:{str(e)}")# 通用占位符處理方法def clear_placeholder(self, entry, default_text):if entry.get() == default_text:entry.config(foreground="black")def restore_placeholder(self, entry, default_text):if not entry.get().strip():entry.insert(0, default_text)entry.config(foreground="gray")def reset_to_default(self):# 清空所有輸入框self.title_entry.delete(0, tk.END)self.package_entry.delete(0, tk.END)self.package_domain_entry.delete(0, tk.END)self.version_entry.delete(0, tk.END)# 重置源碼目錄和擴展名self.source_dir_entry.delete(0, tk.END)self.source_dir_entry.insert(0, ".")self.source_dir_entry.config(foreground="gray")# 重置包含擴展self.include_exts_entry.delete(0, tk.END)self.restore_placeholder(self.include_exts_entry, "py,png,jpg,kv,ttf")# 重置依賴列表(完全恢復默認)self.dependencies_list.delete(0, tk.END)for dep in self.default_dependencies:self.dependencies_list.insert(tk.END, dep)# 重置權限列表(顯示默認權限)self.permissions_list.delete(0, tk.END)for perm in self.default_permissions:self.permissions_list.insert(tk.END, perm)# 清空所有列表(增加文件列表清除)self.file_listbox.delete(0, tk.END)# 重置顯示設置self.orientation_var.set("portrait")self.fullscreen_var.set(False)# 強制清空文件列表(新增)self.clear_files()# 刪除保存的配置文件if os.path.exists(self.config_path):try:os.remove(self.config_path)except Exception as e:messagebox.showwarning("配置清除失敗", f"無法刪除歷史配置: {str(e)}")if __name__ == "__main__":root = tk.Tk()root.geometry("600x700")app = BuildozerConfigTool(root)root.mainloop() 

成品

[app]
title = apply
package.name = bn
version = 0.0.1
package.domain = org.kivy
source.dir = .
source.include_exts = py,png,jpg,kv,ttf
log_level = 2
warn_on_root = 1
android.allow_backup = True
osx.kivy_version = 1.9.1
osx.python_version = 3
source.include_patterns = fonts/simkai.ttf
#android.api = 33
#android.minapi = 21
#android.sdk = 24
#android.ndk = 23b
#android.ndk_api = 21
android.archs = arm64-v8a, armeabi-v7a
requirements = kivy, requests, https://github.com/kivymd/KivyMD/archive/master.zip, python3, asynckivy, asyncgui, exceptiongroup, materialyoucolor
orientation = portrait
fullscreen = 0
android.permissions = BLUETOOTH, CAMERA, INTERNET, READ_EXTERNAL_STORAGE, BLUETOOTH_ADMIN, ACCESS_NETWORK_STATE, ACCESS_WIFI_STATE, QUERY_ALL_PACKAGES, WRITE_EXTERNAL_STORAGE, ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/78995.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/78995.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/78995.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MOOS-ivp使用(一)——水下機器人系統的入門與使用

MOOS-ivp使用&#xff08;一&#xff09;——水下機器人系統的入門與使用 MOOS-ivp&#xff08;Marine Operational Oceanographic System for Intelligent Vehicle Planning&#xff09;是專為水下機器人&#xff08;如AUV&#xff09;設計的開源框架。類似于ROS&#xff0c;…

電子病歷高質量語料庫構建方法與架構項目(智能質控體系建設篇)

引言 隨著人工智能技術的迅猛發展,醫療信息化建設正經歷著前所未有的變革。電子病歷作為醫療機構的核心數據資產,其質量直接關系到臨床決策的準確性和醫療安全。傳統的病歷質控工作主要依賴人工審核,存在效率低下、主觀性強、覆蓋面有限等問題。近年來,基于人工智能技術的…

react學習筆記4——React UI組件庫與redux

流行的開源React UI組件庫 material-ui(國外) 官網: http://www.material-ui.com/#/github: GitHub - mui/material-ui: Material UI: Comprehensive React component library that implements Googles Material Design. Free forever. ant-design(國內螞蟻金服) 官網: Ant…

GPU集群搭建

1. 硬件規劃與采購 GPU 服務器&#xff1a;挑選契合需求的 GPU 服務器&#xff0c;像 NVIDIA DGX 系列就不錯&#xff0c;它集成了多個高性能 GPU。網絡設備&#xff1a;高速網絡設備不可或缺&#xff0c;例如萬兆以太網交換機或者 InfiniBand 交換機&#xff0c;以此保證節點…

ZYNQ 純PL端邏輯資源程序固化流程

ZYNQ 純PL端邏輯資源程序固化 ZYNQ的程序固化流程比傳統的FPGA固化流程復雜很多&#xff0c;Vivado生成的bit文件無法直接固化在ZYNQ芯片中。因為ZYNQ 非易失性存儲器的引腳&#xff08;如 SD 卡、QSPI Flash&#xff09;是 ZYNQ PS 部分的專用引腳。這些非易失性存儲器由 PS …

[計算機科學#6]:從鎖存器到內存,計算機存儲的構建與原理

【核知坊】&#xff1a;釋放青春想象&#xff0c;碼動全新視野。 我們希望使用精簡的信息傳達知識的骨架&#xff0c;啟發創造者開啟創造之路&#xff01;&#xff01;&#xff01; 內容摘要&#xff1a;在上一篇文章中&#xff0c;我們深入了解了計算機如…

如何刪除Google Chrome中的所有歷史記錄【一鍵清除】

谷歌瀏覽器記錄了用戶訪問過的網站。這方便了查找&#xff0c;但有時也需要清理。刪除所有歷史記錄很簡單&#xff0c;只要按照以下步驟操作。 1. 打開谷歌瀏覽器 首先要啟動谷歌瀏覽器。點擊右上角的三個點&#xff0c;進入主菜單。 2. 進入歷史記錄界面 在菜單中找到“歷史…

關于瀏覽器對于HTML實體編碼,urlencode,Unicode解析

目錄 HTML實體編碼 URL編碼 Unicode編碼 解析層次邏輯 為什么<script></script>不可以編碼符號 為什么不能編碼JavaScript:協議 為什么RCDATA標簽中的都會被解析成文本 為什么HTML編碼了<>無法執行 HTML實體編碼 通過特殊語法&#xff08;<、>…

【數據分享】2020年中國高精度森林覆蓋數據集(免費獲取)

森林作為全球陸地生態系統的主體&#xff0c;分布面積廣、結構復雜&#xff0c;承擔著調節氣候、維護生態安全、改善環境等方面的重要作用。我國的森林資源豐富&#xff0c;據《中國森林資源報告&#xff1a;2014—2018》統計&#xff0c;我國森林覆蓋率已經達到23.04%。森林覆…

C語言學習之動態內存的管理

學完前面的C語言內容后&#xff0c;我們之前給內存開辟空間的方式是這樣的。 int val20; char arr[10]{0}; 我們發現這個方式有兩個弊端&#xff1a;空間是固定的&#xff1b;同時在聲明的時候必須指定數組的長度&#xff0c;一旦確定了大小就不能調整的。 而實際應用的過程中…

【深度學習-Day 2】圖解線性代數:從標量到張量,理解深度學習的數據表示與運算

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

首頁數據展示

排版 現在做首頁的排版&#xff0c;依舊是偷antd里面的東西 使用card包裹list的樣式 import React from react import axios import { Card, Col, Row, List } from antd import { EditOutlined, EllipsisOutlined, SettingOutlined } from ant-design/icons; import { Avat…

使用Set和Map解題思路

前言 Set和Map這兩種數據結構,在解決一些題上&#xff0c;效率很高。跟大家簡單分享一些題以及如何使用Set和Map去解決這些題目。 題目鏈接 136. 只出現一次的數字 - 力扣&#xff08;LeetCode&#xff09; 138. 隨機鏈表的復制 - 力扣&#xff08;LeetCode&#xff09; 舊…

嘗試leaflet+webassemly

前言 筆者在github發現rust版本的leaflet&#xff0c;發現是用wasm-bindgen包裝的&#xff0c;嘗試使用一下 Issues slowtec/leaflet-rshttps://github.com/slowtec/leaflet-rs 正文 準備 新建一個react項目&#xff0c;安裝rsw依賴 pnpm i -D vite-plugin-rsw cargo ins…

機器學習實戰,天貓雙十一銷量與中國人壽保費預測,使用多項式回歸,梯度下降,EDA數據探索,彈性網絡等技術

前言 很多同學學機器學習時總感覺&#xff1a;“公式推導我會&#xff0c;代碼也能看懂&#xff0c;但自己從頭做項目就懵”。 這次我們選了兩個小數據集&#xff0c;降低復雜度&#xff0c;帶大家從頭開始進行分析&#xff0c;建模&#xff0c;預測&#xff0c;可視化等&…

SQL數據庫系統全解析:從入門到實踐

一、數據庫世界入門指南 在數字時代&#xff0c;數據就像新時代的石油&#xff0c;而數據庫系統就是儲存和管理這些寶貴資源的倉庫。對于初學者來說&#xff0c;理解數據庫的基本概念是邁入這個領域的第一步。 數據庫本質上是一個有組織的數據集合&#xff0c;它允許我們高效…

【大模型】圖像生成:StyleGAN3:生成對抗網絡的革命性進化

深度解析StyleGAN3&#xff1a;生成對抗網絡的革命性進化 技術演進與架構創新代際技術對比StyleGAN3架構解析 環境配置與快速入門硬件要求安裝步驟預訓練模型下載 實戰全流程解析1. 圖像生成示例2. 自定義數據集訓練3. 潛在空間操作 核心技術深度解析1. 連續信號建模2. 傅里葉特…

PHP-Cookie

Cookie 是什么&#xff1f; cookie 常用于識別用戶。cookie 是一種服務器留在用戶計算機上的小文件。每當同一臺計算機通過瀏覽器請求頁面時&#xff0c;這臺計算機將會發送 cookie。通過 PHP&#xff0c;您能夠創建并取回 cookie 的值。 設置Cookie 在PHP中&#xff0c;你可…

“Everything“工具 是 Windows 上文件名搜索引擎神奇

01 Everything 和其他搜索引擎有何不同 輕量安裝文件。 干凈簡潔的用戶界面。 快速文件索引。 快速搜索。 快速啟動。 最小資源使用。 輕量數據庫。 實時更新。 官網&#xff1a;https://www.voidtools.com/zh-cn/downloads/ 通過網盤分享的文件&#xff1a;Every…

CSS:選擇器-基本選擇器

文章目錄 1、通配選擇器2、元素選擇器3、類選擇器4、ID選擇器 1、通配選擇器 2、元素選擇器 3、類選擇器 4、ID選擇器