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

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

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

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

Q&A

解決済

2回答

3655閲覧

python3,kivyで、シリアルから受信したデータをTabbedPanel上に表示させたい

sv13vsarcb

総合スコア10

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

0グッド

1クリップ

投稿2018/04/13 07:07

編集2018/04/18 07:21

2018/04/18 16:20 ソースコード更新しました

前提・実現したいこと

python3とkivyを使って、シリアルポートから受信したデータを解析したものをGUI上に表示・一定時間毎に更新させたいのですが、上手くいかず困っております。

発生している問題

シリアル受信~解析~コンソールに表示させるプログラムと、kivyを用いてGUIの枠を作成するプログラムを別々に作成することは出来たのですが、kivyのmainloopにシリアル受信~部分のプログラムを入れる方法が分からないといったような状況です。

以下のソースコードを実行すると取り合えずエラーは出ず、GUIの表示部分のみが実行され、GUIのウィンドウを閉じると解析部分が始まるといった動作です。

ご指導の程、何卒宜しくお願い致します。

該当のソースコード

上がpyファイル、下がkvファイルです。

python

1import serial 2import binascii 3import datetime 4import struct 5 6from kivy.app import App 7from kivy.uix.tabbedpanel import TabbedPanel 8from kivy.properties import StringProperty 9from kivy.core.text import LabelBase, DEFAULT_FONT 10from kivy.clock import Clock 11from kivy.event import EventDispatcher 12 13LabelBase.register(DEFAULT_FONT,"meiryo.ttc") 14 15class List(): 16 17 s = serial.Serial('COM5',9600) 18 19 list = [] 20 XB_list = [] 21 BT_list = [] 22 IO_list = [] 23 ML_list = [] 24 25 xbee = 0 26 btid = 0 27 reed = 0 28 ser = 0 29 time = 0 30 31 print("start") 32 33 def __init__(self): 34 pass 35 36 def receive_time(self,dt): 37 time = datetime.datetime.now() 38 self.time = (time.strftime('%Y年%m月%d日 %H:%M:%S')) 39 print(self.time) 40 41 def first_check(self): 42 self.list = [] 43 num = 0 44 print("check") 45 while num <= 2: 46 ser = self.s.read() 47 data = binascii.b2a_hex(ser) 48 dec = int(data,16) 49 self.list.append(dec) 50 num += 1 51 52 def length_read(self): 53 length = self.list[2] 54 55 if length == 35: 56 self.ser = self.s.read(length+1) 57 58 else: 59 print("read error") 60 pass 61 62 def sample(self): 63 xbee = self.ser[2:9] 64 btid = self.ser[18:30] 65 reed = self.ser[33:35] 66 67 self.xbee = str(binascii.hexlify(xbee), 'utf-8') 68 self.btid = btid.decode() 69 self.reed = reed.decode() 70 71 def add_list(self): 72 if((self.xbee in self.XB_list) == False): 73 self.XB_list.append(self.xbee) 74 75 else: 76 pass 77 78 if((self.btid in self.BT_list) == False): 79 self.BT_list.append(self.btid) 80 self.IO_list.append(self.reed) 81 self.ML_list.append(0) 82 83 elif((self.btid in self.BT_list) == True): 84 no = self.BT_list.index(self.btid) 85 self.IO_list[no] = self.reed 86 87class Mado(TabbedPanel): 88 print("window") 89 pass 90 91class TabbedPanelApp(App): 92 time = StringProperty() 93 94 def __init__(self, lst): 95 super().__init__() 96 self.lst = lst 97 98 def build(self): 99 self.title = 'test' 100 Clock.schedule_interval(lst.receive_time,5.0) 101 print("build") 102 return Mado() 103 104lst = List() 105tpa = TabbedPanelApp(lst) 106 107print("print") 108 109if __name__ =='__main__': 110 tpa.run() 111 112print("main2") 113while True: 114 lst.first_check() 115 lst.length_read() 116 lst.sample() 117 lst.add_list() 118 lst.receive_time() 119 print(lst.XB_list) 120 print(lst.BT_list) 121 print(lst.IO_list) 122 123

kviy

1# -*- coding: Shift-JIS -* 2#:kivy 1.10.0 3 4<PaddingBoxLayout@BoxLayout>: 5 padding: 10 6 7<Mado>: 8 size_hint: 1, 1 9 pos_hint: {'center_x': .5, 'center_y': .5} 10 do_default_tab: False 11 12 TabbedPanelItem: 13 text: 'XB_List' 14 Label: 15 text: 'XB ID 1' 16 17 TabbedPanelItem: 18 text: 'BT_List' 19 GridLayout: 20 cols: 2 21 rows: 2 22 Label: 23 text: 'BT ID 1' 24 Button: 25 text: 'BT ID 2' 26 27 TabbedPanelItem: 28 text: 'IO_List' 29 Label: 30 text: 'IO ' 31 32 TabbedPanelItem: 33 text: 'Time' 34 Label: 35 text: str(app.time) 36 37

また、StringPropertyを用いて5秒ごとに現在の時刻をTabbedPanel上に表示、更新させようとしていますが、参照している場所に問題があるのでしょう。これも上手くいきません。
頂いた回答により一部解決しました
AttributeError: 'Window' object has no attribute 'time'

補足情報

[Python] v3.6.3(32bit)
[kivy] v1.10.0

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

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

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

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

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

tachikoma

2018/04/13 08:55

Threadを使わないと難しいかなぁ。
guest

回答2

0

ベストアンサー

私の環境(Linux)では

text

1 Traceback (most recent call last): 2 File "略/site-packages/serial/serialposix.py", line 265, in open 3 self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) 4 FileNotFoundError: [Errno 2] No such file or directory: 'COM5'

と出て動かないので実際に確かめられないですが、とりあえずソースコードを読んで気付いた事を挙げると

  • Kvファイルの最後の行のtext: 'str(root.time)'が間違いで、timeというPropertyを持っているのはTabbedPanelAppクラスなのでtext: str(app.time)とすべきです。
  • Windowクラスの名前は変えた方がいいです。
  • Kvファイル中の<TabbedPanel>:<Windowクラスの新しい名前>:に変えるべきです。現状だとTabbedPanel全てを汚染しているので。
  • 使ってないmoduleのimport文を消した方がいいです。(from kivy.core.window import Windowimport time 他色々)

投稿2018/04/17 12:14

編集2018/04/17 12:15
gottadiveintopy

総合スコア736

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

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

sv13vsarcb

2018/04/18 05:48 編集

ご回答ありがとうございます。 シリアルポートに接続した通信モジュールが受信したデータを解析、表示させるために作成したプログラムですので、シリアルポート[COM5]に接続がないと動きません… 取り合えず最初の```s = serial.Serial('COM5',9600)```を削除して頂ければ、(```ser = self.s.read()```部分でエラーは出ますが)今回問題となっている動作(GUIの表示部分のみが実行され、GUIのウィンドウを閉じると解析部分が始まる)を確認することができます。 GUIウィンドウを表示させながらpyファイル最後のwhileの内容を行い、while内の処理で得た値をGUI上に表示させるのが目標なのですが、どのようにkivyのmain loop内にwhileの内容を入れたら良いのか、といった状況です。 kvファイルの最後の行の変更、Windowクラスの名前の変更、Kvファイル中の<TabbedPanel>の変更を行ったところ、```AttributeError: 'Window' object has no attribute 'time'```は出なくなりました。 ありがとうございます。 しかし、Label上には何も表示されません… ご指摘された「Propertyを持っているクラス」の事、「使ってないimport文の削除」は非常に納得できたのですが、「TabbedPanel全てを汚染」については私のpython,kivyの理解が浅い為、よく分かりませんでした。何故クラス名がWindowだと問題があるのでしょうか。 ご教示いただければ幸いです。
gottadiveintopy

2018/04/18 12:30

> どのようにkivyのmain loop内にwhileの内容を入れたら良いのか、といった状況です。 Clock.schedule_interval()の使い方を知っているのなら、whileの中身をそのまま使った関数を定義して、それをClock.schedule_interval()に渡すだけですよ。今回の場合はこの関数はTabbedPanelAppのMethodの方が良いと思うのでTabbedPanelAppに以下のようなMethodを用意してあげて def polling(self, dt): whileループの中身 それをbuild()内の「lst.receive_time」に代えてClock.chedule_interaval()に渡してあげればいいです。 > しかし、Label上には何も表示されません… コード内にどこにもTabbedPanelAppのtimeプロパティに書き込む処理が無いので当然です。上のpolling()内で self.time = xxxxxxx と書き込んであげるのが良いと思います。 > 「TabbedPanel全てを汚染」については <TabbedPanel>: TabbedPanelItem: と書いてしまうと今後作られる全てのTabbedPanelが始めからTabbedPanelItemを一つ持った状態になります。例えばですがBoxLayoutが最初からButtonが一つ入った状態になってたとしたらどう思いますか?そんな汎用性の無い部品はおかしいですよね。なのでKivy標準のWidgetをいじるのではなくて、自分で用意したクラス(今回の場合はMadoクラス)をいじるべきなんです。そうすればKivy標準のWidgetには一切影響を与えないで済みます。 > 何故クラス名がWindowだと問題があるのでしょうか。 これはWindowが絶対駄目というわけではないですが、Kivyが元から持っているWindowクラスと混同してしまうのでやめて欲しいです。(今回のようにコードを人に見せる場合は特に)。Windowに限らずですが基本KivyのClass名と被らないようにした方がBugが起こりにくく読みやすいので。とりあえず以下のコードで出てくるクラス名と同じ名前のクラスは絶対に作らないようにしたほうがいいです。 from kivy.factory import Factory print(sorted(list(Factory.classes.keys()))) こういった場所で質問する時なんですが、プロジェクトのコードをそのまま持ってくるのではなくて問題を再現するできるだけ最小限のコードを別に作って載せて欲しいです。今回の場合実はserial通信は全く関係ないので外せますし、日本語Font「meiryo.ttc」もどの環境にでもあるFontではないので使うのをやめて、「年月日」の代わりに「ymd」を使えば済むので。
sv13vsarcb

2018/04/19 05:44

知識、質問方法等至らない点も多かった中、回答、ご指摘頂きまして感謝しております。 おかげ様で無事目標としていた動作の実現のみならず、動作や記述方法等についても理解が深まりました。 大変丁寧な解説、本当にありがとうございました。
guest

0

kivyを使ったことがないので完全な当てずっぽですが、コンストラクタの部分を使ってlstをAppのインスタンスに渡してあげればいいんじゃないかなぁ。

python

1class TabbedPanelApp(App): 2 def __init__(self, lst): 3 self.lst = lst 4 5 def build(self): 6 self.title = 'test' 7 Clock.schedule_interval(self.lst.receive_time, 5.0) 8 print("build") 9 return Window() 10 11lst = List() 12tpa = TabbedPanelApp(lst)

投稿2018/04/13 09:08

tachikoma

総合スコア3601

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

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

sv13vsarcb

2018/04/16 00:58

早速のご回答ありがとうございました。 なるほど確かにと思い試してみたものの、エラーが出てしまいました。 line 110, in <module> TabbedPanelApp().run() TypeError: __init__() missing 1 required positional argument: 'lst' この場合、どのようにしたら良いでしょうか。
tachikoma

2018/04/16 01:26

TabbedPanelApp().run()の部分をtpa.run()にしてみたらどうかな。コンストラクタが2回呼ばれてるので。
sv13vsarcb

2018/04/16 03:40

TabbedPanelApp().run()の部分をtpa.run()に変更してみたのですが、また別のエラーが起こってしまいました。 Programs\Python\Python36-32\lib\site-packages\kivy\app.py", line 799, in run if not self.built: AttributeError: 'TabbedPanelApp' object has no attribute 'built' 以下のリンクを参考にもう少し頑張ってみますが、ご意見頂ければ幸いです。 https://stackoverflow.com/questions/36758038/kivy-python-countdown-app-project-kivy-has-no-attribute-built-error
gottadiveintopy

2018/04/17 11:37

__init__()を上書きしたのなら、その中で親の__init__()を呼ぶ必要がありますよ
sv13vsarcb

2018/04/18 07:25

こちらにもご回答ありがとうございます。 おかげさまでAttributeError: 'TabbedPanelApp' object has no attribute 'built'エラーは出なくなりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問