libGDX 2D UI Library - Widgets
概要
libGDX の 2D UI Library のうち、Button 系以外の Widget についてまとめます。
目次
確認環境
- OS X El Capitan (10.11.6)
- Xcode 8.0
- Android Studio 2.2.2
- Multi-OS Engine Plugin 1.2.1
- Kotlin 1.0.4
- buildToolVersion 25.0.0
- compileSdkVersion 24
- libGDX 1.9.5-SNAPSHOT
参考情報
- Scene2d · libgdx/libgdx Wiki · GitHub
- Scene2d 公式文書。
- Viewports · libgdx/libgdx Wiki · GitHub
- Viewport 公式文書。
- Scene2d.ui · libgdx/libgdx Wiki · GitHub
- Scene2d UI 公式文書。
- libGDXの基礎5 Scene2Dを使う - Qiita
- 概要。
解説
Image
設定項目 | 型 | 説明 |
---|---|---|
drawable | Drawable | 描画対象 |
Skin, String | ||
NinePatch | ||
Texture | ||
TextureRegion | ||
scaling | Scaling | Scaling.none, Scaling.fit, Scaling.fill, Scaling.stretch (default)。(fill, stretch には X, Y のみがある。) |
align | Int | Align.topLeft, Align.top, Align.topRight, Align.right, Align.bottomRight, Align.bottom, Align.bottomLeft, Align.left, Align.center (default)。 |
サイズ
min | pref | max | |
---|---|---|---|
width/height | 0 | drawable のサイズ | 0 |
Scaling (align = Align.center の場合)
Scaling.none | Scaling.fit |
---|---|
Scaling.fill | Scaling.stretch |
サンプルコード
private val actor by lazy { Image(Texture("badlogic.jpg")).apply { width = this@MyGdxGame.stage.width height = this@MyGdxGame.stage.height setScaling(Scaling.none) //setScaling(Scaling.fit) //setScaling(Scaling.fill) //setScaling(Scaling.stretch) setAlign(Align.center) } } override fun create() { ... stage.addActor(actor) }
Label
設定項目 | 型 | 説明 |
---|---|---|
text | CharSequence | 描画対象。改行文字 ('\n') で改行される。 |
style | Label.LabelStyle | background, font, fontColor |
Skin | ||
labelAlign | Int | Label 全体の配置。Align.topLeft, Align.top, Align.topRight, Align.right, Align.bottomRight, Align.bottom, Align.bottomLeft, Align.left (default), Align.center。 |
lineAlign | Int | 各行の配置。Align.left (default), Align.center, Align.right。 |
ellipsis | Boolean | true ならば width を超えないように末尾を "..." に置き換える。(default: false) |
String | null 以外ならば width を超えないように末尾を指定した String に置き換える。 | |
fontScaleX | Float | X 方向の拡大率。 |
fontScaleY | Float | Y 方向の拡大率。 |
wrap | Boolean | true ならば width を超える場合に改行する。ellipsis が優先される。(default: false) |
サイズ
min | pref | max | |
---|---|---|---|
width/height | prefと同じ | text が収まるサイズを算出 | 0 |
text = "Hello World\nHello Beautiful World!!"、fontScaleX = 5、fontScaleY = 10 の場合の表示例。
labelAlign = topLeft, lineAlign = center | labelAlign = center, lineAlign = center | labelAlign = bottomRight, lineAlign = center |
---|---|---|
labelAlign = center, lineAlign = left | labelAlign = center, lineAlign = center | labelAlign = center, lineAlign = right |
---|---|---|
サンプルコード
private val actor by lazy { Label("Hello World\nHello Beautiful World!!", Label.LabelStyle(BitmapFont(), Color.WHITE)).apply { width = this@MyGdxGame.stage.width height = this@MyGdxGame.stage.height setFontScale(5f, 10f) setAlignment(Align.center, Align.center) } } override fun create() { ... stage.addActor(actor) }
TextField
設定項目 | 型 | 説明 |
---|---|---|
text | String | 入力欄に設定される文字列。改行文字 ('\n') は除去される。 |
style | TextField.TextFieldStyle | BitmapFont (font, messageFont), Color (fontColor, messageFontColor, disabledFontColor, focusedFontColor), Drawable (background, disabledBackground, focusedBackground, cursor, selection) |
Skin | ||
alignment | Int | Align.left, Align.center, Align.right。 |
maxLength | Int | 入力可能文字数。 |
messageText | String | text 未入力時に表示する文字列。入力を削除しても再表示されない。 |
onlyFontChars | Boolean | true (default) ならば、text に set する際に BitmapFont に含まれない文字を除去する。false ならば、含まれない文字を空白に置き換える。 |
passwordMode | Boolean | true ならば、入力文字列を passwordCharacter で表示する。false (default) ならば、入力文字列をそのまま表示する。 |
passwordCharacter | Char | passwordMode が true のときに使用する文字。設定しないと passwordMode = true でもマスクされない。 |
サイズ
min | pref | max | |
---|---|---|---|
width/height | prefと同じ | ? | 0 |
サンプルコード
private val actor by lazy { TextField("", TextField.TextFieldStyle().apply { font = BitmapFont().apply { data.scale(10f) } messageFont = font fontColor = Color.WHITE messageFontColor = Color.RED }).apply { width = this@MyGdxGame.stage.width height = this@MyGdxGame.stage.height maxLength = 10 messageText = "message" isPasswordMode = false setPasswordCharacter('x') setAlignment(Align.right) setOnlyFontChars(false) //text = "aとbとc" } } override fun create() { ... stage.addActor(actor) }
TextArea
TextField と同様。 異なる点は text に改行文字を含むことができ、width を超える場合には改行して表示される。
List
設定項目 | 型 | 説明 |
---|---|---|
items | Array |
リストの項目。文字列として表示される。 |
style | List.ListStyle | BitmapFont (font), Color (fontColorSelected, fontColorUnselected), Drawable (background, selection) |
Skin |
サイズ
min | pref | max | |
---|---|---|---|
width/height | prefと同じ | ? | 0 |
実行例
サンプルコード
private val actor by lazy { List<String>(List.ListStyle().apply { font = BitmapFont().apply { data.scale(10f) } fontColorUnselected = Color.WHITE fontColorSelected = Color.RED selection = SpriteDrawable(Sprite(Texture("badlogic.jpg"))) }).apply { width = this@MyGdxGame.stage.width height = this@MyGdxGame.stage.height setItems("pen", "apple", "pineapple") } } override fun create() { ... stage.addActor(actor) }
SelectBox
設定項目 | 型 | 説明 |
---|---|---|
items | Array |
リストの項目。文字列として表示される。 |
style | SelectBox.SelectBoxStyle | BitmapFont (font), Color (fontColor, disabledFontColor), Drawable (background, backgroundOpen, backgroundOver, backgroundDisabled), List.ListStyle (BitmapFont (font), Color (fontColorSelected, fontColorUnselected), Drawable (background, selection)), ScrollPane.ScrollPaneStyle (Drawable (background, corner, hScroll, hScrollKnob, vScroll, vScrollKnob)) |
Skin | ||
maxListCount | Int | ドロップダウン時に表示する項目数。(default: items の要素数) |
scrollingDisabled | Boolean | true ならば、ドロップダウン時のスクロールを無効にする (maxListCount の個数しか表示されない)。false (default) ならば、有効にする。 |
サイズ
min | pref | max | |
---|---|---|---|
width/height | prefと同じ | ? | 0 |
実行例
default | maxListCount = 3 | maxListCount = 3, scrollingDisabled = true |
---|---|---|
サンプルコード
private val actor by lazy { val commonFont = BitmapFont().apply { data.scale(10f) } SelectBox<String>(SelectBox.SelectBoxStyle().apply { font = commonFont fontColor = Color.WHITE background = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.YELLOW }) backgroundOpen = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.GRAY }) listStyle = List.ListStyle().apply { font = commonFont fontColor = Color.GRAY fontColorUnselected = Color.GREEN fontColorSelected = Color.RED selection = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.RED }) } scrollStyle = ScrollPane.ScrollPaneStyle().apply { vScroll = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.BLUE }) vScrollKnob = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.MAGENTA }) } }).apply { val stageW = this@MyGdxGame.stage.width val stageH = this@MyGdxGame.stage.height setPosition(stageW/2 - width/2, stageH - height) setItems("1", "2", "3", "4", "5", "6", "7", "8", "9", "0") //maxListCount = 3 //setScrollingDisabled(true) } } override fun create() { ... stage.addActor(actor) }
ProgressBar
設定項目 | 型 | 説明 |
---|---|---|
min | Float | 最小値。 |
max | Float | 最大値。 |
stepSize | Float | 最小値から最大値を分割したときの一区画のサイズ。value は近くの区画に丸められる。 |
vertical | Boolean | true ならば、縦方向に表示。false ならば、横方向に表示。 |
style | ProgressBar.ProgressBarStyle | Drawable (background, knob, knobBefore, knobAfter, disabledBackground, disabledKnob, disabledKnobBefore, disabledKnobAfter) |
Skin | ||
visualInterpolation | Interpolation | value に set して、表示が更新される際のアニメーション表示方法。 |
animateDuration | Float | アニメーション時間。単位は秒。 |
animateInterpolation | Interpolation | setAnimationDuration を実行した際に行われるアニメーションの表示方法。 |
サイズ
min | pref | max | |
---|---|---|---|
width/height | prefと同じ | ? | 0 |
実行例
vertical = false | vertical = true |
---|---|
サンプルコード
private val actor by lazy { ProgressBar(0f, 100f, 25f, false, ProgressBar.ProgressBarStyle().apply { background = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.WHITE }) knob = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.BLUE }) knobBefore = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.RED }) knobAfter = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.GREEN }) } ).apply { width = this@MyGdxGame.stage.width height = this@MyGdxGame.stage.height setVisualInterpolation(Interpolation.fade) setAnimateDuration(10f) value = 60f setAnimateInterpolation(Interpolation.bounce) setAnimateDuration(20f) } } override fun create() { ... stage.addActor(actor) }
Slider
ProgressBar のサブクラス。
設定項目 | 型 | 説明 |
---|---|---|
min | Float | 最小値。 |
max | Float | 最大値。 |
stepSize | Float | 最小値から最大値を分割したときの一区画のサイズ。value は近くの区画に丸められる。 |
vertical | Boolean | true ならば、縦方向に表示。false ならば、横方向に表示。 |
style | Slider.SliderStyle | Drawable (background, knob, knobBefore, knobAfter, knobDown, knobOver, disabledBackground, disabledKnob, disabledKnobBefore, disabledKnobAfter) |
Skin | ||
visualInterpolationInverse | Interpolation | value に現在の value よりも小さい値を set して、表示が更新される際のアニメーション表示方法。 |
サイズ
min | pref | max | |
---|---|---|---|
width/height | prefと同じ | ? | 0 |
サンプルコード
private val actor by lazy { Slider(0f, 100f, 25f, false, Slider.SliderStyle().apply { background = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.WHITE }) knob = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.BLUE }) knobBefore = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.RED }) knobAfter = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.GREEN }) knobDown = SpriteDrawable(Sprite(Texture("badlogic.jpg")).apply { color = Color.MAGENTA }) } ).apply { width = this@MyGdxGame.stage.width height = this@MyGdxGame.stage.height value = 60f setVisualInterpolationInverse(Interpolation.smooth) setAnimateDuration(3f) value = 10f } } override fun create() { ... stage.addActor(actor) }
GPIO 操作するプログラムを macOS で開発する
概要
macOS 環境で RPi.GPIO モジュールを使用します。 macOS 環境では GPIO が存在しないため、エミュレーターを使用します。 なお、エミュレーターは自作です。
確認環境
- Raspberry Pi Zero
- RASPBIAN JESSIE LITE 2016-11-25
- Python 3.4.2
- MacBook Pro 2016 Late
参考情報
- Raspberry Pi GPIO Emulator | Roderick Vella Galea
- Raspberry Pi GPIO Emulator
- GitHub - nosix/raspberry-gpio-emulator: RPi.GPIO emulator
- 自作の RPi.GPIO Emulator
前回の記事
解説
Raspberry Pi には RPi.GPIO モジュールがインストールされているが、macOS 環境にはインストールされていない。 例えば、以下のプログラムを macOS 環境の PyCharm で作成すると No module named RPi とのエラーメッセージが表示される。
hello_gpio.py
from time import sleep import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(25, GPIO.OUT) while True: GPIO.output(25, GPIO.HIGH) sleep(0.5) GPIO.output(25, GPIO.LOW) sleep(0.5)
macOS 環境に RPi モジュールをインストールする代わりに RPi モジュールのエミュレーター(もしくは、シミュレーター)を探した。 いくつか見つかったが、モジュール名を変更しなければいけないなど、ソースコード(上記の例では hello_gpio.py)に全く手を入れずに使えるものではなかった。そこで、RPi モジュールのエミュレーターを自作した。
RPi.GPIO エミュレーターをインストールする
GitHub にある Python パッケージを pip を使って仮想環境にインストール。
mac:~ nosix$ source ~/pyenv/python3/bin/activate (python3) mac:~ nosix$ (python3) mac:~ nosix$ pip install git+https://github.com/nosix/raspberry-gpio-emulator/ Collecting git+https://github.com/nosix/raspberry-gpio-emulator/ Cloning https://github.com/nosix/raspberry-gpio-emulator/ to /private/var/folders/kz/wv_kdss90634rlck2k9d852m0000gn/T/pip-6akufwi3-build Installing collected packages: RPi Running setup.py install for RPi ... done Successfully installed RPi-0.1.0
インストールが完了するとエラーは消える。
macOS 環境、Raspberry Pi 環境のいずれでも変更なしで実行できる。
macOS 環境で実行した場合には、エミュレーターが起動されてピンの状態を表示。
Raspberry Pi 環境で実行した場合には、GPIO が操作される。
なお、エミュレーターの UI が気に入らない場合には、自作 UI に差し替えられる設計になっている。 また、各 GPIO の状態変化を監視するプラグインを追加できる様になっている。
macOS で Python プログラム開発環境を構築して Raspberry Pi で実行する
概要
macOS で Python プログラムの開発環境を構築します。 macOS で作成したプログラムを Raspberry Pi で実行できる様にします。 前回の記事の続きです。
確認環境
- Raspberry Pi Zero
- RASPBIAN JESSIE LITE 2016-11-25
- Python 3.4.2
- MacBook Pro 2016 Late
参考情報
- パッケージ管理システム Homebrew - Qiita
- macOS のパッケージ管理ツール HomeBrew
前回の記事
解説
Python3 環境を構築する
HomeBrew が導入されていなければ導入する。 HomeBrew は macOS においてソフトウェアパッケージを管理するツール。 ソフトウェアパッケージのインストール、アンインストール、アップグレードなどを行うことができる。
mac:~ nosix$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew コマンドを使用して Python3, virtualenv をインストール。 pip は Python パッケージを管理するツール。 Python プログラムで使用できる便利な機能 (ライブラリ) をインストールするために使用する。 virtualenv は仮想環境(実験室)を作成するツール。 Python バージョンやライブラリの組み合わせを切り替えることが容易になる。
mac:~ nosix$ brew install python3 mac:~ nosix$ pip3 install virtualenv
pip を使用した際に新しいバージョンの通知がある場合は、指示に従ってアップグレードする。
You are using pip version 8.1.2, however version 9.0.1 is available. You should consider upgrading via the 'pip install --upgrade pip' command. mac:~ nosix$ pip3 install --upgrade pip
Python3 用の virtualenv (仮想環境) を作成する。 作成後に --version オプションを指定して python コマンドを実行し、バージョンを確認する。
mac:~ nosix$ mkdir ~/pyenv mac:~ nosix$ virtualenv -p python3 ~/pyenv/python3 mac:~ nosix$ source ~/pyenv/python3/bin/activate (python3) mac:~ nosix$ (python3) mac:~ nosix$ python --version Python 3.5.2
PyCharm を導入する
PyCharm Community をダウンロードし、インストール。 もしくは、IntelliJ IDEA など JetBarins 製 IDE を使用しているならば、Python Community Edition プラグインをインストール。 以降の画面例は IntelliJ IDEA に Python Community Edition プラグインをインストールしたもの。 なお、有償版を使うと他のコンピューターで動作している Python プログラムをデバッガで監視できるらしい。
以下はプラグインのインストール。Preferences... から
Python プログラムを作る
PyCharm (もしくは、IntelliJ IDEA + Plugin) を使用して Python プログラムを作る。
仮想環境を指定してプロジェクトを作成する。仮想環境を指定するにあたって、PyCharm に作成済みの仮想環境を登録する。
PyCharm に作成済みの仮想環境を登録。~/pyenv/python3/bin/python
を選択することで登録される。
登録した仮想環境を選択。
プロジェクト名はお好みで。
Python プログラムを作成して、実行する。
hello.py
from time import sleep while True: print("Hello") sleep(1)
Raspberry Pi で実行する
前回、pidep コマンドを作成して Raspberry Pi にログインせずに macOS から実行できる環境を作った。 pidep コマンドを PyCharm で実行できる様にする。
Preferences... を開き Tools > External Tools と移動。
pidep コマンドを使って hello.py を Raspberry Pi で実行する。
再ログインした際に pidep コマンドを実行すると以下のエラーとなることがある。
Permission denied, please try again. Permission denied, please try again. Permission denied (publickey,password). lost connection
このような場合には Terminal で ssh-add コマンドを実行して認証を済ませておく。
Raspberry Pi の Python 実行環境を整える
概要
USB ケーブル 1 本で Raspberry Pi Zero と接続できる様になったので、Python プログラムを Raspberry Pi Zero で動かしてみます。 しかし、今後の試行錯誤を考え、(自分にとっての)プログラムを作りやすい環境を整えてみました。 具体的には以下を行なっています。
- ssh でのログインをパスワードなしにする
- Python 2.x 系と 3.x 系を切り替えられる様にする
- Mac でプログラムを作成し、Raspberry Pi Zero では実行のみ行う様にする
確認環境
- Raspberry Pi Zero
- RASPBIAN JESSIE LITE 2016-11-25
- MacBook Pro 2016 Late
- macOS 10.12
参考情報
- Raspberry Pi ZeroをUSBケーブル1本で遊ぶ | Japanese Raspberry Pi Users Group
- Raspberry Pi Zero からインターネットに接続する方法
- signals - Ctrl-C handling in SSH session - Unix & Linux Stack Exchange
- ssh で接続した時に Ctrl-C をリモートに渡す方法
- 引数を処理する | UNIX & Linux コマンド・シェルスクリプト リファレンス
- bash でコマンド引数を扱う方法
- シェル変数のデフォルト値を設定する、未初期化時にエラーメッセージを出力してスクリプトを強制終了する - 百日半狂乱
- シェル変数にデフォルト値を設定する方法
- virtualenvでpython環境を管理する - Qiita
- virtualenv の使い方
前回の記事
解説
ssh コマンドでパスワードを入力せずにログインする
前回、ssh コマンドでログインできる様になった。 しかし、ssh コマンドでログインする度にパスワードを入力するのは面倒だ。 そこで、公開鍵認証を使用してパスワード入力せずにログインできる様にする。
Mac で鍵ペアを生成して、公開鍵のみを Raspberry Pi の ~/.ssh/authorized_keys に登録する。 秘密鍵は絶対に外部に漏らしてはいけない。 ssh-keygen コマンドは鍵ペアを生成する。 鍵ペアは ~/.ssh ディレクトリに id_rsa (秘密鍵), id_rsa.pub (公開鍵) として生成される。 安全のためにパスフレーズ (passphrase) は入力した方が良い。 id_rsa.pub を Raspberry Pi の ~/.ssh/authorized_keys に登録する。
mac:~ nosix$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/Users/nosix/.ssh/id_rsa): Created directory '/Users/nosix/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/nosix/.ssh/id_rsa. Your public key has been saved in /Users/nosix/.ssh/id_rsa.pub. ...省略... mac:~ nosix$ scp ~/.ssh/id_rsa.pub pi@raspberrypi.local:~ id_rsa.pub 100% 404 0.4KB/s 00:00 mac:~ nosix$ ssh pi@raspberrypi.local ...省略... pi@raspberrypi:~ $ mkdir .ssh pi@raspberrypi:~ $ cat id_rsa.pub >> .ssh/authorized_keys pi@raspberrypi:~ $ rm id_rsa.pub pi@raspberrypi:~ $ exit
authorized_keys は存在していないため cat コマンドではなく mv コマンドでも構わないが、
既に authorized_keys が存在する場合には追記する必要がある。
cat src_file >> dst_file
で追記できることを知っておくと便利かと思う。
以上で設定は完了したので、ssh コマンドでログインしてみる。 途中で接続を続けるかと尋ねられるので yes とする。 Raspberry Pi を識別するための情報(ECDSA key fingerpring)が Mac の ~/.ssh/known_hosts に登録される。 次回からは途中で尋ねられることなくログインできる。
mac:~ nosix$ ssh pi@raspberrypi.local The authenticity of host 'raspberrypi.local (<省略>)' can't be established. ECDSA key fingerprint is SHA256:<省略>. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'raspberrypi.local,<省略>' (ECDSA) to the list of known hosts. The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Fri Dec 16 04:36:43 2016 from <省略> pi@raspberrypi:~ $
ログインできれば成功。 Raspberry Pi (の authorized_keys) に登録した Mac からはパスワードなしでログインできる。 Mac 側では ssh-keygen で入力したパスフレーズを 1 度だけ入力することがある。 パスフレーズで認証しておくことで、ssh でログインする際にはパスワードが不要になる。 パスワードは passwd コマンドで複雑なパスワードに変更する。
~/.bash_profile にコマンドのエイリアス(別名)を登録しておくと便利。 以下の 1 行を追加すると pish コマンドで Raspberry Pi に ssh でログインできる。
alias pish='ssh pi@raspberrypi.local'
PC に再ログインした場合には、ssh-add コマンドを実行して認証する。 認証が完了していない場合には、ssh の実行の際にパスフレーズの入力が求められる。
mac:~ nosix$ pish Enter passphrase for key '/Users/nosix/.ssh/id_rsa':
Python3 環境を Raspberry Pi に作る
Python には 2.x 系と 3.x 系が存在する。 2.x 系と 3.x 系で異なる部分があり、2.x 系で動くからと言って 3.x 系では動かないという場合がある。 もちろん、反対もあり得る。 Raspberry Pi に標準でインストールされている Python は 2.x 系。 3.x 系の Python も導入し、2.x 系と 3.x 系を切り替えられる様にしておく。
Raspberry Pi に python3, pip (Python のパッケージ管理ツール), virtualenv (実行環境を切り替えるツール) をインストールする。 pip を使うことで、多くの人が作ってくれた Python の便利道具(パッケージ)を簡単に導入できる。 パッケージにはバージョンがあり、バージョンの組み合わせによっては動作しないこともある。 様々な実験を行うために個別の実験室(仮想環境; virtualenv)を用意しておくと便利。(実験室は比喩。) パッケージを導入する際には実験室を指定して導入し、他の実験室には影響が及ばない様にする。 また、実験室毎に Python2 と Python3 のいずれを使うかを決めておくことができる。
まず、Raspberry Pi からインターネットに接続できる様にする。 Mac でインターネット共有を設定する。 RNDIS/Ethernet Gadget にチェックを入れる。
次に、python3, python3-rpi.gpio, pip, virtualenv をインストールする。
pi@raspberrypi:~ $ sudo apt-get install python3 ...省略... pi@raspberrypi:~ $ sudo apt-get install python3-rpi.gpio ...省略... pi@raspberrypi:~ $ sudo apt-get install python-pip ...省略... pi@raspberrypi:~ $ sudo pip install virtualenv ...省略...
実験室 (仮想環境; virtualenv) を作成する。 例では、~/pyenv/python2, ~/pyenv/python3 を作成している。 apt-get で install した python3-rpi.gpio を使用するために、--system-site-packages を指定している。 (ディレクトリはお好みで。)
pi@raspberrypi:~ $ mkdir ~/pyenv pi@raspberrypi:~ $ virtualenv -p python2 ~/pyenv/python2 Running virtualenv with interpreter /usr/bin/python2 New python executable in /home/pi/pyenv/python2/bin/python2 Also creating executable in /home/pi/pyenv/python2/bin/python Installing setuptools, pip, wheel...done. pi@raspberrypi:~ $ virtualenv --system-site-packages -p python3 ~/pyenv/python3 Running virtualenv with interpreter /usr/bin/python3 Using base prefix '/usr' New python executable in /home/pi/pyenv/python3/bin/python3 Also creating executable in /home/pi/pyenv/python3/bin/python Installing setuptools, pip, wheel...done.
試しに実験室に入る。activate を source コマンドで読み込むと仮想環境が有効になる。
pi@raspberrypi:~ $ source ~/pyenv/python3/bin/activate (python3) pi@raspberrypi:~ $ (python3) pi@raspberrypi:~ $ python --version Python 3.4.2
実験室から出る(仮想環境を無効にする)には、deactivate コマンドを使う。
(python3) pi@raspberrypi:~ $ deactivate pi@raspberrypi:~ $
以降、pip でパッケージをインストールする際には、実験室に入ってから行う。 全ての実験室で共通して使いたいパッケージの場合には、実験室に入らずに pip でインストールする。
Mac 環境でソースコードを作成して、Raspberry Pi で動かす
Raspberry Pi で IDLE を使用してソースコードを編集しても良いが、Mac 環境の方がツールも多く便利である。 Mac 環境でソースコードを作成して、Raspberry Pi にコピーして Raspberry Pi で実行する仕組みを用意する。 (この節の内容は試行中のものです。)
~/bin/pidep コマンドを自作する。(dep は Deploy の意。) Mac から Raspberry Pi にファイルを scp でコピーして、Mac から ssh で実行するスクリプトになっている。
コマンドを実行できる様にする。
mac:~ nosix$ chmod +x ~/bin/pidep
Raspberry Pi に ~/pyhome ディレクトリと仮想環境 ~/pyenv/python3 を用意しておく。
pi@raspberrypi:~ $ mkdir ~/pyhome
pidep の PI_HOME と PI_ENV で指定している。 PI_HOME はコピー先のルート、PI_ENV は実行時に使用する仮想環境の指定。
使い方
まずは、Python3 プログラム(hello.py)を用意する。1 秒毎に Hello と表示される。
from time import sleep while True: print("Hello") sleep(1)
このプログラムを pidep で Raspberry Pi にコピーして実行する。 -s はコピー元、-r は実行するプログラム(スクリプト)を指定する。
mac:tmp nosix$ pidep -s hello.py -r hello.py hello.py 100% 68 0.1KB/s 00:00 Hello Hello Hello Hello ^CTraceback (most recent call last): File "hello.py", line 5, in <module> sleep(1) KeyboardInterrupt Connection to raspberrypi.local closed.
-d でコピー先を指定できる。 -r を省略するとコピーのみ、-s を省略すると実行のみ行われる。
mac:tmp nosix$ pidep -s hello.py -d loop.py -r loop.py mac:tmp nosix$ pidep -r hello.py mac:tmp nosix$ pidep -s hello.py
Raspberry Pi Zero を USB ケーブル 1 本で遊ぶ
概要
Raspberry Pi Zero をディスプレイ、ネットワークアダプタなしで使用する方法です。 類似タイトルの記事がいくつかあったので、それらの記事に倣っています。 2016-11-25 版の Raspbian では ssh がデフォルト off となっているため、ssh を有効化する設定を追記しています。
確認環境
- Raspberry Pi Zero
- RASPBIAN JESSIE LITE 2016-11-25
- MacBook Pro 2016 Late
- macOS 10.12
- MacBook Air 2011 Mid
- MacBook Pro 2016 Late にSDカードスロットがないため、SDカード書き込み用として使用
参考情報
- Raspberry Pi ZeroをUSBケーブル1本で遊ぶ | Japanese Raspberry Pi Users Group
- Raspberry Pi ZeroをUSBケーブル1本で遊べるようにする - Qiita
- Raspberry Pi • View topic - RASPBIAN JESSIE LITE 2016-11-25 ssh turned off
- 2016-11-25 RASPBIAN JESSIE はデフォルトで ssh が off だよという話
- A security update for Raspbian PIXEL - Raspberry Pi
- 2016-11-25 RASPBIAN JESSIE のセキュリティアップデート情報
- Release Notes
- 2016-11-25 RASPBIAN JESSIE の ChangeLog
- Raspberry PiへのOSインストールの手順 ddコマンド編 | Very Berry Pi
- SDカードへの書き込み
解説
SDカードに Raspbian を書き込む
Raspbian Jessie Lite のイメージファイルをダウンロード。 4GB以上の容量のあるSDカードを用意する。
diskutil コマンド、dd コマンドを使用して、イメージファイルをSDカードに書き込む。環境により異なるため省略して記載する。
diskutil list
でSDカードが接続されているデバイスを特定sudo diskutil unmount /dev/<上記で調べたデバイス>
でアンマウントsudo dd bs=1m if=2016-11-25-raspbian-jessie-lite.img of=/dev/<上記で調べたデバイス>
で書き込む
設定を変更する
SDカードへの書き込みが完了すると自動的にマウントされて Finder に boot が表示される。
config.txt, cmdline.txt を書き換える。
- config.txt
dtoverlay=dwc2
を追記
- cmdline.txt
... rootwait modules-load=dwc2,g_ether quiet init=/usr/lib/raspi-config/init_resize.sh
ssh ファイルを作成する。2016-11-25 では ssh はデフォルトで off となっている。boot に ssh ファイルを置くことで on となる。
$ cd /Volumes/boot $ touch ssh
Finder で boot を取り出す。以上でSDカードの準備は完了。
Raspberry Pi Zero を起動する
SDカードを挿してから、USBケーブルをPCと接続する。 接続するとOSが起動するので待つ。 電源はPCから供給される。 緑ランプの点滅が収まれば起動が完了していると思われる。 (USBケーブルは家にあった適当なケーブルを使ったら繋がった。 USBケーブルによっては動作しないとのことなので注意。 参考情報のサイトを参照。)
ssh で接続する
PCのターミナルを起動し、以下を実行する。password は raspberry
。
mac:~ nosix$ ssh pi@raspberrypi.local The authenticity of host 'raspberrypi.local (169.254.225.196)' can't be established. ECDSA key fingerprint is SHA256:<内緒>. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'raspberrypi.local,169.254.225.196' (ECDSA) to the list of known hosts. pi@raspberrypi.local's password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. SSH is enabled and the default password for the 'pi' user has not been changed. This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password. pi@raspberrypi:~ $
セキュリティリスクがあるので passwd コマンドで新しいパスワードに設定するように書かれている。
Windows 10 でパーティションサイズを変更する
※1 : 2017.07.22 追記/修正
※2 : 2017.09.14 追記
※3 : 2017.12.06 追記
概要
VMware を使用しているとディスクサイズを自由に変更することができます。 ディスクサイズを増やした時に C ドライブのパーティションサイズを拡張することになりますが、 回復パーティションが存在するために拡張できません。 本記事では、回復パーティションを移動して、パーティションサイズを拡張する方法を説明します。
私の環境(下記の確認環境)にて実施して確認した手順です。 他の環境にて動作を保証するものではありません。 他の環境のサポートは致しかねます。(※1)
確認環境
- Windows 10 Pro
- バージョン 1607 (※1)
- OS ビルド 14393.479 (※1)
- VMware Fusion 8.5.8 (※1)
参考情報
- Windows8.1 パーティションを移動してHDD領域の余りを使う: 家庭部PC科
- 日本語で書かれた記事。わかりやすいが確認方法に問題があると思われる。
- https://msdn.microsoft.com/ja-jp/library/hh825089.aspx
- Microsoft 公式
- https://msdn.microsoft.com/ja-jp/library/hh825686.aspx
- Microsoft 公式
解説
全体の手順は以下の通り。
- 回復パーティションにドライブレターを割り当てる
- 回復イメージを保存する
- 回復パーティションを削除する
- 回復ドライブを作成できないことを確認する
- C ドライブを拡張する
- 新規パーティション(回復パーティションになる)を作成する
- 回復パーティションに設定する
- 回復パーティションのドライブレターを削除する
- 回復ドライブを作成できることを確認する
コマンドは全て管理者として実行する。
回復パーティションにドライブレターを割り当てる
回復パーティションにドライブレター R を割り当てる。
C:\WINDOWS\system32>diskpart Microsoft DiskPart バージョン 10.0.14393.0 Copyright (C) 1999-2013 Microsoft Corporation. コンピューター: XXX DISKPART> list disk ディスク 状態 サイズ 空き ダイナ GPT ### ミック ------------ ------------- ------- ------- --- --- ディスク 0 オンライン 64 GB 29 GB DISKPART> select disk 0 ディスク 0 が選択されました。 DISKPART> list partition Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 プライマリ 500 MB 1024 KB Partition 2 プライマリ 33 GB 501 MB Partition 3 回復 450 MB 33 GB DISKPART> select partition 3 パーティション 3 が選択されました。 DISKPART> assign letter=R DiskPart はドライブ文字またはマウント ポイントを正常に割り当てました。 DISKPART> exit DiskPart を終了しています...
回復イメージを保存する
R ドライブに隠されている回復イメージ Winre.wim
を参照できるようにした後に、コピーする。
C:\WINDOWS\system32>attrib R:\Recovery\WindowsRE\Winre.wim -h -s -r C:\WINDOWS\system32>copy R:\Recovery\WindowsRE\Winre.wim C:\ 1 個のファイルをコピーしました。
回復パーティションを削除する
ドライブレターを削除した後にパーティションを削除する。 ドライブレターの削除を忘れると、後で同じドライブレターを使用できなくなるので注意。
C:\WINDOWS\system32>diskpart Microsoft DiskPart バージョン 10.0.14393.0 Copyright (C) 1999-2013 Microsoft Corporation. コンピューター: XXX DISKPART> select disk 0 ディスク 0 が選択されました。 DISKPART> select partition 3 パーティション 3 が選択されました。 DISKPART> remove letter=R DiskPart はドライブ文字またはマウント ポイントを正常に削除しました。 DISKPART> delete partition override DiskPart は選択されたパーティションを正常に削除しました。 DISKPART> exit DiskPart を終了しています...
回復ドライブを作成できないことを確認する
以下に示す手順により回復ドライブを作成できないことを確認する。
回復パーティションが削除された状態で回復ドライブの作成を行うと以下の結果となる。
C ドライブを拡張する
回復パーティションのサイズを覚えておく。
ドライブ C のパーティションを拡張する。回復パーティションのサイズ分だけ残す。
回復パーティションの領域を残して拡張した結果。
新規パーティション(回復パーティションになる)を作成する
新規パーティションを作成し、R ドライブとして設定する。
C:\WINDOWS\system32>diskpart Microsoft DiskPart バージョン 10.0.14393.0 Copyright (C) 1999-2013 Microsoft Corporation. コンピューター: XXX DISKPART> select disk 0 ディスク 0 が選択されました。 DISKPART> create partition primary DiskPart は指定したパーティションの作成に成功しました。 DISKPART> format quick fs=ntfs 100% 完了しました DiskPart は、ボリュームのフォーマットを完了しました。 DISKPART> assign letter=R DiskPart はドライブ文字またはマウント ポイントを正常に割り当てました。 DISKPART> exit DiskPart を終了しています...
回復パーティションに設定する
R ドライブにフォルダを作成し、回復イメージを配置する。 回復イメージの場所を設定し、有効化する。
(本記事執筆時の私の環境では下記の方法で設定できていましたが、 Windows 10 では REAgentC の仕様が変更されているとコメントにて情報を頂きました。 https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn938308(v=vs.85).aspx (※2))
C:\WINDOWS\system32>md R:\Recovery\WindowsRE C:\WINDOWS\system32>copy C:\Winre.wim R:\Recovery\WindowsRE 1 個のファイルをコピーしました。 C:\WINDOWS\system32>C:\Windows\System32\reagentc /setosimage /path R:\Recovery\WindowsRE /index 1 ディレクトリは次に設定されています: \\?\GLOBALROOT\device\harddisk0\partition3\Recovery\WindowsRE REAGENTC.EXE: 操作は成功しました。 C:\WINDOWS\system32>C:\Windows\System32\reagentc /enable REAGENTC.EXE: 操作は成功しました。 (※1)
回復パーティションのドライブレターを削除する
設定は完了したため、ドライブレターは削除する。 回復パーティション(id=27)に設定する。
C:\WINDOWS\system32>diskpart Microsoft DiskPart バージョン 10.0.14393.0 Copyright (C) 1999-2013 Microsoft Corporation. コンピューター: XXX DISKPART> select disk 0 ディスク 0 が選択されました。 DISKPART> list partition Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 プライマリ 500 MB 1024 KB Partition 2 プライマリ 63 GB 501 MB Partition 3 プライマリ 451 MB 63 GB DISKPART> select partition 3 パーティション 3 が選択されました。 DISKPART> remove letter=R DiskPart はドライブ文字またはマウント ポイントを正常に削除しました。 DISKPART> set id=27 DiskPart は、パーティション ID を設定しました。 DISKPART> exit DiskPart を終了しています...
set id=27
では、「指定された種類は正しい形式ではありません。」とエラーになることがあるとの情報を頂きました。
その場合には、以下の様にするとのことです。(https://technet.microsoft.com/ja-jp/library/dd744301(v=ws.10).aspx) (※3)
set id=de94bba4-06d1-4d40-a16a-bfd50179d6ac
回復ドライブを作成できることを確認する
「回復ドライブを作成できないことを確認する」で行った手順を行う。 成功していれば以下の結果になる。
Thymeleaf で isXxx プロパティを参照するとエラーになる
概要
Thymeleaf の変数式で ${aVariable.isXxx} とするとエラーになって困った時の記録です。
確認環境
- Spring Boot 1.4.2
- Spring 4.3.4
- Thymeleaf 2.1.5, 3.0.0
- Kotlin 1.0.5
解説
Kotlin で次のクラスを作成したとする。
data class User( val name: String, val age: Int, val address: Address, val isEnabled: Boolean)
Java ならば以下のようになる。
public class User { private final String name; private final int age; private final Address address; private final boolean isEnabled; public boolean isEnabled() { return isEnabled; } ... (setter/getter, toString, equals, hashCode メソッドと続くが省略) }
Thymeleaf では User オブジェクトの isEnabled プロパティを参照するために以下のように書く。
<span th:text="${user.isEnabled}">どうなるでしょう?</span>
これはエラーになる。isEnabled プロパティが見つからないと。 isEnabled ではなく enabled とすることで参照できる。
<span th:text="${user.enabled}">参照できる</span>
何故エラーになるのかと思い、デバッガで確認した。
org.springframework.expression.spel.support.ReflectivePropertyAccessor クラスの findGetterForProperty メソッドでは、 propertyName=isEnabled を IsEnabled に変換した後に findMethodForProperty メソッドを呼ぶ。
findMethodForProperty メソッドでは、prefix=is と methodSuffix=IsEnabled を結合して isIsEnabled とした上でメソッド名と equals で比較。
プロパティ名を enabled とすれば、isEnabled となるため参照できる。
Thymeleaf は内部的に SpEL (非SpringではOGNL) を使って式を解釈している。 上記は SpEL の一部に該当する。