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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Python 3.x

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

Tkinter

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

Python

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

Q&A

解決済

2回答

9784閲覧

Python tkinterでSpinboxで入力した値を得て計算し、表示させるにはどうしたら良いでしょうか。

flower

総合スコア29

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Python 3.x

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

Tkinter

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

Python

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

1グッド

4クリップ

投稿2017/07/02 02:05

編集2017/07/04 02:47

###前提・実現したいこと
PyhonでTkinterを用いてGUIアプリケーションを作成しています。
文房具の請求のプログラムなのですが、イメージはamazonなどの
通販サイトみたいな感じです。

いま、tkinterのSpinboxという機能を使って、商品の個数を選べるようにし、
その上下(▲▼)ボタン(またはキー入力)を押して個数を決めたときに、それと
連動してウィンドウの右側に、数値(値段と個数をかけたもの)を表示させたいのですが、
get()を使っても初期値の0が表示されるだけで、スピンボックスの中の値を
変化させても右側に表示される値は変わりませんでした。どうすればよいですか?

また、pythonでのクラスの作り方がよくわかっていなくて、クラスなしで
関数を作って実装しているのですが、クラスは作ったほうがいいのでしょうか?

###試したこと

Python

1 2from tkinter import * 3import sys 4 5# Base window 6window = Tk() 7 8wc = Canvas(window, width = 2000, height = 2000) 9wc.create_rectangle(0,0,2000,2000, fill = "paleturquoise") 10 11wc.place(x = 0, y = 0) 12 13# Setting the title 14window.title("文房具の請求") 15 16# Coloring canvas 17 18for x in range(10): 19 c = Canvas(window, width = 240, height = 150) 20 c.create_rectangle(0,0,240,150, fill = "aliceblue") 21 if x<= 4: 22 c.place(x = 30, y = 30 + x * 155) 23 else: 24 c.place(x = 300, y = 30 + (x - 5) * 155) 25 26 27# Set items & spinbox 28 29item = ["*","*","*","*","*","*","*","*","*","*"] 30for x in range(10): 31 i = Label(text = item[x], bg = "#82EBF7") 32 ko = Label(text = "個", bg = "aliceblue") 33 if x <= 4: 34 i.place(x = 30, y = 30 + x * 155) 35 ko.place(x = 115, y = 150 + x * 155) 36 else: 37 i.place(x = 300, y = 30 + (x - 5) * 155) 38 ko.place(x = 385, y = 150 + (x - 5) * 155) 39 40''' 41ついでに、以下のコードをfor文とかで簡単に書く方法ってありますか? 4210個の商品のひとつずつにspinboxで値を決められるようにしています。 43''' 44 45s1value = StringVar() 46s2value = StringVar() 47s3value = StringVar() 48s4value = StringVar() 49s5value = StringVar() 50s6value = StringVar() 51s7value = StringVar() 52s8value = StringVar() 53s9value = StringVar() 54s10value = StringVar() 55 56s1 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s1value) 57s2 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s2value) 58s3 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s3value) 59s4 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s4value) 60s5 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s5value) 61s6 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s6value) 62s7 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s7value) 63s8 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s8value) 64s9 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s9value) 65s10 = Spinbox(window, from_=0, to=100, width = 10, textvariable=s10value) 66 67s1.pack 68s2.pack 69s3.pack 70s4.pack 71s5.pack 72s6.pack 73s7.pack 74s8.pack 75s9.pack 76s10.pack 77 78def spin(w,x): 79 if x <= 4: 80 w.place(x = 40, y = 150 + x * 155) 81 else: 82 w.place(x = 310, y = 150 + (x - 5) * 155) 83 84spin(s1,0) 85spin(s2,1) 86spin(s3,2) 87spin(s4,3) 88spin(s5,4) 89spin(s6,5) 90spin(s7,6) 91spin(s8,7) 92spin(s9,8) 93spin(s10,9) 94 95# Set price 96 97price = ["1 円","2 円","3 円","4 円","5 円","6 円","7 円","8 円","9 円","10 円"] 98 99for x in range(10): 100 t = Label(text = price[x], bg = "aliceblue") 101 if x <= 4: 102 t.place(x = 30, y = 70 + x * 155) 103 else: 104 t.place(x = 300, y = 70 + (x - 5) * 155) 105 106# name 107 108name = ["商品名1","商品名2","商品名3","商品名4","商品名5","商品名6","商品名7","商品名8","商品名9","商品名10"] 109 110for x in range(10): 111 n = Label(text = name[x], bg = "aliceblue") 112 if x <= 4: 113 n.place(x = 30, y = 50 + x * 155) 114 else: 115 n.place(x = 300, y = 50 + (x - 5) * 155) 116 117# Set window 118 119window.geometry("1000x825+100+20") 120 121# Set subwindow 122 123''' 124以下のsubwindow(sb)が、上記でいうウィンドウの右側のことです。 125''' 126 127sb = Canvas(window, width = 400, height = 700) 128sb.create_rectangle(0,0,400,700, fill = "white") 129sb.place(x = 570, y = 50) 130 131text = Label(window, text="カート", bg = "#69D7E3" ) 132text.place(x=570, y=50) 133 134# Get price 135 136''' 137もし、▲が押されたら、get()した値(現在値:0)に1を足し、 138▼が押されたら、1を引く、といったことを書こうとしたのですが、 139buttonupとは何ですか?といったエラーがでてしまいます。 140 141ちなみにs1は商品1のことであり、r1は商品1の個数に商品1の値段を 142かけたものです。(値段設定は今は適当なため、1円ということにしています。) 143''' 144 145if s1.invoke == buttonup: 146 s1.get = s1.get + 1 147elif s1.invoke == buttondown: 148 s1.get = s1.get - 1 149 150r1 = int(s1.get()) * 1 151 152note = Label(window, text = r1, bg = "white" ) 153note.place(x=590, y=80) 154 155window.mainloop() 156
Traceback (most recent call last): File "C:/Users/admin/Desktop/HCI/memo12.py", line 123, in <module> if s1.invoke == buttonup: NameError: name 'buttonup' is not defined

###補足情報(言語/FW/ツール等のバージョンなど)
使用ツール:Python3.5.1

MM921👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

簡単に修正してみました。
やりたい事はこんな感じでしょうか。

Python

1from tkinter import * 2import sys 3 4 5# spinboxの値が更新された時に呼ばれる関数 6# Spinbox生成時にこの関数をcommand引数で渡しています。 7# idxには更新されたSpinboxのIndex値が入ります 8def update_value(idx): 9 print("Update spinbox {}".format(idx)) 10 num_of_purchase = [int(s.get()) for s in spinboxes] 11 sub_total = [n*p for n,p in zip(num_of_purchase, price)] 12 total = sum(sub_total) 13 14 # 表示するデータを作成する(適当に書きました) 15 txt = ["{:5d} x {:2d} = {:5d}".format(p,n,t) for p,n,t in zip(price,num_of_purchase,sub_total)] 16 txt.append("-----------------------------") 17 txt.append("TOTAL : {}".format(total)) 18 19 # noteを更新する 20 note.config(text='\n'.join(txt)) 21 22 23 24# Base window 25window = Tk() 26 27wc = Canvas(window, width = 2000, height = 2000) 28wc.create_rectangle(0,0,2000,2000, fill = "paleturquoise") 29wc.place(x = 0, y = 0) 30 31# Setting the title 32window.title("文房具の請求") 33 34# Coloring canvas 35for x in range(10): 36 c = Canvas(window, width = 240, height = 150) 37 c.create_rectangle(0,0,240,150, fill = "aliceblue") 38 c.place(x = 30 + int(x/5) * 270, y = 30 + (x%5) * 155) 39 40# Set Lavels 41item = ["ノート","鉛筆","シャープペン","消しゴム","色鉛筆","ボールペン","油性ペン","蛍光ペン","はさみ","のり"] 42for x in range(10): 43 i = Label(text = item[x], bg = "#82EBF7") 44 ko = Label(text = "個", bg = "aliceblue") 45 i.place(x = 30 + int(x/5) * 270, y = 30 + (x%5) * 155) 46 ko.place(x = 115 + int(x/5) * 270, y = 150 + (x%5) * 155) 47 48# Set Spinboxes 49spinboxes = [] 50for x in range(10): 51 value = StringVar() 52 s = Spinbox(window, from_=0, to=100, width = 10, textvariable=value, command=lambda idx=x:update_value(idx)) 53 s.place(x = 40 + int(x/5) * 270, y = 150 + (x%5) * 155) 54 spinboxes.append(s) 55 56# Set price 57price = [100,20,150,50,40,120,180,200,350,240] 58for x in range(10): 59 t = Label(text = "{} 円".format(price[x]), bg = "aliceblue") 60 t.place(x = 30 + int(x/5) * 270, y = 70 + (x%5) * 155) 61 62# Set name 63name = ["商品名1","商品名2","商品名3","商品名4","商品名5","商品名6","商品名7","商品名8","商品名9","商品名10"] 64for x in range(10): 65 n = Label(text = name[x], bg = "aliceblue") 66 n.place(x = 30 + int(x/5) * 270, y = 50 + (x%5) * 155) 67 68# Set window 69window.geometry("1000x825+100+20") 70 71# Set subwindow 72sb = Canvas(window, width = 400, height = 700) 73sb.create_rectangle(0,0,400,700, fill = "white") 74sb.place(x = 570, y = 50) 75 76text = Label(window, text="カート", bg = "#69D7E3" ) 77text.place(x=570, y=50) 78 79note = Label(window, text = "", bg = "white" ) 80note.place(x=590, y=80) 81 82window.mainloop()

大きな変更点をザッと説明すると

1.
Spinbox 生成時に10回を同じ処理の繰り返すで記述しておりましたので、spinboxes=[] というリストを作成して、各Splinboxをこの中に格納するように修正しました。

2.
Spinbox 生成時に command引数に関数を渡すことで、

Python

1def update_value(): 2 # Spinboxが更新されたときに呼ばれる関数 3 # 更新時の処理をここに書く 4 5Spinbox(..., command=update_value)

のように記述できます。

pashango2さんのおっしゃるとおり、一般的にGUIアプリはイベントドリブンで動作するので、このように何かしらのイベントが発生した際に呼ばれる イベントハンドラ(コールバック関数) に対応する処理を記述する必要があります。

今回は更に

Python

1def update_value(idx): 2 # Spinboxが更新されたときに呼ばれる関数 3 # idx にどのSpinboxが更新されたのかが格納される 4 new_value = int(spinboxes[idx].get()) 5 #... 6 7Spinbox(..., command=lambda idx=x: update_value(idx))

のようにlambda にデフォルト引数を設定したもの(idx=x)を挟むことにより、どのSpinboxから更新がかかったのかを判別できるようにしております。

3.
上記 2. で追加したupdate_value()関数内にて、noteをに記述する内容を作成し、note更新する部分を記述しております。

4.
priceリストのデータは文字列型で格納されておりましたが、合計などの計算には不適なので、数値型に変更しました。
単位 '円'はLabelを描写するタイミングで付加しております。

5.
コードの至る所にあった判定文を数式化して削除しました。
(このあたりは好みがあるかと思いますが)

あと、

  • 複数あるループをまとめる
  • データ定義の部分とGUIを生成している部分を分離する
  • 5. での修正部が複数存在するので、共通部をまとめて関数化する

などを行おうかと思いましたが、元のコードから構成が大きく変更してしまうので、今回は行っておりません。
これらを行うと、もう少しスッキリと書けると思います。


【補足】
クリアボタン追加してみました

Python

1from tkinter import * 2import sys 3 4# spinboxの値が更新された時に呼ばれる関数 5# Spinbox生成時にこの関数をcommand引数で渡しています。 6# idxには更新されたSpinboxのIndex値が入ります 7def update_value(idx): 8 print("Update spinbox {}".format(idx)) 9 num_of_purchase = [int(s.get()) for s in spinboxes] 10 sub_total = [n*p for n,p in zip(num_of_purchase, price)] 11 total = sum(sub_total) 12 13 # 表示するデータを作成する(適当に書きました) 14 txt = ["{:5d} x {:2d} = {:5d}".format(p,n,t) for p,n,t in zip(price,num_of_purchase,sub_total)] 15 txt.append("-----------------------------") 16 txt.append("TOTAL : {}".format(total)) 17 18 # noteを更新する 19 note.config(text='\n'.join(txt)) 20 21# 全てをクリアする 22def clear_all(): 23 for val in spinbox_values: 24 val.set(0) 25 note.config(text='') 26 27# Base window 28window = Tk() 29 30wc = Canvas(window, width = 2000, height = 2000) 31wc.create_rectangle(0,0,2000,2000, fill = "paleturquoise") 32wc.place(x = 0, y = 0) 33 34# Setting the title 35window.title("文房具の請求") 36 37# Coloring canvas 38for x in range(10): 39 c = Canvas(window, width = 240, height = 150) 40 c.create_rectangle(0,0,240,150, fill = "aliceblue") 41 c.place(x = 30 + int(x/5) * 270, y = 30 + (x%5) * 155) 42 43# Set Lavels 44item = ["ノート","鉛筆","シャープペン","消しゴム","色鉛筆","ボールペン","油性ペン","蛍光ペン","はさみ","のり"] 45for x in range(10): 46 i = Label(text = item[x], bg = "#82EBF7") 47 ko = Label(text = "個", bg = "aliceblue") 48 i.place(x = 30 + int(x/5) * 270, y = 30 + (x%5) * 155) 49 ko.place(x = 115 + int(x/5) * 270, y = 150 + (x%5) * 155) 50 51# Set Spinboxes 52spinboxes = [] 53spinbox_values =[] 54for x in range(10): 55 value = StringVar() 56 s = Spinbox(window, from_=0, to=100, width = 10, textvariable=value, command=lambda idx=x:update_value(idx)) 57 s.place(x = 40 + int(x/5) * 270, y = 150 + (x%5) * 155) 58 spinbox_values.append(value) 59 spinboxes.append(s) 60 61# Set price 62price = [100,20,150,50,40,120,180,200,350,240] 63for x in range(10): 64 t = Label(text = "{} 円".format(price[x]), bg = "aliceblue") 65 t.place(x = 30 + int(x/5) * 270, y = 70 + (x%5) * 155) 66 67# Set name 68name = ["商品名1","商品名2","商品名3","商品名4","商品名5","商品名6","商品名7","商品名8","商品名9","商品名10"] 69for x in range(10): 70 n = Label(text = name[x], bg = "aliceblue") 71 n.place(x = 30 + int(x/5) * 270, y = 50 + (x%5) * 155) 72 73# Set window 74window.geometry("1000x825+100+20") 75 76# Set subwindow 77sb = Canvas(window, width = 400, height = 700) 78sb.create_rectangle(0,0,400,700, fill = "white") 79sb.place(x = 570, y = 50) 80 81text = Label(window, text="カート", bg = "#69D7E3" ) 82text.place(x=570, y=50) 83 84note = Label(window, text = "", bg = "white" ) 85note.place(x=590, y=80) 86 87clr_button = Button(window, text = "CLEAR", bg = "white", command=clear_all) 88clr_button.place(x=580, y= 780) 89 90window.mainloop()

投稿2017/07/04 02:17

編集2017/07/04 04:16
magichan

総合スコア15898

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

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

flower

2017/07/04 02:39

修正の手順までわかりやすく教えていただき、ありがとうございました!未熟な点が多く冗長なプログラムを、わかりやすく、見やすいかたちに直してくださり、理解が深まりました。よく読み、参考にさせていただきますm(__)m 追伸. 右側に表示した値段やスピンボックス内の値を一つのボタンで一括削除するプログラムも考えているのですが、0に書き換えようとすると桁数があふれたところが書き換えられず、少しはみ出て見えてしまうのですが、どうすればよいでしょうか?
magichan

2017/07/04 04:19 編集

すみません。 上記の説明だけでは不具合の内容が理解できませんでした。 もう少し具体的なコードを記述していただけると助かります。 とりあえず、勝手な想定にて一括削除ボタンを実装をしてみましたので、参考にしてください。
flower

2017/07/04 04:47

CLEARをボタンを押したら、スピンボックスの各値を0にし、カートの中身の個数も連動して0にしたい、と考えていましたが、右側の中身をすべて消してしまうのも手ですね。ご丁寧に説明していただき、ありがとうございましたm(__)m
guest

0

pythonというよりもGUIアプリケーションの動きを理解する必要があります。
GUIアプリケーションは基本的にイベント駆動式です、spinboxのボタンが押されたときのイベントをcommand引数のコールバック関数で取得する必要があります。

おそらく、どこかの本かWebをコピーしたものと思います。
参考にしたものを教えてください。

投稿2017/07/03 01:53

pashango2

総合スコア930

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

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

flower

2017/07/04 02:31

なるほど、spinboxでcommand引数が使えることがわからず、ボタンをつけようか迷っていましたが、もう少し考えてみます!未熟者ですみません、ありがとうございましたm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問