iOSおよびAndroid用の組み込みの時計アプリを模倣するアプリ。それは2つの部分に分かれています:
- インタラクションのないデジタル時計、Kivyのイベント駆動型(event-driven)メソッドの簡単な説明、タイマー機能の導入、および継続的な更新。
- インタラクティブなストップウォッチ機能により、スムーズなアダプティブレイアウトを設計します。
学習の概要:
- Kivy言語基盤、DSL(domain-specific language)処理コンポーネント(ウィジェット)
- Kivyレイアウト
- カスタムフォントとテキストスタイル
- イベント管理
アプリの最終的な効果は次のとおりです。コードは60行のみで、PythonコードとKivyコードの半分です。
出発点
kivyにhelloworld
少し変更を加えます。
# %load ../0_Hello/main.py
from kivy.app import App
class ClockApp(App):
pass
if __name__ == "__main__":
ClockApp().run()
レイアウトコンテナを追加すると、BoxLayout
後でコンポーネントを追加できます。
# clock.kv
BoxLayout:
orientation: 'vertical'
Label:
text: '00:00:00'
BoxLayout
コンテナには、水平または垂直に積み重ねられた複数のサブコンポーネントを含めることができます。以来kv
唯一のサブコンポーネントがあり、BoxLayout
それはすべてのスペースを埋めるだろう。
main.py
ファイルが実行されると、Kivyが自動的に呼び出されますclock.kv
。クラス名はClockApp
、.kv
ファイル名はclock
、クラス名は小文字で削除されApp
ます。
新UI
フラットデザインパラダイム(フラットデザインパラダイム)は本格化しており、iOS7およびWin8で登場した、Web、モバイル、およびデスクトップアプリケーションの分野をカバーしています。インターネット企業もそれに続き、Bootstrapなどの他のHTML5フレームワークと同様に、Google I / O2014でマテリアルデザインをリリースしました。
フラットなデザインは、見た目よりもコンテンツを強調し、リアルな写真の影や詳細なテクスチャを無視し、純粋な色とシンプルな幾何学的形状をサポートします。アカデミックなスキューモーフィズムデザインよりもシンプルな手続き型の作成を強調し、前者は視覚効果と芸術的感覚を豊かにする傾向があります。
シミュレーションは、ユーザーインターフェイス設計の主流の方法です。アプリケーションは現実世界の一部であると考えてください。たとえば、ボタン付きの電卓アプリは、ユーザーエクスペリエンスの向上に役立つ、安価で素材の電卓にする必要があります(使用者によって異なります)。
今日では、視覚的な詳細を放棄し、シンプルで合理化されたインターフェイスに切り替えることはコンセンサスのようです。一方で、色とりどりのフレームだけで衝撃的な作品を作るのはとても難しいです。フラットデザインが優れたテキストレイアウトの代名詞となった理由は、テキストがUIデザインの重要な部分になっているため、テキストの見栄えを良くする必要があるためです。
デザインのインスピレーション
Android 4.1 JellyBeanの時計のデザインを模倣します。フォントはGoogleのRobotoフォントで、Android 4.0 Ice Cream SandwichDroidフォントに代わるものです。
カスタムフォントをロードする
KivyのデフォルトはDroidSansフォントであり、font_name
カスタムフォントはプロパティを介して設定できます。フォントは1つだけで、.ttf
ファイル名を直接入力できます。
# clock.kv
Label:
font_name: 'Loster.ttf'
ただし、複数のフォントが必要な場合は、1つの属性だけでは不十分です。異なるフォントはすべて単一のファイルであり、属性の後にはファイル名のみを続けることができるためです。LabelBase.register
以下に示すように、複数のフォントを含むメソッドを使用して、複数のフォントを受け入れることができます。
LabelBase.register(
name="Roboto",
fn_regular="Roboto-Regular.ttf",
fn_bold="Roboto-Bold.ttf",
fn_italic="Roboto-Italic.ttf",
fn_bolditalic="Roboto-BoldItalic.ttf",
)
改善後、パーツのfont_name
プロパティに複数のカスタムフォントを設定できます。ただし、この方法には2つの制限があります。
- KivyはTrueType
.ttf
フォントのみを受け入れます。OpenType.otf
またはWebフォントの.woff
場合は、最初に変換する必要があります。 - ノーマル、イタリック、ボールド、およびボールドイタリックの4つのスタイルのフォントが最大値を持ちます。DroidSansなどの古いフォントで問題ありません。ただし、新しいフォントには4〜20を超えるスタイルがあり、高さやその他の特性も異なります。Robotoには少なくとも12のスタイルがあります。
2番目のポイントでは、アプリのフォントを選択するときに12のスタイルすべてを含める必要があります。そうすると、アプリのサイズが大きくなります。Robotoフォントのサイズは1.7Mです。
この例では、明るい色(Roboto-Thin.ttf
)と太字(Roboto-Medium.ttf
)の2つのスタイルのみが必要です。
from kivy.core.text import LabelBase
LabelBase.register(
name="Roboto", fn_regular="Roboto-Thin.ttf", fn_bold="Roboto-Medium.ttf"
)
下のフォントを使って、Label
後ろに置いてみましょう。
# clock.kv
Label:
text: '00:00:00'
font_name: 'Roboto'
font_size: 60
フォントフォーマット
マークアップ言語は間違いなくHTMLです。Kivyは、[]をラベルとして使用して、別のBBCodeマークアップ言語を実装します。
BBCodeタグ | テキストへの影響 |
---|---|
[b] … [/ b] | テキストへの影響 |
[i] … [/ i] | イタリック |
[font = Lobster] … [/ font] | フォントを変更する |
[color =#FF0000] … [/ color] | CSSのような構文で色を設定する |
[サブ] … [/サブ] | 下付き文字(行の下のテキスト) |
[sup] … [/スープ] | 上付き文字(行の上のテキスト) |
[ref = name] … [/ ref] | <a href="..."> HTMLのクリック可能なゾーン |
[アンカー=名前] | <a name="..."> HTMLでの名前付きの場所 |
Kivyの急速な開発により、上記のコンテンツは決して最終バージョンではありません。詳細については、kivyのドキュメントを参照してください。
図2をもう一度見てください。時間数を太字にする効果は、簡単に実現できます。
# clock.kv
Label:
text: '[b]00[/b]:00:00'
markup: True
KivyのBBCodeは、マークアッププロパティをTrueに設定する必要があります。
行全体を太字にする場合は、bold属性を直接Trueに設定できます。他のイタリック、色、フォント、およびサイズは同じです。
背景色を変更する
Window
オブジェクトの属性であるウィンドウの背景色を調整してみましょう。__name__ == '__main__'
後ろにコードを追加できます:
from kivy.core.window import Window
from kivy.utils import get_color_from_hex
Window.clearcolor = get_color_from_hex("#101216")
この関数でget_color_from_hex
は、CSS RGBカラー値(#RRGGBB
)やその他の関数を使用できます。
表示時間
ほとんどのUIフレームワークはイベント駆動型であり、Kivyも例外ではありません。この方法は通常のプログラムよりも単純です-イベント駆動型コードは常にメインループに戻る必要があります(main loop
);ただし、これはユーザーの動作(マウスをクリックしてウィンドウを変更する)を処理できず、インターフェイスがフリーズします(freeze
)、Windowsが頻繁にこのように程序停止响应
。
つまり、プログラムに無限ループを追加することはできません。
# Don't do this
while True:
update_time() # some function that displays time
sleep(1)
理論的には実現可能ですが、システムまたはユーザーがプロセスをシャットダウンするまで、UIは実際には応答を失います。メインループは常にKivy内で実行されていることを忘れないでください。これは、イベントや計算機を介して使用できます。
イベント駆動型とは、ユーザー入力、ネットワーク動作、タイムアウトなど、さまざまなイベントに応答する必要があることも意味します。
多くのプログラムが監視する一般的なイベントの1つはApp.on_start
クラスで定義され、アプリの初期化時に呼び出されます。もう1つの一般的なon_press
方法は、ユーザーが他のボタンをクリック、タップ、または操作したときに有効になることです。
時間とタイマーを通して、Kivy独自のClockクラスを使用して目的の機能を実現できます。2つの方法:
Clock.schedule_once
:一定時間後に1回実行Clock.schedule_interval
:定期運転
そしてJavaScript
window.setTimeout
などでwindow.setInterval
。実際、APIが完全に異なっていても、KivyとJSは非常に似ています。
Clock
すべてのタイミングイベントはKivyのメインループの一部です。このメソッドはスレッドとは異なるため、ブロッキング関数を呼び出すと、他のイベントが時間内にウェイクアップされない場合があります。
画面上の時刻を更新します
時刻Label
を表示するウィジェットにアクセスするには、ウィジェットに1を指定しid
、id
属性を介してウィジェットを取得する必要があります。これは、Web開発と同様です。
# clock.kv
Label:
id: time
次にroot.ids.time
、のLabel
メンバーにアクセスできます。こちらroot
ですBoxLayout
。
ClockApp
クラスupdate_time
にメソッドを追加して、時刻を更新します。
def update_time(self, nap):
self.root.ids.time.text = strftime("[b]%H[/b]:%M:%S")
更新後、毎秒プログラムを更新する別のスケジューリング関数を追加します。
def on_start(self):
Clock.schedule_interval(self.update_time, 1)
プログラムを実行して、更新が開始されたかどうかを確認します。コードは次のように表示されます。
# %load main.py
from kivy.app import App
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.utils import get_color_from_hex
from time import strftime
class ClockApp(App):
def update_time(self, nap):
self.root.ids.time.text = strftime("[b]%H[/b]:%M:%S")
def on_start(self):
Clock.schedule_interval(self.update_time, 1)
if __name__ == "__main__":
Window.clearcolor = get_color_from_hex("#301216")
ClockApp().run()
Pythonのtime
標準ライブラリstrftime
関数をKivyのBBCodeと組み合わせて、C言語の文字列を形成する方法を見てみましょう。
# %load clock.kv
BoxLayout:
orientation: 'vertical'
Label:
text: '[b]00[/b]:00:00'
markup: True
id: time
属性を持つウィジェットのバインド
IDバインディングコンポーネントに加えて、新しい属性を作成してkvファイルにバインドすることもできます。これは、DRYの原則に沿ったものであり、コードを数行追加するだけです。次のように:
#main.py
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
class ClockLayout (BoxLayout ):
time_prop = ObjectProperty (None )
このコードでは、ウィジェットを接続するBoxLayout
カスタム属性を持つ新しいルートウィジェットクラスを作成しました。time_prop
Label
でclock.kv
、ファイル、我々は属性を結合しid
て、カスタム属性は、デフォルトの属性と同じ構文を持っています:
#%load clock.kv
ClockLayout :
time_prop : time
Label :
id : time
このようにして、Pythonコードid
は、それを知らなくてもLabel
パーツを接続し、新しい属性を使用できますroot.time_prop.text = "demo"
。
これにより、コードの移植性が高まり、リファクタリング中のPythonコードの同期の問題が解消されます。属性に依存したりroot.ids
、Pythonコードに接続したりすることは、コードスタイルの問題であり、重要ではありません。他のKivyプロパティの使用法は、データバインディングを容易にするために後で導入されます。
レイアウトベース
KivyはLayout
レイアウトにたくさんのクラスを提供します。Layout
これはWidget
、クラスのサブクラスであるコンテナクラスでもあります。各レイアウトは、そのサブカテゴリの位置とサイズに影響します。
このアプリでは、以下に示すように、UIは非常に単純で、魔法は必要ありません。
この種のインターフェースを行うにはBoxLayout
、1次元グリッドが必要です。clock.kv
その有しBoxLayout
、唯一のサブコンポーネント。Kivyのレイアウトはデフォルトで画面全体に表示されるため、自動的に画面に適応します。
あなたは1を追加した場合Layout
、それは半分に画面を分割し、されますvertical
とhorizontal
、分割の方向を決めます。
ここvertical
で3つに分割し、真ん中の部分horizontal
を2つに分割しましょう。
レイアウトを完成させる
中央部分はボタンなので、時間より大きくすることはできません。height
属性を追加してから、属性をに設定できsize_hint
ますNone
。size_hint
属性は(宽, 高)
、パーツの幅と高さに影響を与えるタプルです。絶対的な高さと幅を使用する場合は、size_hint
属性をNone
に設定する必要があります。そうしないと、高さと幅の設定が無効になり、ウィジェットが自動的にサイズを計算します。コードは次のように表示されます。
#%load clock.kv
BoxLayout :
orientation : 'vertical'
Label :
id : time
text : '[b] 00 [/ b]:00:00'
font_name : 'Roboto'
font_size : 60
markup : True
BoxLayout :
height : 90
方向: '水平'
パディング: 20
間隔: 20
size_hint : (1、なし)
ボタン:
テキスト: '開始'
font_name : 'Roboto'
font_size : 25
bold : True
Button :
text : 'Reset'
font_name : 'Roboto'
font_size : 25
bold : True
Label :
id : stopwatch
text : '00:00。[size = 40] 00 [/ size] '
font_name : 'Roboto'
font_size : 60
マークアップ: True
コードを実行すると、CSSと同様に、属性と属性が使用されているBoxLayout
ため、ボタンが完全に埋められていないことがわかります。コードは次のように表示されます。padding
spacing
main.py
#%負荷main.py
から kivy.app 輸入 のApp
から kivy.clockの 輸入 時計
から kivy.core.window インポート ウィンドウ
から kivy.utils インポート get_color_from_hexを
から kivy.core.text インポート LabelBase
から 時間 の輸入 のstrftimeの
LabelBase 。register (
name = "Roboto" 、 fn_regular = "Roboto-Thin.ttf" 、 fn_bold = "Roboto-Medium.ttf"
)
class ClockApp(アプリ):
def update_time (self 、 nap ):
self 。ルート。ids 。時間。text = strftime ("[b]%H [/ b]:%M:%S" )
def on_start (self ):
Clock 。schedule_interval (自己。UPDATE_TIME 、 1 )
の場合 __name__ == "__main__" :
ウィンドウ。clearcolor = get_color_from_hex ("#123456" )
ClockApp ()。実行()
繰り返しを減らす
以前のkvコードは何度も繰り返されていますが、CSSを使用する方法は、コードをより洗練されたドライなものにすることです。ではBoxLayout
新しい定義の外の追加:
#%load clock.kv
<ラベル> :
font_name : 'Roboto'
font_size : 60
マークアップ: True
これはCSSセレクターに似たクラスです。それぞれLabel
に<Label>
クラス特性があります。
clock.kv
それぞれLabel
の中に入れることができるようにfont_name
、font_size
そしてmarkup
属性は削除されます。属性の値を変更したい場合は、直接書き込むだけで、CSSとまったく同じように元の値が上書きされます。
クラスを定義すると、新しいパーツは作成されませんが、属性のコレクションが作成されます。定義クラスを追加します。使用されていない場合、アプリのレイアウトは変更されません。
名前付きクラス
以前のkvコードのクラスの処理に問題があります。クラスは1つの名前しか持つことができませんLabel
。同じコンポーネントに異なる属性定義クラスを追加する場合は、クラスをカスタマイズできます。これらの標準クラスを直接書き直すLabel
とButton
、後でクラスコンポーネントを使用するときに、前面と背面を変更するのに多くの問題が発生します。幸いなことに、命名クラスは、この問題を解決することができますRobotoButton
ですButton
。
<RobotoButton @ Button> :
font_name : 'Roboto'
font_size : 25
太字: True
@
最初は新しいクラスの名前で、その後にコンポーネントタイプが続きます。これは基本的にオブジェクト指向のサブクラスclass RobotoButton(Button)
です。kvコードで使用する場合、名前付きクラスを直接使用して元のButton
クラスを置き換えることができます。
RobotoButton :
テキスト: '開始'
名前付きクラスは、コードを合理化し、コンポーネントを改善できます。
ボタンスタイル
UIデザインの行き詰まりは、統一されたスタイルのないボタンなどのクリック可能な要素です。Win8のMetroスタイルは非常に過激で、クリックされた部分は完全に単色の長方形で、非常に小さいか、基本的にパターンがありません。Appleはラジアンを使用しています。特にCSS3スタイルでは、角を丸くする傾向もあります。ライトシェードも使用され始めています。
Kivyはこの点で非常に柔軟性があり、スタイルを強制せず、スタイルを実現するのに役立つ一連の機能を提供します。そのひとつが9パッチズーム機能です。
9パッチスケーリング
従来のUI開発では、背景のサイズが異なる場合、通常、サイズごとに画像を作成する必要があります。これは、ボタンで特に顕著です。もちろん、水平または垂直に繰り返される小さな絵を描くこともできます。アンドロイドには、異なる背景サイズの問題を解決するための9パッチ画像(9.pngで終わる)と呼ばれる特別なタイプがあり、1つの背景画像のみが使用されます。水平画面でも垂直画面でも、高解像度でも低解像度でも、歪みなく自動的に塗りつぶすことができます。
スケーリングアルゴリズムの目的は、特に大量のテキストを含むボタンの場合、さまざまな場面のピクセル要件に可能な限り適応することです。比率のスケーリングは簡単に実現できますが、歪みの比率の問題のため、品質はあまり良くありません。
非比例9パッチ増幅は、歪みのない効果を生み出すことができます。アイデアは、画像を静的でズーム可能なブロックに分割することです。下の画像がズーム可能なボタンであるとします。黄色の部分は操作領域であり、他の色はエッジです。
赤い領域を圧縮しても、青い領域のサイズは変わりません。以下に示すように:
青いコーナーは変更されておらず、赤い側は垂直方向と水平方向に拡大縮小できます。比例して変化する画像の唯一の部分は、通常は単色である黄色の操作領域であり、テキストを追加することもできます。
9パッチ図を使用する
この例では、一辺が1pxのシンプルな単色ボタンを使用しており、色を変更することで再利用できます。次のように:
以下に示すように、それを押し下げて反対の色を使用します。
今、clock.kv
デフォルトは比例的変化であるために9パッチ画像を追加するために、我々は、Kivyに画像のエッジのピクセルを伝える必要があります。
<RobotoButton @ Button> :
background_normal : 'button_normal.png'
background_down : 'button_down.png'
border : (2、2、2、2 )
border
プロパティは時計回りにCSSと一致しています:上、右、下、左。ただし、CSSのように統一された値を直接書き込むborder: 2
ことはできません。当面はできません。
もちろん、Python構文を使用
border:[2] * 4
するのが最短です。
上記のように、CSSはプロパティの背面に似ており、Reset
[新規]ボタンなど、同じ名前のプロパティの前面をカバーします。次の場所でRobotoButton
変更できます。
RobotoButton :
text : 'リセット'
background_normal : 'red_button_normal.png'
background_down : 'red_button_down.png'
このボタンは完了しましたが、まだ実行できません。ストップウォッチ機能を実装しましょう。
タイミング機能
ストップウォッチは時刻を表示するだけでなく、一時停止してリセットする必要があります。これは通常の時計よりも少し複雑です。プログラムに反映されているのは、Pythondatatime
モジュールとstrftime()
関数の違いです。後者は現在の時刻を直接フォーマットできます。これはまさにストップウォッチが表示するものです。
まず、タイマーを作成する必要があります。KivyのClock.schedule_interval
イベントハンドラーは時間パラメーターをサポートしているため、Pythonの時間関数を使用せずに簡単に実装できます。
def on_start (self ):
Clock 。schedule_interval (自己。更新、 0.016 )
DEF 更新(自己、 NAP ):
合格
時間の単位は秒です。つまり、アプリは1フレームとして1秒あたり60回(60fps)実行され、平均間隔時間は次のようになります。 frac {1} {60} = 0.016(6)
次に、更新を続ける時間です。
class ClockApp (App ):
sw_seconds = 0
def update (self 、 nap ):
self 。sw_seconds + = 昼寝
まず時間表示機能を行い、次に停止機能を実現します。
ストップウォッチの時間形式
標準モジュールstrftime
がdatetime
時間変換文字列の機能を提供するため、メインの時間表示の形式は非常に単純です。ただし、この関数にはいくつかの欠点があります。
- Pythonの
datetime
時間形式のみを受け入れます(ただし、ストップウォッチでは秒を小数で表示する必要がありますsw_seconds
) - 10進数の変換機能はありません
datetime
欠点は簡単に克服できます。時間形式にsw_seconds
変換できdatetime
ます。ただし、最後に10進数を表示する必要があるため、少し冗長strftime
です。そのため、形式は適切ではありません。次に、自分でホイールを作成します。
時間の計算
まず、分、秒、分と秒、divmode
関数の出力(商、剰余)を計算します。
分、 秒 = divmod (自己。sw_seconds 、 60 )
divmode
関数は1回だけ計算され、通常の/
合計%
演算には2回必要です。ゲームやシミュレーションのように、画像のすべてのフレームにこのような浮動小数点数の除算が多数ある場合、CPUは非常に強力になります。
いわゆる「時期尚早の最適化は悪魔」に同意しません。多くの不適切な慣行はプログラムのパフォーマンスの低下につながります。実際、最初は簡単に回避でき、コードの品質には影響しません。それをしない悪魔。
ことに留意すべきであるdivmode
関数の結果はまだ浮動小数点数ですので、我々は戦わなければならない:int(minutes)
とint(seconds)
。
これで、残りの分と秒があります。これは、次のように取得できます。
int (秒 * 100 % 100 )
ストップウォッチを実装する
すべての値が揃ったので、それらを組み合わせてみましょう。Pythonの文字列処理には多くの形式がありますが、PythonのZen(Pythonを開いてimport thisと入力)の「明白な方法は1つ、できれば1つだけである必要があります」と矛盾しません。最も単純なのは、%で表されるC言語スタイルです。
def update_time (self 、 nap ):
self 。sw_seconds + = 昼寝
分、 秒 = divmod (自己。sw_seconds 、 60 )
自己。ルート。ids 。ストップウォッチ。text = " %02d :%02d 。[size = 40] %02d [/ size]" % (
int (分)、
int (秒)、
int(秒 * 100 % 100 )、
)
現在、分と秒があり、以前に使用された更新頻度1fpsは適用されません。update_time
時間間隔を0に変更します。つまり、フレームごとに更新します。
時計。schedule_interval (自己。UPDATE_TIME 、 0 )
プログラムを実行して時間の更新を確認しますが、それでもコントロールが不足しています。次のとおりです。
ストップウォッチコントロール
ボタンを使用してアプリケーションを制御するのが最も簡単です。すべてのコードは次のとおりです。
def start_stop (self ):
self 。ルート。ids 。start_stop 。テキスト = 「スタート」 であれば 、自己。sw_started else "Stop"
self 。sw_started = selfではありません 。sw_startedデフリセット(自己):場合は自己。sw_started :self 。ルート。ids 。start_stop 。text = "開始"
自己。sw_started = Falseの
自己。sw_seconds = 0
最初のイベントハンドラーは、状態を変更することで実装される[開始]ボタンと[停止]ボタンsw_started
です。2番目のハンドラーは[リセット]ボタンです。
また、ストップウォッチが実行されているかどうかを追跡するために、ステータス属性を追加する必要があります。
クラス ClockApp (アプリケーション):
sw_started = Falseの
sw_seconds = 0
DEF update_clock (自己、 昼寝):
もし 自己。sw_started :
self 。sw_seconds + = 昼寝
update_clock
関数stopwatchは、更新のみを開始sw_started
するように変更True
します。デフォルトでは、stopwatchの開始状態を停止します。
このclock.kv
ファイルでは、メソッドをon_press
イベントにバインドします。
RobotoButton :
id : start_stop
text : 'Start'
on_press : app.start_stop()
RobotoButton :
id : reset
text : 'Reset'
on_press : app.reset()
Kivy言語には、状況依存の参照がいくつかあります。
- self:現在のコンポーネントを参照します。
- ルート:プログラム全体の最も外側のコンポーネント。
- app:アプリケーションクラスのインスタンス。
ボタンイベントの処理はまったく難しくないことがわかります。このように、私たちのアプリはストップウォッチのインタラクティブ機能を実装し、ユーザーが開始、停止、リセットできるようにします。
総括する
この章では、アプリを作成しました。パッケージ化してGoogle Playや他のストアに公開し、誰もが使用できるようにする場合は、特定のプラットフォームが関係するため、少し作業が必要ですが、最も難しい部分はプログラミングです。以上。
アプリを通じて、ツタのアプリケーション開発の多くの側面を学び、それを実行するためにそれほど複雑なコードは必要ありませんでした。Kivyの主な機能は、その短く簡潔なコードであり、これにより迅速な反復が可能になります。少し古いコードで多くの新機能を利用できます。Kivyは活力に満ちており、永遠に続くでしょう。
この本のすべての内容の共通の根拠は、私たちのプログラムもKivyも薄い空気から作成されたものではないということです。すべては、Pythonから来ているcheese shop
–のPythonパッケージインデックス(は、PyPI) -およびオペレーティングシステムの基盤となるサービスを含む他のツールキット、。
また、CSSフレームワークBootstrapのフォント、色、シャドウなど、Webアプリケーション開発用の多くのリソースを更新しました。もちろん、GoogleもMaterial design principles
ご覧ください。デザインリソースのコレクションだけでなく、アプリの「個性」と特性を維持しながら、統一されたスタイルと使いやすいUIを実現する方法を教えてくれる完全なチュートリアルもあります。
もちろん、これはほんの始まりに過ぎません。何が起こっているのか知りたい場合は、次の内訳を聞いてください。