Start_python’s diary

ふたり暮らし

アラフィフ夫婦のフリーランスプラン

Python 一部のレイアウトだけ変更する(kivy 画面遷移)

f:id:Start_python:20200108161637g:plain

はじめに

前回の続きでGIFファイルを表示しようと思いましたが、先にレイアウトの切り替えが必要になりました。画面のスライドで使ったCarouselを利用します。

 

プログラムのコード

# フル画面を解除して画面の幅と高さを設定
from kivy.config import Config
Config.set('graphics', 'fullscreen', 0)
Config.set('graphics', 'width', 320)
Config.set('graphics', 'height', 568)
Config.set('graphics', 'resizable', 1)

import os
import glob
import cv2
import numpy as np
from PIL import Image

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Label
from kivy.uix.button import Button
from kivy.uix.image import Image as Img
from kivy.graphics.texture import Texture

from kivy.core.text import LabelBase, DEFAULT_FONT
from kivy.resources import resource_add_path

resource_add_path('c:/Windows/Fonts')
LabelBase.register(DEFAULT_FONT, 'msgothic.ttc')


class CustomLayout(BoxLayout):
    pass


class MainScreen(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        files = glob.glob('./data/*.gif')
        for file in files:

            gif = cv2.VideoCapture(file)
            is_success, img = gif.read()

            image = np.array(img)
            image = image[:, :, [2, 1, 0]]    # BGR <-> RGB
            image = Image.fromarray(image)

            texture = Texture.create(size=image.size) 
            texture.blit_buffer(image.tobytes())
            texture.flip_vertical()

            self.ids.sv.add_widget(Img(texture = texture, size_hint_x=None, width=80))
            btn = Button(text=os.path.basename(file), on_release=self.on_command,
                    size_hint_y=None, height=80, color=(0,0,0,1), background_color=(1,1,1,0.1))
            self.ids.sv.add_widget(btn)

    def on_command(self,btn):
        self.ids.label1.text = btn.text
        self.ids.carousel.load_next()

    def on_btn1(self):
        self.ids.carousel.load_previous()

    def on_btn2(self):
        self.ids.carousel.load_next()

class TestApp(App):
    def build(self):
        self.title = 'テスト'
        return MainScreen()

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

kvファイル(test.kv)

<MainScreen>:
    CustomLayout:
        orientation: "vertical"

        BoxLayout:
            orientation: "vertical"

            BoxLayout:
                Button:
                    size_hint_x: 0.2
                    text: "<"
                    on_release: root.on_btn1()
                Label:
                    id: label1
                    size_hint_x: 0.6
                    text: "today"
                    color: 0, 0, 0, 1
                Button:
                    size_hint_x: 0.2
                    text: ">"
                    on_release: root.on_btn2()

            Carousel:
                id: carousel
                size_hint_y: 10
                scroll_timeout: 0
                anim_move_duration: 0.1
                ScrollView:
                    GridLayout:
                        id: sv
                        cols: 2
                        size_hint_y: None
                        orientation: "vertical"
                        height: self.minimum_height
                BoxLayout:
                    Button:
                        text: "test"

            BoxLayout:
                Button:
                    text: "3"
                Button:
                    text: "4"
                Button:
                    text: "5"

<CustomLayout>:
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            pos: self.pos
            size: self.size

 

解説

「Carousel」の親ウェジットに「ScrollView」と「BoxLayout」の子ウェジットを作ります。これで2つのレイアウトをスライドで移動できるようになります。

scroll_timeout: 0

スライド可能な時間(ミリ秒)を「0」にすることでスライドでは移動できなくします。スライドしたい場合は省略するとデフォルトで「200ミリ秒」です。

anim_move_duration: 0.1

画面が切り替わるのが遅く感じたので「0.1秒」にしました。「0」にすると一瞬(アニメーションなし)で画面が変わります。省略するとデフォルトで「0.5秒」です。

self.ids.carousel.load_next()

次のスライドへ移動します。

self.ids.carousel.load_previous()

前のスライドへ移動します。

 

まとめ

いろいろ調べましたが「ScreenManager」や「clear_widgets、add_widget」を利用するやり方は一部レイアウトを切り替えるにはややこしく感じて正直あきらめました。
おそらく「Carousel」を利用するのが一番簡単な気がします。

なにが正解かはまだわかりませんが決められたパーツ(部品)を使って完成させるのはパズルのようで面白いです。

 

次回は選択したGIFファイルを再生させてみたいと思います。

 

 

保存ファイル

lesson79.py

test.kv

 

 

文責:Luke