質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

2回答

2888閲覧

【Kivy】ScreenManagerでGridLayoutを使用したい

shirumono

総合スコア0

Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/09/21 00:35

前提・実現したいこと

Kivyでアプリ制作をしていて、画面の1つにカレンダーを表示させようとしています。ScreenManagerによる画面遷移はできました。GridLayoutを使ってカレンダーを表示させることもできました。しかし、これら2つを組み合わせて、「画面遷移先にカレンダーを表示させる」ことができません。

以下のScreen_TwoとScreen_Two_Layoutが該当部分です(不必要なコードは省いています)。メイン画面でボタンを押すとスクリーン1からスクリーン2に画面を切り替えられるという設計です。kvファイルの該当部分には特に何も書いていないません。

該当のソースコード

Python3

1from kivy.app import App 2from kivy.uix.screenmanager import ScreenManager, Screen 3from kivy.uix.boxlayout import BoxLayout 4from kivy.uix.button import Button 5from kivy.uix.gridlayout import GridLayout 6 7class Display(BoxLayout): 8 pass 9 10class Screen_One(Screen): 11 pass 12 13class Screen_Two(GridLayout): 14 def __init__(self, **kwargs): 15 super(Screen_Two, self).__init__(**kwargs) 16 self.cols = 7 17 # 日付を取得する 18 import calendar 19 cal = calendar.Calendar() 20 import datetime 21 dt_now = datetime.datetime.now() 22 year, month = dt_now.year, dt_now.month 23 day = cal.monthdayscalendar(year, month) 24 25 #カレンダーに数字を入れる 26 for i in range(42): 27 c = i%7 28 r = int(i/7) 29 try: 30 if day[r][c] != 0: 31 btn = Button(text=str(day[r][c])) 32 self.add_widget(btn) 33 else: 34 btn = Button(text='') 35 self.add_widget(btn) 36 except: 37 break 38 39class SM02App(App): 40 def build(self): 41 return Display() 42 43if __name__ == '__main__': 44 SM02App().run()

kv

1#: import RiseInTransition kivy.uix.screenmanager.RiseInTransition 2#: import SlideTransition kivy.uix.screenmanager.SlideTransition 3 4<Display>: 5 BoxLayout: 6 orientation: "vertical" 7 BoxLayout: 8 size_hint: 1, None 9 height: '60dp' 10 Label: 11 id: label1 12 text: 'Home' 13 font_size: 30 14 Label: 15 id: label2 16 text: 'aaa' 17 18 ScreenManager: 19 id: sm 20 Screen_One: 21 Screen_Two: 22 23 BoxLayout: 24 size_hint: 1, None 25 height: '48dp' 26 Button: 27 text: 'Go to Screen1' 28 on_release: 29 sm.transition = RiseInTransition() 30 sm.current = 'screen_one' 31 Button: 32 text: 'Go to Screen2' 33 on_release: 34 sm.transition = RiseInTransition() 35 sm.current = 'screen_two' 36 37<Screen_One>: 38 name: 'screen_one' 39 Button: 40 background_color: 1,0,0,1 41 text: 'Screen1' 42 43<Screen_Two>: 44 name: 'screen_two' 45

以下がエラーメッセージです。ScreenManagerではGridLayoutを受け入れてくれないらしいというところまでは分かりました。

発生している問題・エラーメッセージ

kivy.uix.screenmanager.ScreenManagerException: ScreenManager accepts only Screen widget.

試したこと

Kvファイル上でGridLayoutを作成したり、Screen_Twoのクラスの外側でレイアウトを作ってそれを読み込むような形にしたりすればいいのかなと思いましたが、調べてもやり方が見つけられませんでした。
self.layoutでGridLayoutを指定しましたが、うまくいかず、最後に追加したボタン1つだけが表示されます。

基本的な内容ですがよろしくお願いします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Kivyに関する部分はultharさんが指摘してくれているのでそれ以外で気付いた事を挙げると

1.余りを除いた商を得たい時は//演算子が、商と余りを両方得たい時はdivmod()関数が使えます。

python

1>>> 30 // 7 24 3>>> 30 % 7 42 5>>> divmod(30, 7) 6(4, 2)
2.全ての例外をもみ消すコードを書いてはいけないです

コード内には

python

1try: 2 ... 3except: 4 break

がありますが、このように全ての例外をもみ消すコードは絶対に書いてはだめです。必ず特定の例外だけを捕まえるようにしてください。今回の場合おそらく起きているのはIndexErrorだと思うので捕まえるとするなら

python

1try: 2 .... 3except IndexError: 4 break

となります。ただ以下のようにすればそもそも例外を起こさずに済むのでより良いです。

python

1 def on_kv_post(self, base_widget): 2 #カレンダーに数字を入れる 3 import itertools 4 add_widget = self.maincal.add_widget 5 for d in itertools.chain.from_iterable(self.day): 6 add_widget(Button(text=str(d) if d else ''))

投稿2021/09/21 14:04

gottadiveintopy

総合スコア736

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ScreenManagerはScreenしか扱えないのでやはりScreen_TwoはScreenにするべきでしょう。
それを踏まえてコードを修正すると

python

1from kivy.app import App 2from kivy.uix.screenmanager import ScreenManager, Screen 3from kivy.uix.boxlayout import BoxLayout 4from kivy.uix.button import Button 5from kivy.uix.gridlayout import GridLayout 6from kivy.properties import ObjectProperty 7 8class Display(BoxLayout): 9 pass 10 11class Screen_One(Screen): 12 pass 13 14class Screen_Two(Screen): 15 maincal=ObjectProperty() 16 def __init__(self, **kwargs): 17 super(Screen_Two, self).__init__(**kwargs) 18 # 日付を取得する 19 import calendar 20 cal = calendar.Calendar() 21 import datetime 22 dt_now = datetime.datetime.now() 23 year, month = dt_now.year, dt_now.month 24 self.day = cal.monthdayscalendar(year, month) 25 def on_kv_post(self, base_widget): 26 #カレンダーに数字を入れる 27 for i in range(42): 28 c = i%7 29 r = int(i/7) 30 try: 31 if self.day[r][c] != 0: 32 btn = Button(text=str(self.day[r][c])) 33 self.maincal.add_widget(btn) 34 else: 35 btn = Button(text='') 36 self.maincal.add_widget(btn) 37 except: 38 break 39 40class SM02App(App): 41 def build(self): 42 return Display() 43 44if __name__ == '__main__': 45 SM02App().run()

kv

1#: import RiseInTransition kivy.uix.screenmanager.RiseInTransition 2#: import SlideTransition kivy.uix.screenmanager.SlideTransition 3 4<Display>: 5 BoxLayout: 6 orientation: "vertical" 7 BoxLayout: 8 size_hint: 1, None 9 height: '60dp' 10 Label: 11 id: label1 12 text: 'Home' 13 font_size: 30 14 Label: 15 id: label2 16 text: 'aaa' 17 18 ScreenManager: 19 id: sm 20 Screen_One: 21 Screen_Two: 22 23 BoxLayout: 24 size_hint: 1, None 25 height: '48dp' 26 Button: 27 text: 'Go to Screen1' 28 on_release: 29 sm.transition = RiseInTransition() 30 sm.current = 'screen_one' 31 Button: 32 text: 'Go to Screen2' 33 on_release: 34 sm.transition = RiseInTransition() 35 sm.current = 'screen_two' 36 37<Screen_One>: 38 name: 'screen_one' 39 Button: 40 background_color: 1,0,0,1 41 text: 'Screen1' 42 43<Screen_Two>: 44 maincal:maincal 45 name: 'screen_two' 46 GridLayout: 47 id: maincal 48 cols: 7

で思惑通りに動くのではないでしょうか。

変更点は
・Screen_TwoをScreenにする
・Screenの子にGridLayoutを追加しidを指定する
・GridLayoutへButtonを追加する部分をon_kv_post以下に移動する
(参考:KivyのRecycleViewをアプリ起動時に表示したい)

投稿2021/09/21 03:09

ulthar

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問