Kivy

マルチタッチ対応のクロスプラットフォームGUIフレームワーク。独自のレンダリングエンジンによりモバイル・デスクトップ・Web間での一貫したUI体験を提供。ゲームやインタラクティブアプリケーション開発に特化。

デスクトップクロスプラットフォームPythonGUIモバイルタッチ

GitHub概要

kivy/kivy

Open source UI framework written in Python, running on Windows, Linux, macOS, Android and iOS

ホームページ:https://kivy.org
スター18,475
ウォッチ603
フォーク3,128
作成日:2010年11月3日
言語:Python
ライセンス:MIT License

トピックス

androidappioskivylinuxmacospythonuiwindows

スター履歴

kivy/kivy Star History
データ取得日時: 2025/7/16 08:43

フレームワーク

Kivy

概要

Kivyは、Pythonで書かれたオープンソースのクロスプラットフォームUIフレームワークです。Windows、Linux、macOS、Android、iOSで動作し、タッチ操作に対応したグラフィカルアプリケーションを開発できます。自然なマルチタッチ操作と豊富なUIウィジェットを提供します。

詳細

Kivyは、2025年現在でもPythonクロスプラットフォーム開発の有力な選択肢として継続的に進化しています。特にタッチ操作が重要なデスクトップアプリケーション、キオスクアプリケーション、教育用アプリケーション分野で強みを発揮しています。

OpenGLベースの描画エンジンにより高速なグラフィックス描画を実現し、独自のKV言語によるレイアウト記述、豊富なウィジェットライブラリ、アニメーション機能、マルチタッチジェスチャ認識など、現代的なUIアプリケーション開発に必要な機能を包括的に提供しています。

PyInstaller、Buildozer、p4aなどのパッケージングツールとの統合により、各プラットフォーム向けの実行ファイルやアプリパッケージの作成も容易です。ゲーム開発、教育用ソフトウェア、産業用制御パネル、デジタルサイネージなど、様々な分野で採用されています。

メリット・デメリット

メリット

  • 真のクロスプラットフォーム: デスクトップとモバイルの両方に対応
  • タッチファースト設計: 自然なマルチタッチとジェスチャ操作
  • OpenGL描画: 高速なグラフィックス描画とアニメーション
  • KV言語: 直感的で保守しやすいレイアウト記述
  • 豊富なウィジェット: 豊富なUIコンポーネントライブラリ
  • Pythonの生産性: Pythonの学習しやすさと豊富なライブラリ
  • オープンソース: MIT ライセンスで商用利用可能
  • アクティブコミュニティ: 継続的な開発とサポート

デメリット

  • ネイティブ外観: プラットフォーム固有のネイティブ外観ではない
  • 学習コスト: Kivy特有の概念とKV言語の習得が必要
  • アプリサイズ: OpenGL依存によりバイナリサイズが大きくなる
  • メモリ使用量: リッチなグラフィックスによりメモリ消費が多い
  • モバイル制約: iOS/Android向けパッケージング作業が複雑
  • ドキュメント: 一部ドキュメントの内容が古い場合がある

主要リンク

書き方の例

Hello Worldアプリケーション

# hello_world.py
import kivy
kivy.require('2.1.0')

from kivy.app import App
from kivy.uix.label import Label


class MyApp(App):
    def build(self):
        return Label(text='Hello, Kivy!')


if __name__ == '__main__':
    MyApp().run()

ログイン画面(Python + KV言語)

# login_app.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button


class LoginScreen(GridLayout):
    def __init__(self, **kwargs):
        super(LoginScreen, self).__init__(**kwargs)
        self.cols = 2
        
        # ユーザー名入力
        self.add_widget(Label(text='ユーザー名'))
        self.username = TextInput(multiline=False)
        self.add_widget(self.username)
        
        # パスワード入力
        self.add_widget(Label(text='パスワード'))
        self.password = TextInput(password=True, multiline=False)
        self.add_widget(self.password)
        
        # ログインボタン
        self.add_widget(Label(text=''))  # 空のセル
        login_btn = Button(text='ログイン')
        login_btn.bind(on_press=self.on_login)
        self.add_widget(login_btn)
    
    def on_login(self, instance):
        print(f'ユーザー名: {self.username.text}')
        print(f'パスワード: {self.password.text}')


class LoginApp(App):
    def build(self):
        return LoginScreen()


if __name__ == '__main__':
    LoginApp().run()

ペイントアプリケーション

# paint_app.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line
from random import random


class PaintWidget(Widget):
    def on_touch_down(self, touch):
        with self.canvas:
            # HSVカラーモードで一貫した明度の色を生成
            color = (random(), 1., 1.)
            Color(*color, mode='hsv')
            
            # タッチポイントに円を描画
            d = 30.
            Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
            
            # 線描画の開始
            touch.ud['line'] = Line(points=(touch.x, touch.y))

    def on_touch_move(self, touch):
        # タッチ移動で線を延長
        if 'line' in touch.ud:
            touch.ud['line'].points += [touch.x, touch.y]


class PaintApp(App):
    def build(self):
        parent = Widget()
        
        # ペイント領域
        self.painter = PaintWidget()
        parent.add_widget(self.painter)
        
        # クリアボタン
        clearbtn = Button(text='クリア', size_hint=(None, None), size=(100, 50))
        clearbtn.bind(on_release=self.clear_canvas)
        parent.add_widget(clearbtn)
        
        return parent

    def clear_canvas(self, obj):
        self.painter.canvas.clear()


if __name__ == '__main__':
    PaintApp().run()

KV言語を使用したレイアウト

# kv_app.py
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder

# KV言語でレイアウトを定義
Builder.load_string('''
<RootWidget>:
    orientation: 'vertical'
    padding: 20
    spacing: 10
    
    Label:
        text: 'Kivyアプリケーション'
        size_hint_y: None
        height: 50
        font_size: 24
    
    BoxLayout:
        orientation: 'horizontal'
        spacing: 10
        
        Button:
            text: 'ボタン 1'
            on_press: root.button_pressed(self.text)
        
        Button:
            text: 'ボタン 2'
            on_press: root.button_pressed(self.text)
        
        Button:
            text: 'ボタン 3'
            on_press: root.button_pressed(self.text)
    
    TextInput:
        id: text_input
        text: 'ここにテキストを入力'
        multiline: False
        size_hint_y: None
        height: 30
    
    Label:
        id: result_label
        text: '結果がここに表示されます'
        text_size: self.size
        halign: 'center'
        valign: 'middle'
''')


class RootWidget(BoxLayout):
    def button_pressed(self, button_text):
        # IDを使ってウィジェットにアクセス
        self.ids.result_label.text = f'{button_text} が押されました'
        input_text = self.ids.text_input.text
        print(f'ボタン: {button_text}, 入力: {input_text}')


class KVApp(App):
    def build(self):
        return RootWidget()


if __name__ == '__main__':
    KVApp().run()

アニメーションとプロパティ

# animation_app.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.animation import Animation
from kivy.graphics import Color, Rectangle


class AnimationWidget(Widget):
    def __init__(self, **kwargs):
        super(AnimationWidget, self).__init__(**kwargs)
        
        # 背景を描画
        with self.canvas:
            Color(0.2, 0.6, 0.8)  # 青い背景
            self.rect = Rectangle(size=(100, 100), pos=(50, 50))
        
        # アニメーション用ボタン
        btn = Button(text='アニメーション開始', size_hint=(None, None), 
                    size=(200, 50), pos=(10, 10))
        btn.bind(on_press=self.start_animation)
        self.add_widget(btn)
    
    def start_animation(self, instance):
        # 四角形のアニメーション
        anim = Animation(pos=(300, 200), size=(150, 150), duration=2)
        anim += Animation(pos=(50, 50), size=(100, 100), duration=2)
        anim.repeat = True
        anim.bind(on_progress=self.update_rect)
        anim.start(self)
    
    def update_rect(self, animation, widget, progress):
        # アニメーション中に四角形を更新
        self.rect.pos = (50 + progress * 250, 50 + progress * 150)
        self.rect.size = (100 + progress * 50, 100 + progress * 50)


class AnimationApp(App):
    def build(self):
        return AnimationWidget()


if __name__ == '__main__':
    AnimationApp().run()

モバイル向けパッケージング(Buildozer設定)

# buildozer.spec
[app]
title = My Kivy App
package.name = mykivyapp
package.domain = org.example

source.dir = .
source.include_exts = py,png,jpg,kv,atlas

version = 0.1
requirements = python3,kivy

[buildozer]
log_level = 2

[app:android]
arch = arm64-v8a,armeabi-v7a

[app:android.gradle_dependencies]
implementation 'com.google.android.material:material:1.0.0'

[app:android.permissions]
android.permission.INTERNET
android.permission.WRITE_EXTERNAL_STORAGE

プロジェクト設定と実行

# 仮想環境作成(推奨)
python -m venv kivy_env
source kivy_env/bin/activate  # Linux/macOS
# または
kivy_env\Scripts\activate  # Windows

# Kivyインストール
python -m pip install "kivy[base]" kivy_examples

# アプリケーション実行
python hello_world.py

# Android向けビルド(Buildozer使用)
pip install buildozer
buildozer android debug

# デスクトップ向け実行ファイル作成(PyInstaller使用)
pip install pyinstaller
pyinstaller --onefile --windowed hello_world.py

# Kivyサンプル実行
python -m kivy.examples.demo.showcase

プロジェクト構造例

my_kivy_app/
├── main.py                 # メインアプリケーション
├── screens/
│   ├── __init__.py
│   ├── home_screen.py      # ホーム画面
│   └── settings_screen.py  # 設定画面
├── widgets/
│   ├── __init__.py
│   └── custom_button.py    # カスタムウィジェット
├── layouts/
│   ├── home.kv            # ホーム画面レイアウト
│   └── settings.kv        # 設定画面レイアウト
├── assets/
│   ├── images/
│   └── sounds/
├── buildozer.spec         # Android/iOSビルド設定
├── requirements.txt
└── README.md