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

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

ただいまの
回答率

90.47%

  • Python 3.x

    6877questions

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

変数が生成された場所

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 107

yutaka_1213

score 1

todoitem.pyとtodocontainer.pyをインポートしてtodoapp.pyでtkを使って
todoリストを表示するプログラムです。

動かすことはできたのですが、todosという変数がどこで生成されたのかが
わかりませんでした。
説明が足りないと思いますが、もし可能であればtodosがどのタイミングで
生成されたのか教えていただけないでしょうか。
よろしくお願いいたします。


todoitem.py

from datetime import datetime, timedelta

class ToDoItem(object):

ToDo項目を保存

def init(self, title, description, duedate, addeddate=None):

ToDo項目初期化   

if not addeddate:
addeddate = datetime.now()
self.title = title              
self.description = description 
self.duedate = duedate          
self.addeddate = addeddate     
self.finished = False           
self.finisheddate = None        

def finish(self, date=None):

ToDo項目を終了

self.finished = True
if not date:
date = datetime.now()
self.finisheddate = date

def repr(self):

ToDo項目の表示形式文字列を作る

return "<ToDoItem {}, {}>".format(

self.title, self.duedate.strftime('%Y/%m/%d %H:%M'))

todocontainer.py

from datetime import datetime, timedelta

class ToDoContainer(object):

ToDo項目のリストを保存

def init(self):

ToDo項目のリストのインスタンスを初期化

self.todos = []

def len(self):

ToDo項目の数を返す

return len(self.todos)

def sort(self):

ToDoを締め切り日でソート

self.todos.sort(key=lambda x : x.duedate)       #!!!

def add(self, item):

「+」演算子をエミュレートして,ToDo項目を追加

self.todos.append(item)
self.sort()

def iadd(self, item):
"""
「+=」演算子をエミュレートして,ToDo項目を追加
"""
self.add(item)
return self

def getitem(self, idx):
"""
インデックスアクセスをエミュレート
"""
return self.todos[idx]

def setitem(self, idx, item):
"""
インデックスの代入ををエミュレート
"""
self.todos[idx] = item
self.sort()

def delitem(self, idx):
"""
インデックスを指定したdelをエミュレート
"""
del self.todos[idx]

def get_remaining_todos(self):
"""
終了していないToDo項目をリストとして返す
"""
return [t for t in self.todos if not t.finished]


todoapp.py

from datetime import datetime
from pickle import dump, load

from tkinter import *
import tkinter.messagebox

from todoitem import ToDoItem
from todocontainer import ToDoContainer

DUMPFILE = 'todo.dat'

class ToDoApp(Frame):

ToDo GUIアプリ用のクラス

def init(self, master=None):

Frame.init(self, master, padx=8, pady=4)
self.pack()
self.createwidgets()        
t = self.winfo_toplevel()
t.resizable(False, False)   
self.load()                 
sec = datetime.now().second 
self.after((60-sec)*1000, self.refreshitems)
self.sel_index = -1

def createwidgets(self):

ボタンなどウインドウの部品を作る

self.frame1 = Frame(self)
frame = self.frame1

self.listbox = Listbox(frame, height=10, width=30,
selectmode=SINGLE, takefocus=1)
self.yscroll = Scrollbar(frame, orient=VERTICAL)

 配置

self.listbox.grid(row=0, column=0, sticky=NS)
self.yscroll.grid(row=0, column=1, sticky=NS)

 動きとコードをつなげる

self.yscroll.config(command=self.listbox.yview)
self.listbox.config(yscrollcommand=self.yscroll.set)
self.listbox.bind("<ButtonRelease-1>", self.selectitem)

self.frame1.grid(row=0, column=0)

self.frame2 = Frame(self)
frame = self.frame2
self.title_l = Label(frame, text="タイトル")
self.description_l = Label(frame, text="詳細")
self.duedate_l = Label(frame, text="締め切り")
self.title_e = Entry(frame, justify=LEFT, width=20)
self.description_e = Entry(frame, justify=LEFT, width=20)
self.duedate_e = Entry(frame, justify=LEFT, width=20)
self.finished_v = IntVar()
self.finished_c = Checkbutton(frame, justify=LEFT, text="終了",
variable=self.finished_v)
self.update_button = Button(frame, text="更新", state=DISABLED,
command=self.updateitem)
self.delete_button = Button(frame, text="削除", state=DISABLED,
command=self.deleteitem)
self.new_button = Button(frame, text="新規",
command=self.createitem)

 配置

self.title_l.grid(row=0, column=0, columnspan=2)
self.title_e.grid(row=1, column=0, columnspan=2)
self.description_l.grid(row=2, column=0, columnspan=2)
self.description_e.grid(row=3, column=0, columnspan=2)
self.duedate_l.grid(row=4, column=0, columnspan=2)
self.duedate_e.grid(row=5, column=0, columnspan=2)
self.finished_c.grid(row=6, column=0, columnspan=2)
self.update_button.grid(row=7, column=0)
self.delete_button.grid(row=7, column=1)
self.new_button.grid(row=8, column=0, columnspan=2)

self.frame2.grid(row=0, column=1)

def load(self):

ToDoのデータをファイルから読み込む

try:
f = open(DUMPFILE, 'rb') #!!!
self.todos = load(f)
except IOError:
self.todos = ToDoContainer()

def save(self):
"""
ToDoのデータをファイルに書き出す
"""
f = open(DUMPFILE, 'wb') #!!!
dump(self.todos, f)

def setlistitems(self):
"""
ToDoのうち未消化分をリストに表示する
"""
self.listbox.delete(0, END)
for todo in self.todos.get_remaining_todos():
d = todo.duedate
t = todo.title.ljust(20)
if todo.duedate < datetime.now():
t = '* '+t      # ToDoの期限が過ぎていたら*を前につける
item = "{} {:4}/{:02}/{:02} {:02}:{:02}".format(
t, d.year, d.month, d.day, d.hour, d.minute)
self.listbox.insert(END, item)

def refreshitems(self):
"""
タイマーで定期的に呼び出されるメソッド
ToDoのうち時間になったものがあればダイアログで知らせる
"""
dirty = False
for todo in self.todos.get_remaining_todos():
td = datetime.now()
d = todo.duedate
if (d.year == td.year == td.year and d.month == td.month and
d.day == td.day and d.hour == td.hour and
d.minute == td.minute):
msg = "{}の時間です。\n {}\n {}".format(
todo.title, todo.description,
todo.duedate.strftime('%Y/%m%d %H:%M'))
tkinter.messagebox.showwarning("時間です", msg)
dirty = True
sec = datetime.now().second
self.after((60-sec)*1000, self.refreshitems)

if dirty:
self.setlistitems()

def clearentries(self):
"""
予定入力フィールドを消去する
"""
self.title_e.delete(0, END)
self.description_e.delete(0, END)
self.duedate_e.delete(0, END)
self.finished_c.deselect()

def selectitem(self, event):

Listboxで項目が選択されたときに呼ばれるメソッド

入力フィールドに選択された項目を反映

self.delete_button.config(state=NORMAL)
self.update_button.config(state=NORMAL)
for idx in self.listbox.curselection():
i = int(idx)
self.sel_index = i
td = self.todos.get_remaining_todos()[i]
self.clearentries()
self.title_e.insert(0, td.title)
self.description_e.insert(0, td.description)
ddtxt = td.duedate.strftime('%Y/%m/%d %H:%M')
self.duedate_e.insert(0, ddtxt)
if td.finished:
self.finished_c.select()
else:
self.finished_c.deselect()

def refrectententries(self, todo):

フィールドに入力された文字列をToDoItemインスタンスに反映する

todo.title = self.title_e.get()
todo.description = self.description_e.get()
dt = datetime.strptime(self.duedate_e.get()+':00',
'%Y/%m/%d %H:%M:%S')
todo.duedate = dt
if self.finished_v.get() != 0:
todo.finish()

def createitem(self):

新しいToDOアイテムを作る

todo = ToDoItem('', '', datetime.now())
self.refrectententries(todo)
self.todos += todo
self.clearentries()
self.setlistitems()
self.sel_index = -1
self.save()

def updateitem(self):

入力フィールドの情報を選択中のToDOアイテムに反映

if self.sel_index != -1:
i = self.sel_index
todo = self.todos.get_remaining_todos()[i]
self.todos.sort()
self.refrectententries(todo)
self.sel_index = -1
self.clearentries()
self.setlistitems()
self.save()

def deleteitem(self):

Listboxで選択されているToDoのアイテムを消去

for idx in self.listbox.curselection():
i = int(idx)
todo = self.todos.get_remaining_todos()[i]
real_idx = self.todos.todos.index(todo)
del self.todos[real_idx]
self.todos.sort()
self.clearentries()
self.setlistitems()
self.save()

def main():

root = Tk()
app = ToDoApp()        

app.setlistitems()      
app.mainloop()          
root.destroy()

if name == 'main':
main()

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • quiqui

    2018/05/25 14:03

    せめて読めるようにしてください。 https://teratail.com/help/question-tips#questionTips3-5 あと、属性値todosはありますが変数はないように見えます。一体どういう意味で聞いていますか?

    キャンセル

まだ回答がついていません

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    6877questions

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