macOS   ChatGPT   Todo

ホーム

恐る恐る ChatGPT を使ってプログラミングを始めてみます。

私の環境は、MacBook Air 2012 メモリ 4GB に OpenCore Legacy Patcher を使って未サポートのmacOS Big Sur 11.7.6をインストールしています。

もしかすると今後この環境がプログラミング上で不具合を起こすかもしれません。

Todo

前回では、オセロゲームを作ろうとしてうまくいきませんでした。今回はもう少し簡単なところで、Todo アプリを作ってみようと思います。

todoView.swift


import SwiftUI

struct TodoItem: Identifiable {
    let id = UUID()
    var title: String
    var details: String
    var createdAt = Date()
    var isCompleted = false
}

class TodoList: ObservableObject {
    @Published var items = [TodoItem]()
    
    func add(title: String, details: String) {
        items.append(TodoItem(title: title, details: details))
    }
    
    func remove(item: TodoItem) {
        if let index = items.firstIndex(where: { $0.id == item.id }) {
            items.remove(at: index)
        }
    }
    
    func toggleCompletion(item: TodoItem) {
        if let index = items.firstIndex(where: { $0.id == item.id }) {
            items[index].isCompleted.toggle()
        }
    }
}

struct ContentView: View {
    @ObservedObject var todoList = TodoList()
    @State var newTitle = ""
    @State var newDetails = ""
    
    var body: some View {
        NavigationView {
            List {
                Section(header: Text("New Task")) {
                    TextField("Title", text: $newTitle)
                    TextField("Details", text: $newDetails)
                    Button("Add Task") {
                        todoList.add(title: newTitle, details: newDetails)
                        newTitle = ""
                        newDetails = ""
                    }
                }
                
                Section(header: Text("Tasks")) {
                    ForEach(todoList.items) { item in
                        HStack {
                            Button(action: {
                                todoList.toggleCompletion(item: item)
                            }) {
                                if item.isCompleted {
                                    Image(systemName: "checkmark.circle.fill")
                                } else {
                                    Image(systemName: "circle")
                                }
                            }
                            .buttonStyle(BorderlessButtonStyle())
                            VStack(alignment: .leading) {
                                Text(item.title)
                                    .font(.headline)
                                Text(item.details)
                                    .font(.subheadline)
                            }
                            Spacer()
                            Button(action: {
                                todoList.remove(item: item)
                            }) {
                                Image(systemName: "trash")
                            }
                            .buttonStyle(BorderlessButtonStyle())
                        }
                    }
                }
            }
            .listStyle(DefaultListStyle())

            .navigationTitle("ToDo List")
        }
    }
}
	

todoApp.swift


import SwiftUI

// SwiftUI のプログラムは @main と書かれた所から始まる決まりになっています。
@main
struct FooApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

// 次のクラスは、アプリケーションのウィンドウが閉じたら、
// アプリケーションも終了するようにするためのコードです。
// macOS のデフォルトではウィドウを閉じてもアプリケーションは終了しません。
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        return true
   }
}
    

ToDo として機能しませんし、文字入力も受け付けてもらえません。しかし UI の出来としては良いように思います。

todo.py


from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
import datetime

class TodoItem:
    def __init__(self, title, details):
        self.title = title
        self.details = details
        self.created_at = datetime.datetime.now()
        self.completed = False

class TodoList:
    def __init__(self):
        self.items = []

    def add(self, item):
        self.items.append(item)

    def remove(self, item):
        self.items.remove(item)

    def toggle_completion(self, item):
        item.completed = not item.completed

class TodoApp:
    def __init__(self, master):
        self.master = master
        master.title("Todo List")
        master.geometry("400x400")

        self.todo_list = TodoList()

        self.title_label = Label(master, text="Title:")
        self.title_label.pack()

        self.title_entry = Entry(master)
        self.title_entry.pack()

        self.details_label = Label(master, text="Details:")
        self.details_label.pack()

        self.details_entry = Entry(master)
        self.details_entry.pack()

        self.add_button = Button(master, text="Add Task", command=self.add_task)
        self.add_button.pack()

        self.tasks_label = Label(master, text="Tasks:")
        self.tasks_label.pack()

        self.tasks_listbox = Listbox(master)
        self.tasks_listbox.pack()

        self.remove_button = Button(master, text="Remove Task", command=self.remove_task)
        self.remove_button.pack()

        self.complete_button = Button(master, text="Complete Task", command=self.toggle_completion)
        self.complete_button.pack()

        self.refresh_tasks()

    def add_task(self):
        title = self.title_entry.get()
        details = self.details_entry.get()
        item = TodoItem(title, details)
        self.todo_list.add(item)
        self.title_entry.delete(0, END)
        self.details_entry.delete(0, END)
        self.refresh_tasks()

    def remove_task(self):
        selection = self.tasks_listbox.curselection()
        if not selection:
            messagebox.showwarning("Error", "Please select a task to remove.")
            return
        index = selection[0]
        item = self.todo_list.items[index]
        self.todo_list.remove(item)
        self.refresh_tasks()

    def toggle_completion(self):
        selection = self.tasks_listbox.curselection()
        if not selection:
            messagebox.showwarning("Error", "Please select a task to complete.")
            return
        index = selection[0]
        item = self.todo_list.items[index]
        self.todo_list.toggle_completion(item)
        self.refresh_tasks()

    def refresh_tasks(self):
        self.tasks_listbox.delete(0, END)
        for item in self.todo_list.items:
            prefix = "[x] " if item.completed else "[ ] "
            self.tasks_listbox.insert(END, prefix + item.title)

root = Tk()
app = TodoApp(root)
root.mainloop()
    

Detail(詳細)が表示されませんが、前回のオセロゲームと合わせても、今までで一番機能しています。

todo.py その2


from tkinter import *
from tkinter import messagebox
import os

class TodoApp:
    def __init__(self, master):
        self.master = master
        self.master.title("ToDo App")
        self.master.geometry("300x300")
        
        # Create a label
        self.label = Label(self.master, text="Enter a task:")
        self.label.pack()
        
        # Create a task input box
        self.task_input = Entry(self.master)
        self.task_input.pack()
        
        # Create a button to add task
        self.add_button = Button(self.master, text="Add Task", command=self.add_task)
        self.add_button.pack()
        
        # Create a listbox to display tasks
        self.task_list = Listbox(self.master)
        self.task_list.pack()
        
        # Create a button to remove selected task
        self.remove_button = Button(self.master, text="Remove Task", command=self.remove_task)
        self.remove_button.pack()
        
        # Load tasks from file
        self.load_tasks()
    
    def add_task(self):
        task = self.task_input.get()
        if task:
            self.task_list.insert(END, task)
            self.task_input.delete(0, END)
            self.save_tasks()
        else:
            messagebox.showwarning("Warning", "Please enter a task")
    
    def remove_task(self):
        selected_task = self.task_list.curselection()
        if selected_task:
            self.task_list.delete(selected_task)
            self.save_tasks()
        else:
            messagebox.showwarning("Warning", "Please select a task to remove")
    
    def load_tasks(self):
        if os.path.exists("tasks.txt"):
            with open("tasks.txt", "r") as f:
                for task in f:
                    self.task_list.insert(END, task)
    
    def save_tasks(self):
        with open("tasks.txt", "w") as f:
            for i in range(self.task_list.size()):
                f.write(self.task_list.get(i) + "\n")

root = Tk()
app = TodoApp(root)
root.mainloop()
    

さっきより機能は減りましたが、項目の追加と削除、リストの保存ができ、再起動しても、以前のリストがちゃんと表示されます。これで編集機能が付けば、アプリケーションとしての最小必須機能をクリアしたことになりますが、一応これで Todo アプリは一行もコーディングすることなく完成したことにします。

メモ

今回はどんな質問したかについては書いていません。書くとキリがありません。ビルドしてエラーが出て、そのままそのエラーをコピーして、質問欄にペーストしての繰り返しです。 そして一応起動したら、起動したアプリの不具合箇所や、増やして欲しい機能などを、また質問します。その繰り返しです。

また、オセロゲームを作っているときは、カッコの閉じ忘れなどの初歩的なミスが多かったですが、今回はそれは出ませんでした。ChatGPT が恐ろしい勢いでノウハウを集積しているような気がします。今回で言えば、Python Tkinter の時にメインループを記述しないという癖がありました。これも数日後には修正されているかもしれません。

今やりたいこと

なんか、Python の勉強をしたくなりましたw。以前にやってたんですが、もう忘れたというかw。それに Mac に標準で Python と TclTk がインストールされなくなってるんですね。Emacs が標準で入っていないことは気づいていたんですが。今回はあちこちのサイトを見て、なんとなく Tkinter が使えるようになりましたが、Mac に Python Tkinter 環境を構築する方法を整理したくなってきました。

ChatGPT は続けるかもしれませんが、率先して使って、ChatGPTのサンプルになるよりは、十分に情報が集積されてからのほうが、「オセロゲームを作ってください」で、一発でオセロゲームを作ってくれるようになってる気がしなくもないですねw。

ついでに

Python を学習したくて Googole で検索したのですが、数が多すぎてどこが良いかわからなっかので、ChatGPT に質問してみました。

質問 Pythonを勉強下いのですが、どこのサイトが良いですか?日本語のサイトが良いです。

答え Pythonを学ぶには、以下の日本語のサイトが役立つでしょう。

  1. Python入門 | Python.jp - https://www.python.jp/train/index.html
  2. Pythonプログラミングの入門から応用まで学べる | TechAcademy - https://techacademy.jp/magazine/28786
  3. 【初心者向け】Python入門 | Progate - https://prog-8.com/languages/python
  4. Pythonチュートリアル | W3Schools Japan - https://www.w3schools.com/python/default.asp
  5. Pythonの文法・基礎からWebアプリ開発まで - Qiita - https://qiita.com/tags/python

これらのサイトは、Pythonの基礎から応用まで、様々なレベルに合わせた学習コンテンツを提供しています。また、サイト内にはコード例や実践的なチュートリアルが含まれており、理解を深めるのに役立ちます。

質問 Tkinterを勉強したいのですが、どこか良いサイトを教えてください。日本語サイトが良いです。

答え

Tkinterを学ぶには、以下のウェブサイトが役立つかもしれません。すべて日本語で提供されています。

  1. Python Tkinter 入門ガイド (https://www.javadrive.jp/python/tkinter/index1.html)
    このサイトは、初心者向けのPython Tkinter入門ガイドです。ウィジェットの作成からイベント処理、メニューの作成など、基本的な機能を網羅しています。
  2. Tkinterの使い方 (https://kuroro.blog/python/sgGWcJ0w0ZLkW8QfCIiD/)
    このサイトは、Python Tkinterの使い方について、サンプルコードを交えてわかりやすく解説しています。ウィジェット、キャンバス、ファイルダイアログなどの機能が説明されています。
  3. Tkinter(Python)の使い方【初心者向けチュートリアル】 (https://techacademy.jp/magazine/31807)
    このサイトは、初心者向けのPython Tkinterチュートリアルです。ウィンドウの作成、ボタン、ラベル、テキストボックス、チェックボックス、ラジオボタンなどのウィジェットが紹介されています。

これらのサイトは、Python Tkinterを学ぶ上で役立つ情報がたくさんあります。これらのリソースを利用して、Python Tkinterの基礎から応用まで学んでください。


結構リンク切れがあります。また次のように言われることもあります。

「申し訳ありませんが、私は英語のみの対応となっており、日本語の情報を提供することができません。しかし、以下の日本語のTkinter学習リソースが役立つかもしれません。」

なんかやっぱりな〜という感じw、ごっつ傷ついた。もしかしてオセロゲームやTodoも英語で質問したらもっとちゃんとした答えが返ってきてたのかも




2691 visits
Posted: May. 02, 2023
Update: May. 05, 2023

ホーム   目次