Konten Sub Menu "Data Diri"
Isi Menu "Profil Kesehatan"
(Konten Sub Menu "Data Diri")
1. Sub Menu "Data Diri"
Sekarang kita membuat konten masing masing sub menu, pertama Data Diri, ini di bawah menu Profil Kesehatan
Kita akan menambahkan konten sub menu "Data Diri" di bawah menu Profil Kesehatan, sebagai bagian dari aplikasi SmartNutriChefAI. Sub menu ini akan berisi form input seperti: nama, umur, jenis kelamin, tinggi badan, dan berat badan, lalu tombol simpan dan kembali.
✅ Tujuan:
Menambahkan fungsi show_data_diri() di file menu_profil_kesehatan.py.
✅ Struktur:
menu_profil_kesehatan.py
├── show_menu_profil_kesehatan() # Menu utama Profil Kesehatan
│ └── tombol: "Data Diri" ➜ show_data_diri()
└── show_data_diri() # Submenu form input Data Diri
๐งฉ 1. Tambahkan ke menu_profil_kesehatan.py:
import tkinter as tk
from tkinter import ttk
def show_menu_profil_kesehatan(root_frame):
from menu_utama import tampilkan_halaman_utama
# Bersihkan frame
for widget in root_frame.winfo_children():
widget.destroy()
label_judul = tk.Label(root_frame, text="Profil Kesehatan", font=("Arial", 18, "bold"),
bg="green", fg="orange", pady=10)
label_judul.pack(pady=20, fill="x")
label_subjudul = tk.Label(root_frame, text="Silakan pilih opsi:", font=("Arial", 12),
bg="light blue", fg="green", pady=5)
label_subjudul.pack(pady=10, fill="x")
# Tombol submenu
tombol_data_diri = tk.Button(root_frame, text="Data Diri", font=("Arial", 12),
bg="#2196F3", fg="white", width=30, height=2,
command=lambda: show_data_diri(root_frame))
tombol_data_diri.pack(pady=10)
tombol_kembali = tk.Button(root_frame, text="Kembali ke Menu Utama", font=("Arial", 12),
bg="#4CAF50", fg="white", command=lambda: tampilkan_halaman_utama(root_frame))
tombol_kembali.pack(pady=30)
def show_data_diri(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan # Hindari circular import
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Data Diri", font=("Arial", 18, "bold"),
bg="green", fg="orange", pady=10).pack(pady=20, fill="x")
# Form input
form_data = {}
def buat_input(label_text, key):
frame = tk.Frame(root_frame, bg="light blue", pady=5)
frame.pack(fill="x", padx=20, pady=5)
label = tk.Label(frame, text=label_text, font=("Arial", 12),
bg="light blue", fg="green", width=20, anchor="w")
label.pack(side="left")
entry = tk.Entry(frame, font=("Arial", 12), width=30)
entry.pack(side="right", padx=10)
form_data[key] = entry
# Bidang input
buat_input("Nama Lengkap:", "nama")
buat_input("Usia (tahun):", "usia")
buat_input("Jenis Kelamin:", "jenis_kelamin")
buat_input("Tinggi Badan (cm):", "tinggi")
buat_input("Berat Badan (kg):", "berat")
# Tombol Simpan
def simpan_data():
data = {k: v.get() for k, v in form_data.items()}
print("Data Diri Disimpan:", data)
# Di sini bisa simpan ke file/database kalau perlu
tk.Button(root_frame, text="Simpan Data", font=("Arial", 12),
bg="blue", fg="white", width=20, height=2, command=simpan_data).pack(pady=20)
# Tombol kembali
tk.Button(root_frame, text="Kembali", font=("Arial", 12),
bg="#4CAF50", fg="white", width=20, height=2,
command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=10)
✅ Tampilan yang Akan Muncul
- Judul: "Data Diri"
- Form:
- Nama Lengkap
- Usia
- Jenis Kelamin
- Tinggi Badan
- Berat Badan
- Tombol:
- Simpan Data
- Kembali
❗️Catatan:
- Penyimpanan data masih berupa
print()ke konsol. Kalau ingin simpan ke file.json,.txt, atau SQLite, tinggal saya bantu lanjutkan. - Jika ingin validasi input (misalnya usia harus angka), itu juga bisa ditambahkan.
Siap lanjut ke submenu berikutnya seperti Kondisi Kesehatan, Tujuan Nutrisi, atau lainnya?
Saya mau simpan datanya ke SQLite, dan validasi input Usia, tinggi badan, betat badan harus angka
Bagus, kita akan menyimpan data ke SQLite dan menambahkan validasi input pada kolom:
- Usia
- Tinggi Badan
- Berat Badan
✅ Perubahan yang Akan Kita Lakukan:
- Tambahkan database SQLite (
data_diri.db) - Buat tabel
data_dirijika belum ada - Validasi input: hanya angka untuk usia, tinggi, dan berat
- Simpan data ke SQLite
๐ฆ 1. Buat atau tambahkan fungsi init_db() dan simpan_ke_db(data) ke menu_profil_kesehatan.py
Tambahkan di bagian paling atas:
import sqlite3
import tkinter as tk
from tkinter import messagebox
Lalu tambahkan ini setelah import:
# Inisialisasi database SQLite
def init_db():
conn = sqlite3.connect("data_diri.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_diri (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT,
usia INTEGER,
jenis_kelamin TEXT,
tinggi REAL,
berat REAL
)
""")
conn.commit()
conn.close()
def simpan_ke_db(data):
conn = sqlite3.connect("data_diri.db")
cursor = conn.cursor()
cursor.execute("""
INSERT INTO data_diri (nama, usia, jenis_kelamin, tinggi, berat)
VALUES (?, ?, ?, ?, ?)
""", (data['nama'], int(data['usia']), data['jenis_kelamin'], float(data['tinggi']), float(data['berat'])))
conn.commit()
conn.close()
๐งฉ 2. Panggil init_db() di awal fungsi show_data_diri()
def show_data_diri(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
init_db() # Panggil ini di awal
๐ 3. Ubah fungsi simpan_data() jadi:
def simpan_data():
data = {k: v.get().strip() for k, v in form_data.items()}
# Validasi
if not data['nama'] or not data['jenis_kelamin']:
messagebox.showerror("Input Error", "Nama dan Jenis Kelamin tidak boleh kosong.")
return
try:
data['usia'] = int(data['usia'])
data['tinggi'] = float(data['tinggi'])
data['berat'] = float(data['berat'])
except ValueError:
messagebox.showerror("Input Error", "Usia harus angka, Tinggi dan Berat harus berupa angka desimal.")
return
try:
simpan_ke_db(data)
messagebox.showinfo("Berhasil", "Data berhasil disimpan ke database.")
except Exception as e:
messagebox.showerror("Database Error", f"Gagal menyimpan data: {e}")
✅ Penyesuaian Akhir
- Pastikan kamu menyimpan file
menu_profil_kesehatan.pydi direktori sama dengan tempatsplash_screen.pydijalankan. - File database SQLite
data_diri.dbakan otomatis dibuat saat kamu buka sub menu "Data Diri".
๐งช Hasilnya:
Ketika pengguna mengisi:
- Nama
- Usia
- Jenis Kelamin
- Tinggi
- Berat
dan menekan Simpan, data akan tervalidasi dan disimpan ke SQLite.
Siap lanjut ke submenu berikutnya seperti:
- Kondisi Kesehatan
- Tujuan Nutrisi
- atau ingin saya bantu buat halaman untuk menampilkan data yang sudah disimpan?
Saya mau data_diri.db disimpan ke path: /storage/emulated/0/AppJadi/SmartNutriChefAI/Database/
Bagus! Kita bisa arahkan penyimpanan database data_diri.db ke folder:
/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/
Namun, perlu memastikan folder tersebut sudah ada sebelum menyimpan database ke sana. Kita akan:
✅ Langkah-Langkah:
- Buat folder jika belum ada
- Simpan database ke path tersebut
- Pastikan semua query tetap berjalan dengan baik
๐ ️ 1. Ubah Fungsi init_db() dan simpan_ke_db(data)
Ganti versi sebelumnya dengan versi ini:
import os
import sqlite3
import tkinter as tk
from tkinter import messagebox
# Path lengkap untuk menyimpan database
DB_FOLDER = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database"
DB_PATH = os.path.join(DB_FOLDER, "data_diri.db")
# Inisialisasi database SQLite
def init_db():
# Buat folder jika belum ada
if not os.path.exists(DB_FOLDER):
os.makedirs(DB_FOLDER)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_diri (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT,
usia INTEGER,
jenis_kelamin TEXT,
tinggi REAL,
berat REAL
)
""")
conn.commit()
conn.close()
def simpan_ke_db(data):
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
INSERT INTO data_diri (nama, usia, jenis_kelamin, tinggi, berat)
VALUES (?, ?, ?, ?, ?)
""", (data['nama'], int(data['usia']), data['jenis_kelamin'], float(data['tinggi']), float(data['berat'])))
conn.commit()
conn.close()
๐งช Testing
Setelah kamu jalankan aplikasi:
- Folder
/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/akan otomatis dibuat jika belum ada. - File
data_diri.dbakan tersimpan di sana. - Data pengguna yang diinput pada menu "Data Diri" akan masuk ke database.
⚠️ Catatan Tambahan (penting untuk Android atau termux):
Jika kamu menjalankan ini di Android (via Pydroid atau termux), pastikan:
- Aplikasi punya izin menulis ke storage.
- Jalur
/storage/emulated/0/...tersedia dan bisa diakses.
Jika perlu, tambahkan permission di Pydroid:
Settings → Permissions → Allow Storage Access
Ingin dilanjut ke fitur berikutnya, misalnya:
- Menampilkan data yang sudah disimpan
- Edit data pengguna
- atau submenu selanjutnya seperti Kondisi Kesehatan?
Maunya file dibuat terpisah antara file menu dengan file sub menu seperti antara file menu_profil_kesehatan.py dengan file sub_menu_data_diri.py, dan dan ketika user menginput data dirinya pertama kali, dan ketika sudah di input data, lalu tombol "Simpan data* ditekan, maka data akan tersimpan ke database, dan teks pada kotak entry harus sudah bersih,
Baik! Ini penjelasan dan implementasi sesuai permintaan Anda:
✅ Tujuan:
- Memisahkan file menu utama (
menu_profil_kesehatan.py) dengan sub-menu (sub_menu_data_diri.py) - Agar struktur aplikasi lebih modular, terorganisir, dan mudah dikembangkan
๐ Struktur Direktori Disarankan
/SmartNutriChefAI/
│
├── splash_screen.py
├── menu_utama.py
├── menu_profil_kesehatan.py
├── sub_menu_data_diri.py ✅ File baru untuk "Data Diri"
│
├── Database/
│ └── data_diri.db
✅ 1. menu_profil_kesehatan.py
import tkinter as tk
from sub_menu_data_diri import show_sub_menu_data_diri
def show_menu_profil_kesehatan(root_frame):
from menu_utama import tampilkan_halaman_utama # Hindari circular import
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
label_judul = tk.Label(root_frame, text="Menu Profil Kesehatan", font=("Arial", 18, "bold"), bg="green", fg="orange", padx=10, pady=10)
label_judul.pack(pady=20)
# Submenu tombol
submenus = [
("Data Diri", lambda: show_sub_menu_data_diri(root_frame)),
# Bisa tambah lagi: ("Hitung BMI", func_lainnya), dll.
]
for label, command in submenus:
lbl = tk.Label(root_frame, text=label, font=("Arial", 12), bg="light blue", fg="green")
lbl.pack(pady=5)
btn = tk.Button(root_frame, text=f"Buka {label}", command=command, font=("Arial", 12), bg="#4CAF50", fg="white")
btn.pack(pady=5)
# Tombol kembali
tk.Button(root_frame, text="Kembali ke Menu Utama", font=("Arial", 12), bg="gray", fg="white", command=lambda: tampilkan_halaman_utama(root_frame)).pack(pady=30)
✅ 2. sub_menu_data_diri.py
import tkinter as tk
from tkinter import messagebox
import sqlite3
import os
DB_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def init_db():
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_diri (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT NOT NULL,
usia INTEGER NOT NULL,
jenis_kelamin TEXT,
tinggi REAL NOT NULL,
berat REAL NOT NULL
)
""")
conn.commit()
conn.close()
def show_sub_menu_data_diri(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
init_db()
for widget in root_frame.winfo_children():
widget.destroy()
tk.Label(root_frame, text="Formulir Data Diri", font=("Arial", 18, "bold"), bg="green", fg="orange", padx=10, pady=10).pack(pady=20)
fields = {}
def buat_input(label, key):
tk.Label(root_frame, text=label, font=("Arial", 12), bg="light blue", fg="green").pack(pady=5)
entry = tk.Entry(root_frame, font=("Arial", 12), width=30)
entry.pack(pady=5)
fields[key] = entry
buat_input("Nama", "nama")
buat_input("Usia", "usia")
buat_input("Jenis Kelamin (L/P)", "jenis_kelamin")
buat_input("Tinggi Badan (cm)", "tinggi")
buat_input("Berat Badan (kg)", "berat")
def simpan_data():
try:
nama = fields["nama"].get()
usia = int(fields["usia"].get())
jenis_kelamin = fields["jenis_kelamin"].get()
tinggi = float(fields["tinggi"].get())
berat = float(fields["berat"].get())
if not nama or not jenis_kelamin:
raise ValueError("Nama dan Jenis Kelamin tidak boleh kosong.")
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
INSERT INTO data_diri (nama, usia, jenis_kelamin, tinggi, berat)
VALUES (?, ?, ?, ?, ?)
""", (nama, usia, jenis_kelamin, tinggi, berat))
conn.commit()
conn.close()
messagebox.showinfo("Sukses", "Data berhasil disimpan.")
for entry in fields.values():
entry.delete(0, tk.END)
except ValueError as ve:
messagebox.showerror("Input Salah", f"Kesalahan input: {ve}")
except Exception as e:
messagebox.showerror("Error", f"Terjadi kesalahan: {str(e)}")
tk.Button(root_frame, text="Simpan Data", font=("Arial", 12), bg="#4CAF50", fg="white", command=simpan_data).pack(pady=20)
tk.Button(root_frame, text="Kembali", font=("Arial", 12), bg="gray", fg="white", command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=10)
๐ Langkah Selanjutnya?
Jika sudah benar:
- Lanjutkan dengan edit data diri
- Tambahkan submenu hitung BMI
- Atau tampilkan data yang telah disimpan
Beritahu saya bagian selanjutnya yang ingin Anda bangun. Saya siap bantu ๐ป
Buatkan setiap kotak entry berada di samping label teksnya, dan buat validasi input Usia, tinggi badan, berat badan harus angka,
Baik! Berikut ini adalah versi terbaru dari file sub_menu_data_diri.py sesuai permintaan Anda:
✅ Perubahan:
- Label teks berada di samping kiri kotak entry (menggunakan
tk.Framedanpack(side=...)) - Validasi:
Usia,Tinggi, danBerat Badanwajib berupa angka. - Layout lebih rapi dengan margin/padding yang sesuai.
✅ Kode Lengkap sub_menu_data_diri.py
import tkinter as tk
from tkinter import messagebox
import sqlite3
import os
DB_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def init_db():
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_diri (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT NOT NULL,
usia INTEGER NOT NULL,
jenis_kelamin TEXT,
tinggi REAL NOT NULL,
berat REAL NOT NULL
)
""")
conn.commit()
conn.close()
def show_sub_menu_data_diri(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
init_db()
for widget in root_frame.winfo_children():
widget.destroy()
tk.Label(root_frame, text="Formulir Data Diri", font=("Arial", 18, "bold"),
bg="green", fg="orange", padx=10, pady=10).pack(pady=20)
fields = {}
def buat_input(label_text, key):
frame = tk.Frame(root_frame)
frame.pack(pady=5)
label = tk.Label(frame, text=label_text, font=("Arial", 12), bg="light blue", fg="green", width=20, anchor='w')
label.pack(side=tk.LEFT, padx=5)
entry = tk.Entry(frame, font=("Arial", 12), width=30)
entry.pack(side=tk.LEFT, padx=5)
fields[key] = entry
buat_input("Nama", "nama")
buat_input("Usia", "usia")
buat_input("Jenis Kelamin (L/P)", "jenis_kelamin")
buat_input("Tinggi Badan (cm)", "tinggi")
buat_input("Berat Badan (kg)", "berat")
def simpan_data():
try:
nama = fields["nama"].get().strip()
usia_str = fields["usia"].get().strip()
jenis_kelamin = fields["jenis_kelamin"].get().strip()
tinggi_str = fields["tinggi"].get().strip()
berat_str = fields["berat"].get().strip()
# Validasi angka
if not usia_str.isdigit():
raise ValueError("Usia harus berupa angka bulat.")
if not tinggi_str.replace('.', '', 1).isdigit():
raise ValueError("Tinggi harus berupa angka.")
if not berat_str.replace('.', '', 1).isdigit():
raise ValueError("Berat harus berupa angka.")
usia = int(usia_str)
tinggi = float(tinggi_str)
berat = float(berat_str)
if not nama or not jenis_kelamin:
raise ValueError("Nama dan Jenis Kelamin tidak boleh kosong.")
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
INSERT INTO data_diri (nama, usia, jenis_kelamin, tinggi, berat)
VALUES (?, ?, ?, ?, ?)
""", (nama, usia, jenis_kelamin, tinggi, berat))
conn.commit()
conn.close()
messagebox.showinfo("Sukses", "Data berhasil disimpan.")
for entry in fields.values():
entry.delete(0, tk.END)
except ValueError as ve:
messagebox.showerror("Validasi Gagal", str(ve))
except Exception as e:
messagebox.showerror("Error", f"Terjadi kesalahan: {str(e)}")
# Tombol simpan
tk.Button(root_frame, text="Simpan Data", font=("Arial", 12),
bg="#4CAF50", fg="white", command=simpan_data).pack(pady=20)
# Tombol kembali
tk.Button(root_frame, text="Kembali", font=("Arial", 12),
bg="gray", fg="white", command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=10)
✅ Penjelasan Validasi
usia_str.isdigit()→ memastikan usia adalah bilangan bulat.tinggi_str.replace('.', '', 1).isdigit()→ validasi angka pecahan seperti170.5- Semua input dikosongkan kembali dengan
entry.delete(0, tk.END)setelah berhasil simpan.
Kalau sudah sesuai, saya siap bantu lanjut ke fitur berikutnya seperti edit data pengguna atau menampilkan data. Mau dilanjutkan?
Buatkan satu tombol lagi di antara tombol "Simpan data" dan tombol "Kembali" yaitu tombol "Edit Data" untuk mengedit (memperbarui) data diri pengguna. Dengan begitu, user bisa memperbarui data dirinya dengan menekan tombol "Edit Data" ini, Untuk itu tolong tambahkan fitur Edit Data Pengguna agar pengguna dapat mengubah data diri yang sebelumnya telah disimpan ke database SQLite.
Bagus, kita lanjutkan! ๐
๐ฏ Tujuan:
Ketika tombol "Edit Data" ditekan, data pengguna yang terakhir disimpan di database akan ditampilkan kembali ke dalam Entry untuk diedit, lalu setelah diubah, pengguna bisa tekan "Simpan Perubahan".
✅ Fitur "Edit Data Pengguna"
Kita akan lakukan perubahan berikut:
- Tambah tombol "Edit Data" di bawah tombol "Simpan Data".
- Ketika ditekan, sistem akan:
- Mengambil data terakhir dari database
- Menampilkannya di form
- Mengubah tombol "Simpan Data" menjadi "Simpan Perubahan" sementara
✅ Kode Lengkap Final sub_menu_data_diri.py (dengan fitur Edit)
import tkinter as tk
from tkinter import messagebox
import sqlite3
import os
DB_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def init_db():
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_diri (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT NOT NULL,
usia INTEGER NOT NULL,
jenis_kelamin TEXT,
tinggi REAL NOT NULL,
berat REAL NOT NULL
)
""")
conn.commit()
conn.close()
def show_sub_menu_data_diri(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
init_db()
for widget in root_frame.winfo_children():
widget.destroy()
tk.Label(root_frame, text="Formulir Data Diri", font=("Arial", 18, "bold"),
bg="green", fg="orange", padx=10, pady=10).pack(pady=20)
fields = {}
current_edit_id = [None] # gunakan list agar bisa dimodifikasi di nested function
def buat_input(label_text, key):
frame = tk.Frame(root_frame)
frame.pack(pady=5)
label = tk.Label(frame, text=label_text, font=("Arial", 12), bg="light blue", fg="green", width=20, anchor='w')
label.pack(side=tk.LEFT, padx=5)
entry = tk.Entry(frame, font=("Arial", 12), width=30)
entry.pack(side=tk.LEFT, padx=5)
fields[key] = entry
buat_input("Nama", "nama")
buat_input("Usia", "usia")
buat_input("Jenis Kelamin (L/P)", "jenis_kelamin")
buat_input("Tinggi Badan (cm)", "tinggi")
buat_input("Berat Badan (kg)", "berat")
def bersihkan_entry():
for entry in fields.values():
entry.delete(0, tk.END)
current_edit_id[0] = None
tombol_simpan.config(text="Simpan Data")
def ambil_data_form():
nama = fields["nama"].get().strip()
usia_str = fields["usia"].get().strip()
jenis_kelamin = fields["jenis_kelamin"].get().strip()
tinggi_str = fields["tinggi"].get().strip()
berat_str = fields["berat"].get().strip()
# Validasi angka
if not usia_str.isdigit():
raise ValueError("Usia harus berupa angka bulat.")
if not tinggi_str.replace('.', '', 1).isdigit():
raise ValueError("Tinggi harus berupa angka.")
if not berat_str.replace('.', '', 1).isdigit():
raise ValueError("Berat harus berupa angka.")
if not nama or not jenis_kelamin:
raise ValueError("Nama dan Jenis Kelamin tidak boleh kosong.")
return (
nama,
int(usia_str),
jenis_kelamin,
float(tinggi_str),
float(berat_str)
)
def simpan_data():
try:
data = ambil_data_form()
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
if current_edit_id[0] is not None:
# UPDATE data
cursor.execute("""
UPDATE data_diri SET nama=?, usia=?, jenis_kelamin=?, tinggi=?, berat=?
WHERE id=?
""", data + (current_edit_id[0],))
messagebox.showinfo("Sukses", "Data berhasil diperbarui.")
else:
# INSERT data
cursor.execute("""
INSERT INTO data_diri (nama, usia, jenis_kelamin, tinggi, berat)
VALUES (?, ?, ?, ?, ?)
""", data)
messagebox.showinfo("Sukses", "Data berhasil disimpan.")
conn.commit()
conn.close()
bersihkan_entry()
except ValueError as ve:
messagebox.showerror("Validasi Gagal", str(ve))
except Exception as e:
messagebox.showerror("Error", f"Terjadi kesalahan: {str(e)}")
def edit_data():
try:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("SELECT * FROM data_diri ORDER BY id DESC LIMIT 1")
result = cursor.fetchone()
conn.close()
if result:
current_edit_id[0] = result[0] # Simpan id yang sedang diedit
fields["nama"].delete(0, tk.END)
fields["nama"].insert(0, result[1])
fields["usia"].delete(0, tk.END)
fields["usia"].insert(0, str(result[2]))
fields["jenis_kelamin"].delete(0, tk.END)
fields["jenis_kelamin"].insert(0, result[3])
fields["tinggi"].delete(0, tk.END)
fields["tinggi"].insert(0, str(result[4]))
fields["berat"].delete(0, tk.END)
fields["berat"].insert(0, str(result[5]))
tombol_simpan.config(text="Simpan Perubahan")
else:
messagebox.showinfo("Info", "Belum ada data yang dapat diedit.")
except Exception as e:
messagebox.showerror("Error", f"Gagal mengambil data: {str(e)}")
# Tombol Simpan / Simpan Perubahan
tombol_simpan = tk.Button(root_frame, text="Simpan Data", font=("Arial", 12),
bg="#4CAF50", fg="white", command=simpan_data)
tombol_simpan.pack(pady=10)
# Tombol Edit Data
tk.Button(root_frame, text="Edit Data", font=("Arial", 12),
bg="orange", fg="white", command=edit_data).pack(pady=5)
# Tombol Kembali
tk.Button(root_frame, text="Kembali", font=("Arial", 12),
bg="gray", fg="white", command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=10)
✅ Struktur Tombol
[Simpan Data] ← Menyimpan baru atau simpan perubahan
[Edit Data] ← Memuat data terakhir ke form untuk diedit
[Kembali]
๐ Alur:
- User isi data ➝ klik Simpan Data.
- User klik Edit Data ➝ data sebelumnya otomatis tampil.
- User ubah ➝ klik Simpan Perubahan.
Siap lanjut ke fitur berikutnya? Misalnya:
- Menampilkan daftar riwayat input
- Validasi jenis kelamin
- Hapus data
Silakan beri instruksi selanjutnya.
Sampai saat ini perubahan, penyempurnaan, dan tambahan file pada applikasi SmartNutriChefAI adalah:
1. menu_profil_kesehatan.py
Kode programnya adalah berikut:
# Menu Profil Kesehatan
import tkinter as tk
from sub_menu_data_diri import show_sub_menu_data_diri
def show_menu_profil_kesehatan(root_frame):
from menu_utama import tampilkan_halaman_utama # Hindari circular import
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
label_judul = tk.Label(root_frame, text="Profil Kesehatan", font=("Arial", 18, "bold"), bg="green", fg="orange", padx=10, pady=10)
label_judul.pack(pady=20)
# Submenu tombol
submenus = [
("Data Diri", lambda: show_sub_menu_data_diri(root_frame)),
# Bisa tambah lagi: ("Hitung BMI", func_lainnya), dll.
]
for label, command in submenus:
lbl = tk.Label(root_frame, text=label, font=("Arial", 12), bg="light blue", fg="green")
lbl.pack(pady=5)
btn = tk.Button(root_frame, text=f"Buka {label}", command=command, font=("Arial", 12), bg="#4CAF50", fg="white")
btn.pack(pady=5)
# Tombol kembali
tk.Button(root_frame, text="Kembali ke Menu Utama", font=("Arial", 12), bg="gray", fg="white", command=lambda: tampilkan_halaman_utama(root_frame)).pack(pady=30)
2. sub_menu_data_diri.py
Kode programnya adalah berikut:
# Sub Meny Data Diri
import tkinter as tk
from tkinter import messagebox
import sqlite3
import os
DB_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def init_db():
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS data_diri (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nama TEXT NOT NULL,
usia INTEGER NOT NULL,
jenis_kelamin TEXT,
tinggi REAL NOT NULL,
berat REAL NOT NULL
)
""")
conn.commit()
conn.close()
def show_sub_menu_data_diri(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
init_db()
for widget in root_frame.winfo_children():
widget.destroy()
tk.Label(root_frame, text="Formulir Data Diri", font=("Arial", 18, "bold"),
bg="green", fg="orange", padx=10, pady=10).pack(pady=20)
fields = {}
current_edit_id = [None] # gunakan list agar bisa dimodifikasi di nested function
def buat_input(label_text, key):
frame = tk.Frame(root_frame)
frame.pack(pady=5)
label = tk.Label(frame, text=label_text, font=("Arial", 8), bg="light blue", fg="dark green", width=16, anchor='w')
label.pack(side=tk.LEFT, padx=5)
entry = tk.Entry(frame, font=("Arial", 8), width=30)
entry.pack(side=tk.LEFT, padx=5)
fields[key] = entry
buat_input("Nama", "nama")
buat_input("Usia", "usia")
buat_input("Jenis Kelamin (L/P)", "jenis_kelamin")
buat_input("Tinggi Badan (cm)", "tinggi")
buat_input("Berat Badan (kg)", "berat")
def bersihkan_entry():
for entry in fields.values():
entry.delete(0, tk.END)
current_edit_id[0] = None
tombol_simpan.config(text="Simpan Data")
def ambil_data_form():
nama = fields["nama"].get().strip()
usia_str = fields["usia"].get().strip()
jenis_kelamin = fields["jenis_kelamin"].get().strip()
tinggi_str = fields["tinggi"].get().strip()
berat_str = fields["berat"].get().strip()
# Validasi angka
if not usia_str.isdigit():
raise ValueError("Usia harus berupa angka bulat.")
if not tinggi_str.replace('.', '', 1).isdigit():
raise ValueError("Tinggi harus berupa angka.")
if not berat_str.replace('.', '', 1).isdigit():
raise ValueError("Berat harus berupa angka.")
if not nama or not jenis_kelamin:
raise ValueError("Nama dan Jenis Kelamin tidak boleh kosong.")
return (
nama,
int(usia_str),
jenis_kelamin,
float(tinggi_str),
float(berat_str)
)
def simpan_data():
try:
data = ambil_data_form()
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
if current_edit_id[0] is not None:
# UPDATE data
cursor.execute("""
UPDATE data_diri SET nama=?, usia=?, jenis_kelamin=?, tinggi=?, berat=?
WHERE id=?
""", data + (current_edit_id[0],))
messagebox.showinfo("Sukses", "Data berhasil diperbarui.")
else:
# INSERT data
cursor.execute("""
INSERT INTO data_diri (nama, usia, jenis_kelamin, tinggi, berat)
VALUES (?, ?, ?, ?, ?)
""", data)
messagebox.showinfo("Sukses", "Data berhasil disimpan.")
conn.commit()
conn.close()
bersihkan_entry()
except ValueError as ve:
messagebox.showerror("Validasi Gagal", str(ve))
except Exception as e:
messagebox.showerror("Error", f"Terjadi kesalahan: {str(e)}")
def edit_data():
try:
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("SELECT * FROM data_diri ORDER BY id DESC LIMIT 1")
result = cursor.fetchone()
conn.close()
if result:
current_edit_id[0] = result[0] # Simpan id yang sedang diedit
fields["nama"].delete(0, tk.END)
fields["nama"].insert(0, result[1])
fields["usia"].delete(0, tk.END)
fields["usia"].insert(0, str(result[2]))
fields["jenis_kelamin"].delete(0, tk.END)
fields["jenis_kelamin"].insert(0, result[3])
fields["tinggi"].delete(0, tk.END)
fields["tinggi"].insert(0, str(result[4]))
fields["berat"].delete(0, tk.END)
fields["berat"].insert(0, str(result[5]))
tombol_simpan.config(text="Simpan Perubahan")
else:
messagebox.showinfo("Info", "Belum ada data yang dapat diedit.")
except Exception as e:
messagebox.showerror("Error", f"Gagal mengambil data: {str(e)}")
# Tombol Simpan / Simpan Perubahan
tombol_simpan = tk.Button(root_frame, text="Simpan Data", font=("Arial", 12),
bg="#4CAF50", fg="white", command=simpan_data)
tombol_simpan.pack(pady=10)
# Tombol Edit Data
tk.Button(root_frame, text="Edit Data", font=("Arial", 12),
bg="orange", fg="white", command=edit_data).pack(pady=5)
# Tombol Kembali
tk.Button(root_frame, text="Kembali", font=("Arial", 12),
bg="gray", fg="white", command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=10)
.
Bersambung Ke: Konten Sub Menu "Berat & Tinggi Badan"
Comments
Post a Comment