WPP
QEMU のモニタで disassemble したい

先日から Mikan 本をやっているのは既出ですが、QEMU モニタでアセンブラ出力できないことにきづきました。今使っている QEMU は LM22 (Ubuntu 24) レポジトリのものを安直につかっていたのですが、その機能がアクティブになっていないようなので、自前ビルドしました。

公式から 9.1.1 をダウンロードして解凍したあと、./configure すると色々とモジュールが不足kしていると文句を言われます。ので順次インストールしていきます。

結論としては libcapstone-dev をインストールする必要があるようです。

参考

https://download.qemu.org/qemu-9.1.1.tar.xz

Hosts/Linux – QEMU

Remmina でRDP接続した時に IME を使えるようにする

何故か NoaMachine で Windows に接続できなくなったので、Remmina を使うことにした。Remmina は RDP 以外にも色々なプロトコルに対応しているがそんことはどうでもいい。

でタイトルに戻ると、認証情報を入力し画面は表示するが IME の入力がどうしてもできなかった。

三本線のメニューアイコンから Preferences > RDP で [Use client keyboard mapping] のチェックを外すと動作した。

もしかしたら Linux PC には US 配列のキーボードを接続しているのが原因なのかもしれない。というのも接続先の Win11 PCには日本語キーボードが接続されているのでマップに不整合が起きているのかもしれない。

参考

Remmina で RDP 接続したら IME 経由で日本語が入力できなくなった【解決】 | 穀風

LM22 Thinkpad のトラックパッドで2本指スクロール

Linux Mint 22 を Thinkpad で動かしていますが、本体付属のトラックパッドで2本指スクロールができないことに気づきました。普段は外付けトラックボールを使用しているので気にしていなかったのですがせっかくなので直してみます。

Linux Mint 22 をインストールするとトラックパッドそのものは認識してくれていて1本指操作や中央ボタンのスクロールは何もしなくても機能してくれます。

$ sudo apt install xserver-xorg-input-synaptics xserver-xorg-input-evdev
$ synclient VertTwoFingerScroll=1

xserver-xorg-input-all も必要らしいですが、トラックパッドが使えているのであれば恐らく入っているはずです。

これで、GUI で設定してもきちんと2本指スクロールを On / Off できるようになりました。

参考

Ubuntu 18.04LTSで2本指のスクロールをアクティブにする方法

cmake のフラグ一覧

cmake がよくわからないのでメモ。

昨日から続けている librealsense2 ですが、python3.12 で pyrealsense2 を使うためには自前ビルドしなければいけない状況なりました。そして librealsense2 は cmake が使われています。

librealsense2 をビルドする時には例えば -DBUILD_EXAMPLES=true とか指定できるのですが、他のオプションは何があるのだろうということで調べました。

cmake の基本的な知識ですが -L とか -LA をつけると一覧が見れるようです。

libsense2 2.56.1 で自分の環境で実行するとこうなります。

$ mkdir build
$ cd build
$ cmake ..
$ cmake .. -LA
-- Checking internet connection...
-- Internet connection identified
-- Info: REALSENSE_VERSION_STRING=2.56.1
-- Setting Unix configurations
-- No output directory set; using /media/mnishi/opt/ws-sf/rs2/librealsense/build/Release/
-- Fetching pybind11...
CMake Deprecation Warning at build/third-party/pybind11/CMakeLists.txt:8 (cmake_minimum_required):
  Compatibility with CMake < 3.5 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


-- pybind11 v2.10.3 
CMake Warning (dev) at build/third-party/pybind11/tools/FindPythonLibsNew.cmake:98 (find_package):
  Policy CMP0148 is not set: The FindPythonInterp and FindPythonLibs modules
  are removed.  Run "cmake --help-policy CMP0148" for policy details.  Use
  the cmake_policy command to set the policy and suppress this warning.

Call Stack (most recent call first):
  build/third-party/pybind11/tools/pybind11Tools.cmake:50 (find_package)
  build/third-party/pybind11/tools/pybind11Common.cmake:180 (include)
  build/third-party/pybind11/CMakeLists.txt:208 (include)
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Fetching pybind11 - Done
-- Fetching pybind11_json...
-- Fetching pybind11_json - Done
-- Building libcurl enabled
-- using RS2_USE_V4L2_BACKEND
-- Fetching nlohmann/json...
-- Using the multi-header code from /media/mnishi/opt/ws-sf/rs2/librealsense/build/third-party/json/include/
-- Fetching nlohmann/json - Done
-- Check for updates capability added to realsense-viewer
-- Check for updates capability added to realsense-depth-quality
-- Fetching recommended firmwares:
-- disable link time optimization for fw project
-- ... https://librealsense.intel.com/Releases/RS4xx/FW/D4XX_FW_Image-5.16.0.1.bin
-- Configuring done (2.2s)
-- Generating done (0.1s)
-- Build files have been written to: /media/mnishi/opt/ws-sf/rs2/librealsense/build
-- Cache values
ANDROID_USB_HOST_UVC:BOOL=OFF
BUILD_CSHARP_BINDINGS:BOOL=OFF
BUILD_CV_EXAMPLES:BOOL=OFF
BUILD_CV_KINFU_EXAMPLE:BOOL=OFF
BUILD_DLIB_EXAMPLES:BOOL=OFF
BUILD_EASYLOGGINGPP:BOOL=ON
BUILD_EXAMPLES:STRING=true
BUILD_GLSL_EXTENSIONS:BOOL=ON
BUILD_GRAPHICAL_EXAMPLES:BOOL=ON
BUILD_LEGACY_LIVE_TEST:BOOL=OFF
BUILD_LEGACY_PYBACKEND:BOOL=OFF
BUILD_MATLAB_BINDINGS:BOOL=OFF
BUILD_OPEN3D_EXAMPLES:BOOL=OFF
BUILD_OPENNI2_BINDINGS:BOOL=OFF
BUILD_OPENVINO_EXAMPLES:BOOL=OFF
BUILD_PCL_EXAMPLES:BOOL=OFF
BUILD_PC_STITCHING:BOOL=OFF
BUILD_PYTHON_BINDINGS:STRING=true
BUILD_PYTHON_DOCS:BOOL=OFF
BUILD_RS2_ALL:BOOL=ON
BUILD_SHARED_LIBS:BOOL=ON
BUILD_TOOLS:BOOL=ON
BUILD_UNITY_BINDINGS:BOOL=OFF
BUILD_UNIT_TESTS:BOOL=OFF
BUILD_WITH_CPU_EXTENSIONS:BOOL=ON
BUILD_WITH_CUDA:BOOL=OFF
BUILD_WITH_DDS:BOOL=OFF
BUILD_WITH_OPENMP:BOOL=OFF
BUILD_WITH_STATIC_CRT:BOOL=ON
CCACHE_FOUND:FILEPATH=CCACHE_FOUND-NOTFOUND
CHECK_FOR_UPDATES:BOOL=ON
CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line
CMAKE_AR:FILEPATH=/usr/bin/ar
CMAKE_BUILD_TYPE:STRING=
CMAKE_COLOR_MAKEFILE:BOOL=ON
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++
CMAKE_CXX_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-13
CMAKE_CXX_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-13
CMAKE_CXX_FLAGS:STRING=
CMAKE_CXX_FLAGS_DEBUG:STRING=-g
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc
CMAKE_C_COMPILER_AR:FILEPATH=/usr/bin/gcc-ar-13
CMAKE_C_COMPILER_RANLIB:FILEPATH=/usr/bin/gcc-ranlib-13
CMAKE_C_FLAGS:STRING=
CMAKE_C_FLAGS_DEBUG:STRING=-g
CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
CMAKE_DLLTOOL:FILEPATH=CMAKE_DLLTOOL-NOTFOUND
CMAKE_EXE_LINKER_FLAGS:STRING=
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=
CMAKE_INSTALL_BINDIR:PATH=bin
CMAKE_INSTALL_DATADIR:PATH=
CMAKE_INSTALL_DATAROOTDIR:PATH=share
CMAKE_INSTALL_DOCDIR:PATH=
CMAKE_INSTALL_INCLUDEDIR:PATH=include
CMAKE_INSTALL_INFODIR:PATH=
CMAKE_INSTALL_LIBDIR:PATH=lib
CMAKE_INSTALL_LIBEXECDIR:PATH=libexec
CMAKE_INSTALL_LOCALEDIR:PATH=
CMAKE_INSTALL_LOCALSTATEDIR:PATH=var
CMAKE_INSTALL_MANDIR:PATH=
CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include
CMAKE_INSTALL_PREFIX:PATH=/usr/local
CMAKE_INSTALL_RUNSTATEDIR:PATH=
CMAKE_INSTALL_SBINDIR:PATH=sbin
CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com
CMAKE_INSTALL_SYSCONFDIR:PATH=etc
CMAKE_LINKER:FILEPATH=/usr/bin/ld
CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/gmake
CMAKE_MODULE_LINKER_FLAGS:STRING=
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_NM:FILEPATH=/usr/bin/nm
CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy
CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump
CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib
CMAKE_READELF:FILEPATH=/usr/bin/readelf
CMAKE_SHARED_LINKER_FLAGS:STRING=
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
CMAKE_SKIP_RPATH:BOOL=NO
CMAKE_STATIC_LINKER_FLAGS:STRING=
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
CMAKE_STRIP:FILEPATH=/usr/bin/strip
CMAKE_TAPI:FILEPATH=CMAKE_TAPI-NOTFOUND
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
COM_MULTITHREADED:BOOL=ON
ENABLE_CCACHE:BOOL=ON
ENABLE_EASYLOGGINGPP_ASYNC:BOOL=ON
ENFORCE_METADATA:BOOL=OFF
FORCE_LIBUVC:BOOL=OFF
FORCE_RSUSB_BACKEND:BOOL=OFF
FORCE_WINUSB_UVC:BOOL=OFF
GIT_EXECUTABLE:FILEPATH=/usr/bin/git
HWM_OVER_XU:BOOL=ON
IMPORT_DEPTH_CAM_FW:BOOL=ON
JSON_BuildTests:BOOL=OFF
JSON_CI:BOOL=OFF
JSON_Diagnostics:BOOL=OFF
JSON_DisableEnumSerialization:BOOL=OFF
JSON_GlobalUDLs:BOOL=ON
JSON_ImplicitConversions:BOOL=ON
JSON_Install:BOOL=OFF
JSON_LegacyDiscardedValueComparison:BOOL=OFF
JSON_MultipleHeaders:BOOL=ON
JSON_SystemInclude:BOOL=OFF
LIBUSB_INC:PATH=/usr/include/libusb-1.0
LIBUSB_LIB:FILEPATH=/usr/lib/x86_64-linux-gnu/libusb-1.0.so
OPENGL_EGL_INCLUDE_DIR:PATH=/usr/include
OPENGL_GLES2_INCLUDE_DIR:PATH=/usr/include
OPENGL_GLES3_INCLUDE_DIR:PATH=/usr/include
OPENGL_GLX_INCLUDE_DIR:PATH=/usr/include
OPENGL_INCLUDE_DIR:PATH=/usr/include
OPENGL_egl_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libEGL.so
OPENGL_gles2_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libGLESv2.so
OPENGL_gles3_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libGLESv2.so
OPENGL_glu_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libGLU.so
OPENGL_glx_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libGLX.so
OPENGL_opengl_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libOpenGL.so
OPENGL_xmesa_INCLUDE_DIR:PATH=OPENGL_xmesa_INCLUDE_DIR-NOTFOUND
OPENSSL_CRYPTO_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libcrypto.so
OPENSSL_INCLUDE_DIR:PATH=/usr/include
OPENSSL_SSL_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libssl.so
PKG_CONFIG_ARGN:STRING=
PKG_CONFIG_EXECUTABLE:FILEPATH=/usr/bin/pkg-config
PYBIND11_FINDPYTHON:BOOL=OFF
PYBIND11_INSTALL:BOOL=OFF
PYBIND11_INTERNALS_VERSION:STRING=
PYBIND11_NOPYTHON:BOOL=OFF
PYBIND11_PYTHONLIBS_OVERWRITE:BOOL=ON
PYBIND11_PYTHON_VERSION:STRING=
PYBIND11_SIMPLE_GIL_MANAGEMENT:BOOL=OFF
PYBIND11_TEST:BOOL=OFF
PYTHON_EXECUTABLE:FILEPATH=/media/mnishi/opt/ws-sf/rs2/.venv/bin/python
PYTHON_INSTALL_DIR:PATH=/media/mnishi/opt/ws-sf/rs2/.venv/lib/python3.12/site-packages/pyrealsense2
PYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.12.so
REALSENSE_FIRMWARE_URL:STRING=https://librealsense.intel.com
UDEV_INCLUDE_DIRS:PATH=/usr/include
UDEV_LIBRARIES:FILEPATH=/usr/lib/x86_64-linux-gnu/libudev.so
UNIT_TESTS_ARGS:STRING=
glfw3_DIR:PATH=/usr/lib/x86_64-linux-gnu/cmake/glfw3
pkgcfg_lib_UDEV_PKGCONF_udev:FILEPATH=/usr/lib/x86_64-linux-gnu/libudev.so
pkgcfg_lib__OPENSSL_crypto:FILEPATH=/usr/lib/x86_64-linux-gnu/libcrypto.so
pkgcfg_lib__OPENSSL_ssl:FILEPATH=/usr/lib/x86_64-linux-gnu/libssl.so
(rs2) mnishi@tpe14:/media/mnishi/opt/ws-sf/rs2/librealsense/build$ 

参考

cmakeプロジェクトの設定項目一覧を表示させる – かみのメモ

Linux Mint 22 に librealsense2 をインストール

今日はちょっと話題を変えて intel RealSense を試す機会があり早速 LM22 にインストールしてみた

基本的には公式の手順通りなのだが、Linux Mint なので Ubuntu のコードネームを正しく設定してやる必要がある。

通常なら lsb_release -csubuntu-distro-info -cs に変更すれば OK なようだが、librealsense2 は Ubuntu 24 (noble) には完全に対応していないようで librealsense2-utils とかが存在しない

なので一つ前の jammy にしてみる。

; pgp キーの追加
$ sudo mkdir -p /etc/apt/keyrings
$ curl -sSf https://librealsense.intel.com/Debian/librealsense.pgp | sudo tee /etc/apt/keyrings/librealsense.pgp > /dev/null

; lsb_release だと LM22 のコードネーム wilma を返してくる
; $ echo "deb [signed-by=/etc/apt/keyrings/librealsense.pgp] https://librealsense.intel.com/Debian/apt-repo `lsb_release -cs` main" | \
sudo tee /etc/apt/sources.list.d/librealsense.list

$ echo "deb [signed-by=/etc/apt/keyrings/librealsense.pgp] https://librealsense.intel.com/Debian/apt-repo jammy main" | \
sudo tee /etc/apt/sources.list.d/librealsense.list

$ sudo apt-get update

$ sudo apt install librealsense2-dkms librealsense2-utils
$ sudo apt isntall librealsense2-dev librealsense2-dbg

; とりあえずビューアが動くか確認
$ realsense-viewer

; キャリブレータと依存ライブラリ
$ apt install libgult3.12 librscalibrationtool
$sudo ln -s /usr/lib/x86_64-linux-gnu/libglut.so.3.12 /usr/lib/x86_64-linux-gnu/libglut.so.3

ubuntu-distro-info コマンド使えば Ubuntu のコードネームを簡単にとれることを覚えておこう。今まで気づきませんでした。docker とか virtualbox とかの独自リポジトリで配布している時に便利に使えそう。

それにしても apt とかのリポジトリでどのコードネームが実際ホストしているかってどうやって調べたら良いのか?まだまだ知らないことは多い。

参考

librealsense/doc/distribution_linux.md at master · IntelRealSense/librealsense

Realsense カメラキャリブレーション 400シリーズ D415 D435 #RealSense – Qiita

KivyMD の NavigationDrawer に RecycleView を追加するサンプル

引き続き、Kivy です。

今回は、KivyMD の NavigationDrawer の中に RecycleView を突っ込んでみます。Kivy / KivyMD はここのコンポーネントを動作確認する分には特別難しいことはありませんが、複数組み合わせるとトタンになかなかいい感じに配置することができないのが難点だと思う。(自分の理解の浅さのせいかもしれないが、HTML/CSS の方がまだましに感じます。)

提示するサンプルを実行するとこんな感じになります。前回と同じように Appbar が画面上部にあり、 Appbar のアイコンを押すと、NavigationDrawer が表示されます。その NavigationDrawer の中に 果物の名前のリストを表示しています。

Appbar のアイコンが左で、ドロワーが右から出てくるのは違和感があるかもしれませんが anchor の確認のためにあえて行っています。

環境

  • Kivy 2.3.0
  • KivyMD 2.0.1.dev

コード

from kivy.lang import Builder

from kivy.properties import StringProperty

from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.recycleview import MDRecycleView


KV = '''
MDScreen:

    MDNavigationLayout:
        # size_hint_x: 1

        ScreenManager:
            MDScreen:

                MDBoxLayout:
                    md_bg_color: self.theme_cls.secondaryContainerColor
                    orientation:'vertical'
                    
                    MDTopAppBar:                        
                        MDTopAppBarLeadingButtonContainer:
                            MDActionTopAppBarButton:
                                icon: 'menu'
                                on_release: nav_drawer.set_state('toggle')
                            
                        MDTopAppBarTitle:
                            text: 'this is AppBar'
                            pos_hint: {'center_x': .5}
                            
                    MDLabel:
                        text: "I'm MDLabel"

        MDNavigationDrawer:
            anchor: 'right'

            MDBoxLayout:
                orientation: 'vertical'

                MDNavigationDrawerLabel:
                    text: 'drawer items!!'
                    icon: 'format-list-bulleted'

                MDNavigationDrawerDivider:

                NvDrawerRecycleItem:                    
                    id: rv
                    padding: 0, nav_drawer.height, 0, 0
                    viewclass: 'Food'
                    RecycleBoxLayout:
                        size_hint: (1, None)
                        height: self.minimum_height
                        orientation:'vertical'

<NvDrawerRecycleItem>:

<Food>:
    text: 'name: {}'.format(self.item)
    adaptive_size: True
    padding: 0, dp(16), 0, dp(16)

'''

class Food(MDLabel):
    item = StringProperty('')

class NvDrawerRecycleItem(MDRecycleView):
    pass


class TestNavigationDrawer(MDApp):
    def build(self):
        self.theme_cls.theme_style = 'Dark'  # or 'Light'
        return Builder.load_string(KV)
    
    def on_start(self):
        rv = self.root.ids.rv
        rv.data = (
            { 'item': it }
            for it in [
                'Apple', 'Banana', 'Cherry', 'Grape', 'Lemon',
                'Mikan', 'Orange', 'Pear', 'Lychee', 'Strawberry',
                'Peach', 'Fig'
            ]
        )


TestNavigationDrawer().run()

公式のサンプルでは MDNavigationDrawerMenu の中に Drawer の中身を入れてるのですが、そうすると RecycleView と MDNavigationDrawerMenu の間に大きな隙間ができてしまい。どうしても制御することができませんでした。

また、MDBoxLayout: orientation: ‘vertical’ で囲ってあげないと ドロワー系のアイテムと RecycleView が横並びになってしまいました。

そのため、上のようなサンプルコードになりました。


        MDNavigationDrawer:
            id: nav_drawer
            anchor: 'right'

            MDBoxLayout:
                orientation: 'vertical'

                MDNavigationDrawerMenul:
                    MDNavigationDrawerLabel:
                       text: 'drawer items!!'
                       icon: 'format-list-bulleted'

                      MDNavigationDrawerDivider:

                NvDrawerRecycleItem:                    
                    id: rv
                    padding: 0, nav_drawer.height, 0, 0
                    viewclass: 'Food'
                    RecycleBoxLayout:
                        size_hint: (1, None)
                        height: self.minimum_height
                        orientation:'vertical'

今作りたいものをやるのにドロワーの中にリスト入れればいけるんじゃね?と安直に考えてやってみたがなかなかしんどかった。Kivy の道はきびしい。

KivyMD の Appbar 画面上部にピッタリに配置する方法

さあ、今日も Kivy の話です。

KivyMD にはあたかも Android アプリのような Appbar というコンポーネントがあります。これを画面のトップに配置して下部分に大きさピッタリのコンテンツを配置する方法のメモです。

やりたいことは、2つあります。

  1. Appbar を画面トップに配置する。
  2. 空いた下の領域いっぱいにコンテンツを表示する。

結果はこんな感じになります。

画像を入れる

環境

  • Kivy 2.3.0
  • KivyMD 2.0.1.dev

最終的なサンプル

from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
MDScreen:
    MDBoxLayout:
        orientation: 'vertical'
        padding: 0,app_bar.height, 0,0      # L T R B

        MDBoxLayout:
            md_bg_color: 0.2,0.2,0.4, 1
            MDLabel:
                text: 'text label'
                valign: 'bottom'

    MDTopAppBar:
        id: app_bar
        pos_hint: {'top': 1}
        
        MDTopAppBarLeadingButtonContainer:
            MDActionTopAppBarButton:
                icon: 'menu'
                
        MDTopAppBarTitle:
            text: 'top appbar'
        
        MDTopAppBarTrailingButtonContainer:
            MDActionTopAppBarButton:
                icon: "github"
'''

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = 'Dark'  # or 'Light'
        return Builder.load_string(KV)
    
if __name__ == '__main__':
    MainApp().run()

画面トップに配置

自分が試した限りでは、 TopAppBar を公式サンプルのまま配置しただけでは画面の上部に表示することはできませんでした。(これバグ何じゃないだろうか ?)

なので pos_hint に ‘top’: 1 を設定してやります。kivy では画面左下が原点になるので ‘top’: 1 は画面の最上部を意味します。(0 – 1.0 が入り割合を示すらしい。)

    MDTopAppBar:
        id: app_bar
        pos_hint: {'top': 1}
        

コンテンツを Appbar の下ギリギリまで配置する

次に、コンテンツ領域の制御です。ここはなにも制限しないと親の大きさいっぱいまで使ってしまいます。つまりコンテンツ領域が Appbar で隠れるか、 Appbar を隠すかしてしまいます。(これは .KV 内の定義の順番によるっぽいです。)

Stack overflow で見つけた解決策は padding を設定して下の領域の大きさを明示的に制限するというものでした。こんな感じです。

padding に設定してやるのは Appbar の高さなので id: 属性を追加します。

追加した id (Appbar) の高さ分 padding でコンテンツ領域を下げてやります。

    MDBoxLayout:
        orientation: 'vertical'
        padding: 0,app_bar.height, 0,0      # Left Top Right Bottom

   # いろいろ省略

    MDTopAppBar:
        id: app_bar
        pos_hint: {'top': 1}
        # size_hint_x: 1

Kivy / KivyMD は配置周りの挙動がよくわからないのが辛い。

参考

python – How do i make an MDBottomAppBar appear on top of a list view in KivyMD – Stack Overflow

Appbar — KivyMD 2.0.1.dev0 documentation

Kivy AnchorLayout が効かない時はサイズを指定すると良い

今回も Kivy ネタです。

下記のようなコードで(コメントアウトは除き) で右寄せが効かずちょいハマりました。

Stack Overflow にスレがあり、CSS のブロックエレメント/インラインエレメント のような感じでMDLabel の幅が max に設定されてしまうようです。

コメントアウトを解除すると無事に右寄せが機能しました。

Label を MDLabel にすると別のスタイルが有効になるようで文字が見切れてしまいます。その場合は size を texture_size から変更する必要があるようです。ここは追求していません。

from kivy.lang import Builder
from kivymd.app import MDApp

KV = '''
MDScreen:
    MDBoxLayout:
        orientation: 'vertical'
        
        AnchorLayout:
            # size_hint_x: 1
            anchor_x: 'right'
            anchor_y: 'center'
    
            Label:
                text: 'menu-'

                # この2行を追加すれば OK
                # size_hint: (None, None)
                # size: self.texture_size
                max_lines: 1                    
                padding: (dp(16), dp(0))
'''

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = 'Dark'  # or 'Light'
        return Builder.load_string(KV)
    

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

参考

python – Kivy AnchorLayout .Kv file – Stack Overflow

Kivy のログレベル変更

さて、今日も Kivy です。 Kivy 戦記ってブログがあるんですが、Kivy をやってる時はまさに「戦い」って感じでいちいち面倒くさいです。

Kivy をコンソールから実行するとログが流れてきます。そのログレベルを変更しようと思います。
というのも、.kv ファイルの記述どおりにどうも動かない現象にぶち当たりましたがデフォルトのログレベルではなにも異常はなさそうだったのでもう少し詳しく見る必要がありました。

どうやら Kivy.config にコンフィグ設定値があるようです。
ログレベルに限らず、Config は環境変数で渡せるようですが、設定ファイルを使ってみます。

自分の環境ではそもそも設定ファイルは、存在しませんでした。おそらくそれが普通のようです。Config のドキュメントから設定値読み取っていちいち手入力するのはだるいなと思っていたら、ファイルに書き出す機能がありました。

$ python -m kivy
>>> from kivy.config import Config as cfg
>>> cfg.write()

こうすると ~/.kivy/config.ini が生成されているはずです。Win/Mac もそれっぽいところにあります。

それはそうと config.ini を書き換えていきます。log 周りの設定だけでなくデフォルトフォントの設定など色々ありそうですが、今回はつかわないので log_level を debug に変更します。

info や debug 以外にもドキュメントにある通り warn, error, trace なんかも設定できるようです。

[kivy]
..... いろいと並んでいる
log_dir =
log_enable =1
log_level = debug
....

にしても Kivy の API (クラス) リファレンスは、キーワードと説明の区別がつけにくくて読み取りにくいのがどうも好きになれない。

参考

Configure Kivy — Kivy 2.3.0 documentation

Configuration object — Kivy 2.3.0 documentation

pipenv で setup.py のパッケージをインストールする方法

pipenv の仮想環境で setup.py をインストールする方法です。

KivyMD の最新を git から持ってくると setup.py でのインストールを求められますが、やり方を知らなかったのでメモします。

pipenv の公式に載っているのですが run pip install すればいいらしい。

$ pipenv run pip install -e .

ちなみに、git で取ってきた KivyMD の example を動作させるには、プロジェクトのルートで python example/xxx.py のように実行するか、PYTHONPATH に追加する必要がある。インストールしても仮想環境にコピーされないので注意。

ついでに requirements.txt でインストールする場合は以下のようになる

$ pipenv install -r ./requirements.txt

参考

pipenv · PyPI

kivymd/KivyMD: KivyMD is a collection of Material Design compliant widgets for use with Kivy