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

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

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

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Python

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

Q&A

解決済

1回答

2993閲覧

Rosからのメッセージ表示GUIを作成でのエラー解決

kanaha

総合スコア7

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

Python

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

0グッド

0クリップ

投稿2020/10/02 06:43

RosのTopic通信を利用してロボットの動作状況を表示するGUIを作成しています。
(写真がGUIのイメージです。) 
Subscriber側で受け取ったメッセージによって表示文字と背景色を変えるという形で作っています。
現在は通信部分はRosの参考書・表示の仕組みはいろいろなWebサイトを参考に作ってはいますが、以下のエラーが出ていてこのエラーを解決できていません。助けていただけないでしょうか。お願いいたします。

参考書
「ROSではじめる ロボットプログラミング」著者 小倉崇

主な参考サイト
時刻部分   
https://qiita.com/The-town/items/be391ff799f95dab8b96

状況表示部分
https://www.geeksforgeeks.org/python-tkinter-text-widget/

使用言語
Python

使用OS
Ubuntu16.04

イメージ

GUIイメージ

エラー文

CTraceback (most recent call last): File "/home/tomatoko/catkin_ws/src/ros_start/scripts/listener.py", line 98, in <module> tk.mainloop() File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 417, in mainloop _default_root.tk.mainloop(n) AttributeError: 'NoneType' object has no attribute 'tk' Exception in thread Thread-7: Traceback (most recent call last): File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner self.run() File "/usr/lib/python2.7/threading.py", line 754, in run self.__target(*self.__args, **self.__kwargs) File "/home/tomatoko/catkin_ws/src/ros_start/scripts/listener.py", line 38, in changeLabelText self.label1["text"] = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1336, in __setitem__ self.configure({key: value}) File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1329, in configure return self._configure('configure', cnf, kw) File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1320, in _configure self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) RuntimeError: main thread is not in main loop

Publisher側

#!/usr/bin/env python # -*- coding:utf-8 -*- import rospy from std_msgs.msg import String rospy.init_node('talker') pub = rospy.Publisher('chatter',String, queue_size=10) rate = rospy.Rate(10) while not rospy.is_shutdown(): hello_str = String() hello_str.data = "b" pub.publish(hello_str) rate.sleep()

Subscriber側

#!/usr/bin/env python # -*- coding:utf-8 -*- import rospy from std_msgs.msg import String import Tkinter as tk import datetime import time import threading status = "今は" color = "#ff69b4" class Start: def __init__(self): self.root = tk.Tk() self.root.attributes("-zoomed", "1") self.label = tk.Label(self.root) self.label1 = tk.Label(self.root) self.label["font"] = ("Helvetica", 170) self.label1["font"] = ("Helvetica", 78) self.label["bg"] = color self.label1["bg"] = "white" self.label["fg"] = "black" self.label1["fg"] = "black" self.label ["text"] = status self.label.place(x=0,y=20,width=1000,height=430) self.label1.place(x=0, y=450) def changeLabelText(self): while True: self.label1["text"] = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") time.sleep(1) def calc(Rosmsg): if(Rosmsg == "a"): status = "停 止 中" color = "#87cefa" #lightskyblue elif(Rosmsg == "b"): status = "移 動 中" color = "#ffd700" #orange elif(Rosmsg == "c"): status = "認 識 中" color = "#9932cc" #darkchid elif(Rosmsg == "d"): status = "収 穫 中" color = "#9acd32" #yellowgreen elif(Rosmsg == "e"): status = "収 納 中" color = "#ff69b4" #hotpink else: status = "Error!!" color = "#dc143c" #crimson #label["text"] = status # ラベル内テキスト変更 #label["bg"] = color # ラベル背景色変更 def callback(message): Rosmsg= str(message.data) calc(Rosmsg) rospy.init_node('listener') sub = rospy.Subscriber('chatter', String, callback) rospy.spin() if __name__ == "__main__": start = Start() start.root.title(u"status") thread = threading.Thread(target=start.changeLabelText) thread.start() start.root.mainloop() tk.mainloop()

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

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

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

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

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

teamikl

2020/10/03 01:45

rospy.spin() で待機状態になるので、それ以降のコードは実行されず tkinter のGUIは表示されないと思うのですが、GUIは正常に表示されますか? エラーはプログラムを終了しようとしたときに表示されるものではないでしょうか?
kanaha

2020/10/06 04:46

プログラムを終了したあとにGUIが表示されていまして
guest

回答1

0

ベストアンサー

AttributeError: 'NoneType' object has no attribute 'tk'

末尾の tk.mainloop() は、存在しないので不要です。

RuntimeError: main thread is not in main loop

原因: Tkinter が終了した後も、スレッドが残っていて
ラベルのテキストを更新しようとしています。
解決策: スレッドではなく Tkinter のタイマー (afterメソッド) を使い、時刻の更新を実装してください。


他の問題点:

tkinterのmainloop() と rospy.spin() はどちらも待機ループを持つため、
同一スレッド上で実行できません。

rospy.spin() は、rospyの終了を待つだけのループなので、
tkinterのmainloopを使う場合は不要です。


他の問題点2:

python

1 #label["text"] = status # ラベル内テキスト変更 2 #label["bg"] = color # ラベル背景色変更

変数のスコープでlabel は参照できないのもありますが、
他にスレッド絡みの問題があります

callbackはrospyのスレッドから呼ばれると思うのですが、
スレッドを跨いだ操作は問題の原因になりやすいので、
キューを使ってスレッド間通信をする等の対策が必要です。
(同時アクセスや、上で指摘したようなGUIが終了した後に発生するアクセス)

root.protocol('WM_DELETE_WINDOW', on_close_callback)

で、ウィンドウが閉じる前のイベント・ハンドラを設定できるので、
Tkinter が終了する前に、GUIにアクセスのあるスレッドを終了
(もしくはSubscriperを解除)してください。

投稿2020/10/03 02:09

teamikl

総合スコア8760

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

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

kanaha

2020/10/06 04:47

現在 Timer部分をこのように直しているのですがあっているのでしょうか def update_clock(self): now = datetime.dateime.now() self.label1["text"] = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") self.root.after(1000,self.update_clock)
kanaha

2020/10/06 04:57

上の書き方を間違っていました気にしないでください。すみません。 Timerの書き換えとrospy.spin()の削除で終了後のエラーをなくすことができました。ありがとうございました。 あとはメッセージを受け取って変更できるようにがんばります。 こんな問題にアドバイスをいただき本当にありがとうございました。
teamikl

2020/10/07 03:43

スコープ問題について、簡単な解決法は calc() を Start クラスのメソッドとして実装して、 ラベルにはインスタンス変数 (self.label) でアクセスする方法です。 必然的にcallback登録は、GUI 生成後にする事になります。 ---- 終了時にエラーが出る場合は、大抵 スレッドの生存期間の問題で、GUI(tkinter) は終了してるのに スレッドからはラベルの変更などGUIを「直接操作」しようとしている、 といった状況です。 今回の対策としては、「Tkinter終了前に subscriptの解除」を提案しますが、 より汎用的に対応するには、Queue を用いたスレッド間通信を調べて見て下さい。
kanaha

2020/10/21 02:32

返答が遅くなってしまいすみません class start を start = Start() にして def calc で start.label["text"] = で呼び出すことで 無事動かすことができました。 大変お世話になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問