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

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

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

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Tkinter

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

Python

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

Q&A

解決済

1回答

4115閲覧

tkinterのCanvas配置内容の保存方法

tile

総合スコア19

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Tkinter

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

Python

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

0グッド

1クリップ

投稿2021/03/11 07:36

大変お世話になっております。
お忙しいところ恐縮ではございますが
Tkinterについてご指導のほど何卒どうぞよろしくお願い致します。

例えば以下のようなコードを制作したとします。

python

1import tkinter 2 3class CanvasOval: 4 canvas = None 5 6 def __init__(self, x0, y0, x1, y1, **key): 7 self.id = self.canvas.create_oval(x0, y0, x1, y1, **key) 8 self.canvas.tag_bind(self.id, '<1>', self.drag_start) 9 self.canvas.tag_bind(self.id, '<Button1-Motion>', self.dragging) 10 11 def drag_start(self, event): 12 self.x = event.x 13 self.y = event.y 14 15 def dragging(self, event): 16 self.canvas.move(self.id, event.x-self.x ,event.y-self.y) 17 self.x = event.x 18 self.y = event.y 19 20class Frame(tkinter.Frame): 21 22 def __init__(self, master=None): 23 tkinter.Frame.__init__(self, master) 24 self.cvs = tkinter.Canvas(self,width="200", height="200", bg="white") 25 self.cvs.grid(row=0, column=0) 26 27 CanvasOval.canvas=self.cvs 28 CanvasOval(40, 40, 50, 50, fill="red", width=0) 29 CanvasOval(130, 130, 170, 170, fill="red", width=0) 30 31if __name__ == '__main__': 32 f = Frame() 33 f.pack() 34 f.mainloop()

こちらは図形をドラッグにより移動することができる内容となります。

作りたいアプリとしては

図形を配置することができ、その配置状態を保存できるものを
制作したいと考えております。
保存したファイルをクリックすると、配置された図形が表示されると
いったイメージをもっております。

配置された図形の状態をファイルに保存するためのアイディアを、
ご指導いただければと思い投稿致しました。

お忙しい中恐縮ではありますが
何卒どうぞよろしくお願い致します。

現状としては

sqlite3を利用し、配置する「CanvasOval」の状態を記録、
及び、ドラックして移動した座標を取得して記録、
といった方法になるのではないか?と仮説しておりますが
他にも方法がありましたらご教授のほど何卒どうぞよろしくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

tkinter の canvas は、postscript 出力しか対応してません。
キャンバス内アイテムの復元方法は無いため、独自に実装することになります。

余談: ライブラリ内部のTcl/Tk側のアップデートで、
次期バージョンのSVG 実装が使えれば、改善されるかもしれませんが、先の話です。

辞書形式でデータ構造を考えて、
JSON 等で保存したほうが扱いやすいと思います。

「キャンバス内アイテム」の保存・読み込みには

  • 必要な情報の列挙

 形式、座標、色、等の状態を記録。

  • 情報所得に必要な canvas のメソッドを調べる

 type(item), coords(item), itemcget(item), 等

  • item ID の列挙 canvas.find_all()
  • 保存: 辞書でデータを出力、
  • 読込: 辞書データを読込、キャンバス内容を復元

という流れになります。


01: キャンバス内アイテムの SAVE/LOAD
サンプルコード (形式は oval、座標と fill(色) のみ対応)

python

1 2# 前半部分は質問のコード通り省略 3 4if __name__ == '__main__': 5 f = Frame() 6 f.pack() 7 8 import json 9 canvas = f.cvs 10 filepath = "sanvas.json" 11 12 def save(): 13 print("SAVE") 14 data = [] 15 for itemID in canvas.find_all(): 16 # TODO: type に応じて、保存する内容は異なる。 17 data.append({ 18 "type": canvas.type(itemID), 19 "coords": canvas.coords(itemID), 20 "config": { 21 "fill": canvas.itemcget(itemID, "fill"), 22 } 23 }) 24 with open(filepath, "w", encoding="utf-8") as stream: 25 json.dump(data, stream) 26 27 28 def load(): 29 print("LOAD") 30 with open(filepath, encoding="utf-8") as stream: 31 data = json.load(stream) 32 33 # イベントの解除 (※ leak を避ける為必須) 34 for itemID in canvas.find_all(): 35 canvas.tag_unbind(itemID, '<1>') 36 canvas.tag_unbind(itemID, '<Button1-Motion>') 37 38 # キャンバス内のアイテムを全て削除 39 canvas.delete("all") 40 41 for item in data: 42 # TODO: type の種類に応じて異なる 43 if item["type"] == "oval": 44 # itemID = canvas.create_oval(*item["coords"]) 45 # canvas.itemconfig(itemID, **item["config"]) 46 47 CanvasOval(*item["coords"], **item["config"]) 48 49 tkinter.Button(f, text="save", command=save).grid() 50 tkinter.Button(f, text="load", command=load).grid() 51 52 f.mainloop()

JSONファイルに保存されるデータ内容のサンプル

json

1[{"type": "oval", 2 "coords": [40.0, 40.0, 50.0, 50.0], 3 "config": {"fill": "red"}}, 4 {"type": "oval", 5 "coords": [122.0, 40.0, 162.0, 80.0], 6 "config": {"fill": "red"}}]

他の方法:
質問のコードでは Oval を Python のオブジェクトとして扱っているので、
「Pythonオブジェクトの保存・復元」となるとオブジェクトの直列化 pickle という仕組みも使えます。
独自に実装しなければならないことには変わらないので、
簡単な方法というわけでは有りません。難易度は、少し高め。

投稿2021/03/12 04:10

teamikl

総合スコア8664

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

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

tile

2021/03/22 12:01

ご連絡が遅れてしまい大変申し訳ありません。 この度はアドバイスをいただきありがとうございます。 次期バージョンがあることも存じておりませんでしたので 多様な選択肢があり助かりました。 この度は大切なお時間をくださり 感謝申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問