Kivyを使用したシンプルで甘いアプリ



記事の最初のバージョンの試みが失敗した後、記事で提供されているサンプルプログラムの巨大なデザインのために材料が採掘されたとき(記事を削除する必要がありました)、すべての欠点を考慮し、テストアプリケーションの新しいバージョンを引用しました。







おそらくあなたにとってはニュースになるでしょうが、Kivyフレームワークを使用してAndroidのJava開発者が利用できる機能を備えたモバイルアプリケーションの開発は、単純なだけでなく、非常に簡単です! これはまさに、Python + Kivyを使用してプロジェクトを作成する際に順守するルールです。開発はできるだけシンプルで高速でなければなりません。 指のスナップのように。







与えられた情報は初心者向けではありません;何を、どこで、どこで指で説明するつもりはありません。 この記事を読んだ人は、その資料を理解するのに十分な知識を持っていると思います。 さらに、Kivyは、先ほど書いたように、非常にシンプルなフレームワークと、使用例を含むすべてのドキュメントがソースにあります!







最後の記事では、Kivyでの実装におけるClean Masterアプリケーションのいくつかの画面が検討されました。 今日は、自由時間に取り組んでいるドラフトアプリケーションの1つを紹介します。













彼らは、Kivyはよくできた工芸品にのみ適していると言い、それを使って本格的なアプリケーションを作ることはできません。 彼らを言うように、私はあなたを幸せにする(または動揺させる)ために急いでいます-彼らが言うように、この果物を調理する方法を知らない人々(Kivy)。







ただし、コーヒータバコ、3番目のパイソン付きテラリウム、鳥、または果物-Kivyといくつかの脳が必要です。 後者の存在は大歓迎です! githubに移動してウィザードをダウンロードし、Kivy + Python3フレームワーク用の新しいプロジェクトを作成します (はい、Python2の使用を完全に拒否しました。これをお勧めします)。 解凍し、ウィザードでフォルダーに移動して実行します:







python3 main.py name_project path_to_project -repo repo_project_on_github
      
      





プロジェクトのgithubにリポジトリがある場合。







または







 python3 main.py name_project path_to_project
      
      





githubリポジトリが利用できない場合。







この場合、作成後、main.pyプロジェクトファイルを開いて編集し、バグレポート機能を手動で送信します。













そのため、結果として、次のディレクトリ構造を持つデフォルトのKivyプロジェクトを取得します。













別途、Libsディレクトリを検討する必要があります。













他のプロジェクトディレクトリにはコメントは不要です。 作成されたプロジェクトには、メイン画面と設定画面の2つの画面があります。













必要なのは、メイン画面を使用することです。つまり、Libs / uixディレクトリのstartscreen.pyファイルを置き換え、Libs / uix / kvフォルダーに新しいstartscreen.kv画面レイアウトファイルを作成し、ベースクラスprogram.pyを編集します。新しいインポートとコンパニオンクラスがある場合は追加します。







メイン画面で使用されるカスタムボタンから始めましょう。













はい、Kivy自体にはJavaのインターフェイスデザインを構築するための標準要素は多くありませんが、Kivyを使用すると、自分で必要なウィジェットを完全に設計およびアニメーション化できます。 それはすべてあなたの想像の境界に依存します。







Libs / uixディレクトリにcustombutton.pyファイルを作成し、その中にボタンのクラスを定義します。







custombutton.py
 import os from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.lang import Builder from kivy.properties import StringProperty, ObjectProperty, ListProperty from . imagebutton import ImageButton root = os.path.split(__file__)[0] Builder.load_file('{}/kv/custombutton.kv'.format( root if root != '' else os.getcwd()) ) class CustomButton(BoxLayout, Button): icon = StringProperty('') icon_map = StringProperty('') icon_people = StringProperty('') text = StringProperty('') button_color = ListProperty([0, 0, 0, .2]) text_color = ListProperty([0, 0, 0, .1]) events_callback = ObjectProperty(None)
      
      





Libs / uix / kvディレクトリのボタンレイアウト-custombutton.kvファイル:







custombutton.kv
 #:kivy 1.9.1 <CustomButton>: id: root.text padding: 5 size_hint_y: None height: 60 on_release: root.events_callback(root.text) canvas: #   Color: rgba: root.button_color Rectangle: pos: self.x + 2.5, self.y - 3 size: self.size #   Color: rgba: [1, 1, 1, 1] Rectangle: pos: self.pos size: self.size Image: source: root.icon size_hint: .2, 1 Label: markup: True text: root.text text_size: self.width - 70, None color: root.text_color BoxLayout: orientation: 'vertical' size_hint: .1, 1 spacing: 6 ImageButton: source: root.icon_people on_release: root.events_callback({'people': root.text}) ImageButton: source: root.icon_map on_release: root.events_callback({'map': root.text})
      
      





ロケーション画面のカスタムボタン:













custommenu.py
 import os from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder from kivy.properties import ListProperty, StringProperty, ObjectProperty root = os.path.split(__file__)[0] Builder.load_file('{}/kv/custommenu.kv'.format( root if root != '' else os.getcwd()) ) class CustomMenuItem(BoxLayout): background_item = ListProperty([.1, .1, .1, 1]) text_color = ListProperty([.1, .1, .1, 1]) icon_item = StringProperty('') text_item = StringProperty('') id_item = StringProperty('') events_callback = ObjectProperty(None)
      
      





custommenu.kv
 #:kivy 1.9.1 #:import ImageButton Libs.uix.imagebutton.ImageButton <CustomMenuItem>: orientation: 'vertical' canvas: Color: rgba: root.background_item Rectangle: pos: self.pos size: self.size ImageButton: source: root.icon_item on_release: root.events_callback(root.id_item.split('.')[0]) Label: text: root.text_item color: root.text_color font_size: '19sp'
      
      





また、ImageButtonクラス(画像付きのボタン)をバナーに使用します。 クラスはUIであるため、Libs / uixディレクトリにimagebutton.pyファイルを配置しました。







imagebutton.py
 from kivy.uix.image import Image from kivy.uix.behaviors import ButtonBehavior class ImageButton(ButtonBehavior, Image): pass
      
      





次に、プログラムのメイン画面で広告バナーを変更するためのクラスが必要です。 このテストアプリケーションの例では、広告バナー付きのポスターをプロジェクトのローカルフォルダーに配置します。 Libs / programclassアプリケーションクラスディレクトリにshow_banners.pyファイルを作成します。







show_banners.py
 import os from kivy.uix.boxlayout import BoxLayout from Libs.uix.imagebutton import ImageButton class ShowBanners(object): '''       .''' def __init__(self): self.banner_list = os.listdir( '{}/Data/Images/banners'.format(self.directory) ) #    . self.directions = ('up', 'down', 'left', 'right') def show_banners(self, interval): if self.screen.ids.screen_manager.current == '': name_banner = self.choice(self.banner_list) box_banner = BoxLayout() new_banner = ImageButton( id=name_banner.split('.')[0], source='Data/Images/banners/{}'.format(name_banner), on_release=self.press_banner ) box_banner.add_widget(new_banner) name_screen = name_banner banner = self.Screen(name=name_screen) banner.add_widget(box_banner) self.screen.ids.banner_manager.add_widget(banner) effect = self.choice(self.effects_transition) direction = self.choice(self.directions) if effect != self.SwapTransition: self.screen.ids.banner_manager.transition = effect( direction=direction ) else: self.screen.ids.banner_manager.transition = effect() self.screen.ids.banner_manager.current = name_screen self.screen.ids.banner_manager.screens.pop() def press_banner(self, instance_banner): if isinstance(instance_banner, str): print(instance_banner) else: print(instance_banner.id)
      
      





このクラスは、banner_managerスクリーンマネージャーでバナーを設定することで、バナー付きの画面を単に変更します。













作成したクラスのインポートを、初期化ファイルのprogramclassクラスライブラリに追加することを忘れないでください。













基本のprogram.pyファイルにポスター変更アニメーション用のシェーダーセットをインポートします。













アプリケーションのメイン画面の実装:







startscreen.py
 import os from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder from kivy.properties import ObjectProperty, ListProperty, StringProperty from Libs.uix.custombutton import CustomButton root = os.path.split(__file__)[0] root = root if root != '' else os.getcwd() class StartScreen(BoxLayout): events_callback = ObjectProperty(None) '''   .''' core = ObjectProperty(None) '''module 'Libs.programdata' ''' color_action_bar = ListProperty( [0.4, 0.11764705882352941, 0.2901960784313726, 0.5607843137254902] ) ''' ActionBar.''' color_body_program = ListProperty( [0.15294117647058825, 0.0392156862745098, 0.11764705882352941, 1] ) '''   .''' color_tabbed_panel = ListProperty( [0.15294117647058825, 0.0392156862745098, 0.11764705882352941, 1] ) '''  tabbed panel.''' title_previous = StringProperty('') ''' ActionBar.''' tabbed_text = StringProperty('') '''   tabbed panel.''' Builder.load_file('{}/kv/startscreen.kv'.format(root)) def __init__(self, **kvargs): super(StartScreen, self).__init__(**kvargs) self.ids.custom_tabbed.bind(on_ref_press=self.events_callback) # C . for name_shop in self.core.dict_shops.keys(): self.ids.shops_list.add_widget( CustomButton( text=self.core.dict_shops[name_shop], icon='Data/Images/shops/{}.png'.format(name_shop), icon_people='Data/Images/people.png', icon_map='Data/Images/mapmarker.png', events_callback=self.events_callback, ) )
      
      





startscreen.kv
 #: kivy 1.9.1 #: import StiffScrollEffect Libs.uix.garden.stiffscroll.StiffScrollEffect <StartScreen> orientation: 'vertical' canvas: Color: rgb: root.color_body_program Rectangle: pos: self.pos size: self.size ActionBar: id: action_bar canvas: Color: rgb: root.color_action_bar Rectangle: pos: self.pos size: self.size ActionView: id: action_view ActionPrevious: id: action_previous app_icon: 'Data/Images/logo.png' title: root.title_previous with_previous: False on_release: root.events_callback('navigation_drawer') ActionButton: icon: 'Data/Images/trash_empty.png' ActionButton: icon: 'Data/Images/search.png' Label: id: custom_tabbed text: root.tabbed_text bold: True markup: True size_hint: 1, .35 text_size: self.width - 40, None canvas.before: Color: rgb: root.color_tabbed_panel Rectangle: pos: self.pos size: self.size ScreenManager: id: screen_manager size_hint: 1, 8 Screen: ScreenManager: id: banner_manager size_hint: 1, .38 pos_hint: {'top': 1} ScrollView: effect_cls: StiffScrollEffect size_hint_y: None height: root.height // 1.8 pos_hint: {'top': .62} GridLayout: id: shops_list cols: 1 spacing: 5 padding: 5 size_hint_y: None height: self.minimum_height
      
      





ご覧のとおり、TabbedPanelは使用していません。Androidでの標準実装はあまり美しくないからです。 Label + refに置き換えられました:



















基本クラスプログラム:







program.py
 import os import sys from random import choice from kivy.app import App from kivy.uix.screenmanager import Screen, SlideTransition, SwapTransition from kivy.core.window import Window from kivy.config import ConfigParser from kivy.clock import Clock from kivy.utils import get_hex_from_color, get_color_from_hex from kivy.properties import ObjectProperty, NumericProperty from Libs.uix.kdialog import KDialog, BDialog, Dialog from Libs.uix.startscreen import StartScreen from Libs.uix.custommenu import CustomMenuItem from Libs.uix.navigationmenu import NavigationMenu from Libs.uix.garden.navigationdrawer import NavigationDrawer #  . from Libs import programclass as prog_class from Libs import programdata as core from Libs.manifest import Manifest #    . Dialog.background_image_buttons = core.image_buttons Dialog.background_image_shadows = core.image_shadows Dialog.background = core.decorator class Program(App, prog_class.ShowPlugin, prog_class.ShowBanners, prog_class.SearchShop, prog_class.ShowLicense, prog_class.ShowLocations): ''' .''' start_screen = ObjectProperty(None) ''':attr:`start_screen` is a :class:`~Libs.uix.startscreen.StartScreen`''' screen = ObjectProperty(None) ''':attr:`screen` is a :class:`~Libs.uix.startscreen.StartScreen`''' window_text_size = NumericProperty(15) def __init__(self, **kvargs): super(Program, self).__init__(**kvargs) Window.bind(on_keyboard=self.events_program) #     programclass. self.Screen = Screen self.Clock = Clock self.CustomMenuItem = CustomMenuItem self.KDialog = KDialog self.BDialog = BDialog self.Manifest = Manifest self.SwapTransition = SwapTransition self.choice = choice self.get_color_from_hex = get_color_from_hex self.get_hex_from_color = get_hex_from_color self.core = core self.name_program = core.string_lang_title self.navigation_drawer = NavigationDrawer(side_panel_width=230) self.current_open_tab = core.string_lang_tabbed_menu_shops self.shop = False #   self.open_dialog = False #    self.effects_transition = (SlideTransition, SwapTransition) #  . self.shops = core.dict_shops.keys() #  . self.locations = [ location.split('.')[0].lower() for location in os.listdir( '{}/Data/Images/locations'.format(core.prog_path))] def build_config(self, config): config.adddefaultsection('General') config.setdefault('General', 'language', '') config.setdefault('General', 'theme', 'default') def build(self): self.title = self.name_program #    self.icon = 'Data/Images/logo.png' #    self.use_kivy_settings = False self.config = ConfigParser() self.config.read('{}/program.ini'.format(core.prog_path)) self.set_var_from_file_settings() #   . self.start_screen = StartScreen( color_action_bar=core.color_action_bar, color_body_program=core.color_body_program, color_tabbed_panel=core.color_tabbed_panel, tabbed_text=core.string_lang_tabbed_menu.format( TEXT_SHOPS=core.string_lang_tabbed_menu_shops, TEXT_LOCATIONS=core.string_lang_tabbed_menu_locations, COLOR_TEXT_SHOPS=get_hex_from_color(core.color_action_bar), COLOR_TEXT_LOCATIONS=core.theme_text_color), title_previous=self.name_program[1:], events_callback=self.events_program, core=core ) self.screen = self.start_screen navigation_panel = NavigationMenu( events_callback=self.events_program, items=core.dict_navigation_items ) Clock.schedule_interval(self.show_banners, 4) self.navigation_drawer.add_widget(navigation_panel) self.navigation_drawer.anim_type = 'slide_above_anim' self.navigation_drawer.add_widget(self.start_screen) return self.navigation_drawer def set_var_from_file_settings(self): '''      program.ini.''' self.language = core.select_locale[ self.config.get('General', 'language') ] def set_current_item_tabbed_panel(self, color_current_tab, color_tab): self.screen.ids.custom_tabbed.text = \ core.string_lang_tabbed_menu.format( TEXT_SHOPS=core.string_lang_tabbed_menu_shops, TEXT_LOCATIONS=core.string_lang_tabbed_menu_locations, COLOR_TEXT_SHOPS=color_tab, COLOR_TEXT_LOCATIONS=color_current_tab ) def events_program(self, *args): '''  .''' if self.navigation_drawer.state == 'open': self.navigation_drawer.anim_to_state('closed') if len(args) == 2: #   event = args[1] else: #    try: _args = args[0] event = _args if isinstance(_args, str) else _args.id except AttributeError: #    event = args[1] if core.PY2: if isinstance(event, unicode): event = event.encode('utf-8') if event == core.string_lang_settings: pass elif event == core.string_lang_exit_key: self.exit_program() elif event == core.string_lang_license: self.show_license() elif event == core.string_lang_plugin: self.show_plugins() elif event in self.locations: print(event) elif event == 'search_shop': self.search_shop() elif event == 'navigation_drawer': self.navigation_drawer.toggle_state() elif event == core.string_lang_tabbed_menu_locations: self.show_locations() elif event == core.string_lang_tabbed_menu_shops: self.back_screen(event) elif event == 'obi_banner': self.press_banner(event) elif event in (1001, 27): self.back_screen(event) elif event in self.shops: print(event) return True def back_screen(self, event): ''' .''' #  BackKey   . if self.screen.ids.screen_manager.current == '': if event in (1001, 27): self.exit_program() return if len(self.screen.ids.screen_manager.screens) != 1: self.screen.ids.screen_manager.screens.pop() self.screen.ids.screen_manager.current = \ self.screen.ids.screen_manager.screen_names[-1] #    . #self.screen.ids.action_previous.title = self.screen.ids.screen_manager.current #     item_tabbed_panel. self.set_current_item_tabbed_panel( core.theme_text_color, get_hex_from_color(core.color_action_bar) ) def exit_program(self, *args): def dismiss(*args): self.open_dialog = False def answer_callback(answer): if answer == core.string_lang_yes: sys.exit(0) dismiss() if not self.open_dialog: KDialog(answer_callback=answer_callback, on_dismiss=dismiss, separator_color=core.separator_color, title_color=get_color_from_hex(core.theme_text_black_color), title=self.name_program).show( text=core.string_lang_exit.format(core.theme_text_black_color), text_button_ok=core.string_lang_yes, text_button_no=core.string_lang_no, param='query', auto_dismiss=True ) self.open_dialog = True def on_pause(self): '''   ''    .      ''' return True def on_resume(self): print('on_resume') def on_stop(self): print('on_stop')
      
      





ローカリゼーションファイル(データ/言語/russian.txt、グラフィックリソースのパッケージ化、Data / Themes / default / default.iniファイル内のアプリケーションの配色、programdata.py内のデータの作成、Navigation Drawerメニュー)を残します(考慮されません)簡単な小さなこと、テスト例を実行します。







 python3 main.py
      
      





...そして、この写真を取得します:













gifの品質が低いため、画面のアニメーションはあまり見えませんが、これはそれほど重要ではありません。 デバイス上プロジェクトソースからサンプルをテストする人は、すぐに欠陥を強調します。広告バナーのサイズを、比率を歪めずにすべての画面解像度に調整するアルゴリズムをまだ実装していません。 また、アプリケーションをテストできないため、エミュレータはプログラムで最適なフォントサイズを見つけることができませんでしたが、ボタンアニメーションはありません。ライブラリはまだ開発中であるため、kdialogダイアログボックスで作業するには不十分です。







しかし、このすべてにもかかわらず、この記事は、私のような、Kivyのようなすばらしいフレームワークを愛し、使用している人々に役立つと思います!










All Articles