Konten Sub Menu "Status Gizi"
Isi Menu "Profil Kesehatan"
(Konten Sub Menu "Status Gizi")
6. Sub Menu “Status Gizi”
Lanjut kita membuat konten Sub Menu "Status Gizi"
Oke, untuk sub menu "Status Gizi", saya sarankan kita bikin dua fitur utama di layarnya:
- Ambil data otomatis dari
data_diri.dbuntuk menghitung status gizi berdasarkan IMT (Indeks Massa Tubuh). - Menampilkan hasil status gizi langsung di layar, termasuk kategori gizi menurut WHO (Kurus, Normal, Overweight, Obesitas).
Struktur filenya kita buat seperti file sub menu lain, misalnya:
sub_menu_status_gizi.py
Kode sub_menu_status_gizi.py
import tkinter as tk
import sqlite3
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def ambil_data_diri():
"""Ambil data berat & tinggi dari database"""
try:
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT berat_badan, tinggi_badan FROM data_diri ORDER BY id DESC LIMIT 1")
hasil = c.fetchone()
conn.close()
return hasil # (berat, tinggi)
except:
return None
def show_sub_menu_status_gizi(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan # Hindari circular import
# Bersihkan layar
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(
root_frame,
text="Status Gizi",
font=("Arial", 18, "bold"),
bg="green",
fg="orange",
pady=10
).pack(pady=20)
# Frame info
info_frame = tk.Frame(root_frame)
info_frame.pack(pady=10)
berat_label = tk.Label(info_frame, text="Berat Badan: -", font=("Arial", 12))
berat_label.grid(row=0, column=0, sticky="w", padx=5, pady=5)
tinggi_label = tk.Label(info_frame, text="Tinggi Badan: -", font=("Arial", 12))
tinggi_label.grid(row=1, column=0, sticky="w", padx=5, pady=5)
hasil_label = tk.Label(root_frame, text="", font=("Arial", 12), fg="blue")
hasil_label.pack(pady=10)
# Fungsi hitung status gizi
def hitung_status_gizi():
data = ambil_data_diri()
if not data:
hasil_label.config(text="⚠ Data tidak ditemukan di database.")
return
berat, tinggi = data
berat_label.config(text=f"Berat Badan: {berat} kg")
tinggi_label.config(text=f"Tinggi Badan: {tinggi} cm")
if berat <= 0 or tinggi <= 0:
hasil_label.config(text="⚠ Data tidak valid.")
return
tinggi_m = tinggi / 100
imt = berat / (tinggi_m ** 2)
# Kategori WHO
if imt < 18.5:
status = "Kurus"
elif 18.5 <= imt < 25:
status = "Normal"
elif 25 <= imt < 30:
status = "Kelebihan Berat Badan"
else:
status = "Obesitas"
hasil_label.config(text=f"IMT: {imt:.2f} → Status Gizi: {status}")
# Tombol hitung
tk.Button(
root_frame,
text="Hitung Status Gizi",
font=("Arial", 12),
bg="#4CAF50",
fg="white",
command=hitung_status_gizi
).pack(pady=10)
# 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=20)
Cara kerja:
- Saat masuk ke menu "Status Gizi", user tekan tombol "Hitung Status Gizi".
- Sistem otomatis mengambil berat & tinggi terakhir dari
data_diri.db. - Menghitung IMT, lalu menampilkan kategori gizi.
- Tidak ada input manual — data diambil dari database untuk meminimalkan kesalahan.
Kalau mau, saya bisa tambahkan opsi input manual kalau data di database kosong, jadi menu ini tetap bisa dipakai meskipun user belum mengisi Data Diri.
Mau langsung saya buatkan versi yang ada fallback input manual itu?
Bagaimana perubahan isi file mwnu_profil_kesehatan.py
Kalau kita menambahkan sub menu baru "Status Gizi", maka file menu_profil_kesehatan.py harus diperbarui supaya tombolnya ikut muncul.
Supaya rapi dan mudah tambah menu lagi nanti, tombol-tombol sub menu akan kita buat pakai loop list — bukan hardcode satu per satu seperti sebelumnya.
Dengan begitu, kalau mau menambah sub menu lain, cukup tambah 1 baris di list.
Perubahan menu_profil_kesehatan.py
# Menu Profil Kesehatan
import tkinter as tk
from sub_menu_data_diri import show_sub_menu_data_diri
from sub_menu_berat_tinggi_badan import show_sub_menu_berat_tinggi_badan
from sub_menu_indeks_massa_tubuh import show_sub_menu_indeks_massa_tubuh
from sub_menu_riwayat_kesehatan import show_sub_menu_riwayat_kesehatan
from sub_menu_kebutuhan_kalori import show_sub_menu_kebutuhan_kalori
from sub_menu_status_gizi import show_sub_menu_status_gizi
def show_menu_profil_kesehatan(root_frame):
from menu_utama import tampilkan_halaman_utama # Hindari circular import
# Bersihkan layar
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(
root_frame,
text="Profil Kesehatan",
font=("Arial", 18, "bold"),
bg="green",
fg="orange",
padx=10,
pady=10
).pack(pady=20)
# List sub menu: (label, fungsi)
sub_menus = [
("Data Diri", show_sub_menu_data_diri),
("Berat & Tinggi Badan", show_sub_menu_berat_tinggi_badan),
("Indeks Massa Tubuh (IMT)", show_sub_menu_indeks_massa_tubuh),
("Riwayat Kesehatan", show_sub_menu_riwayat_kesehatan),
("Kebutuhan Kalori Harian", show_sub_menu_kebutuhan_kalori),
("Status Gizi", show_sub_menu_status_gizi),
]
# Loop buat tombol sub menu
for i, (label, func) in enumerate(sub_menus):
tk.Button(
root_frame,
text=label,
font=("Arial", 12),
bg="light blue",
fg="black",
command=lambda f=func: f(root_frame)
).pack(pady=10)
# Separator antar tombol (kecuali terakhir)
if i < len(sub_menus) - 1:
tk.Frame(root_frame, height=2, bg="gray").pack(fill="x", padx=50, pady=2)
# 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)
Keuntungan cara ini:
- Lebih singkat: Semua tombol sub menu dibuat dari 1 loop.
- Mudah tambah menu baru: Cukup tambahkan tuple
(nama tombol, fungsi)di listsub_menus. - Ada separator otomatis antar tombol supaya rapi.
Kalau mau, saya bisa tambahkan ikon kecil di sebelah teks tombol supaya menu ini kelihatan lebih menarik.
Mau saya buatkan versi dengan ikon?
Ketika kode program dieksekusi, dan tombol "Hitung Status Gizi" ditekan, muncul error: Data Tidak Ditemukan di Database
Itu artinya di database data_diri.db belum ada data yang dibaca oleh file sub_menu_status_gizi.py ketika tombol "Hitung Status Gizi" ditekan.
Penyebab umum:
- Tabel
data_dirikosong — User belum pernah mengisi data melalui menu Data Diri. - Path database salah — Lokasi
data_diri.dbdi kodesub_menu_status_gizi.pytidak sama dengan lokasi penyimpanan di menu Data Diri. - Format tabel tidak sesuai — Kolom yang dibaca (misalnya
berat_badandantinggi_badan) tidak ada di tabel.
Solusi yang perlu dilakukan
1️⃣ Pastikan path database sama
Di sub_menu_status_gizi.py pastikan:
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
Path ini harus sama dengan yang dipakai di sub_menu_data_diri.py.
2️⃣ Pastikan ada data di tabel data_diri
Coba cek manual dengan script sederhana:
import sqlite3
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
cursor.execute("SELECT * FROM data_diri")
rows = cursor.fetchall()
print(rows)
conn.close()
Kalau hasilnya [], berarti memang tidak ada data → user harus isi dulu lewat menu Data Diri.
3️⃣ Tambahkan validasi di sub_menu_status_gizi.py
Supaya tidak error dan muncul pesan yang jelas:
cursor.execute("SELECT berat_badan, tinggi_badan FROM data_diri ORDER BY id DESC LIMIT 1")
result = cursor.fetchone()
if result:
berat_badan, tinggi_badan = result
# lanjut hitung status gizi...
else:
messagebox.showwarning("Data Tidak Ditemukan", "Silakan isi data diri Anda terlebih dahulu di menu 'Data Diri'.")
return
Kalau mau, aku bisa langsung revisikan file sub_menu_status_gizi.py milik kamu supaya:
- Otomatis memeriksa ketersediaan data
- Menampilkan peringatan kalau data belum diinput
- Tidak crash/error walaupun database kosong
Mau saya buatkan langsung revisinya?
Apa iti Status Gizi?.
Data ada tetsedia di database (data_diri.db), file data_diri.db ada di dirwktori dengan path: /storage/emulated/0/AppJadi/SmartNutriChefAI/Database/
Mungkin kode pada isi file sub_menu_status_gizi.py perlu diperbaiki
Oke, saya jelaskan dulu singkat.
Status gizi adalah kondisi tubuh seseorang yang ditentukan oleh keseimbangan antara asupan gizi dan kebutuhan gizi tubuhnya.
Umumnya diukur lewat IMT (Indeks Massa Tubuh) dan dibandingkan dengan kategori WHO:
- IMT < 18.5 → Kekurangan gizi (underweight)
- 18.5 ≤ IMT < 25 → Normal
- 25 ≤ IMT < 30 → Kelebihan berat badan (overweight)
- IMT ≥ 30 → Obesitas
Kalau datanya sudah ada di database tapi saat tombol Hitung Status Gizi ditekan masih muncul error "Data Tidak Ditemukan", berarti kemungkinan besar kodenya tidak membaca data dengan benar dari data_diri.db.
Saya bisa perbaiki sub_menu_status_gizi.py agar:
- Path database sesuai (
/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db). - Mengambil data terakhir dari tabel
data_diri. - Menghitung IMT otomatis dan menampilkan hasil status gizi di layar, bukan di kotak pesan.
- Tidak error walaupun tabel kosong.
Berikut contoh revisinya:
import tkinter as tk
from tkinter import messagebox
import sqlite3
# Path database
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def hitung_status_gizi(berat, tinggi):
tinggi_meter = tinggi / 100
imt = berat / (tinggi_meter ** 2)
if imt < 18.5:
kategori = "Kurus"
elif 18.5 <= imt < 25:
kategori = "Normal"
elif 25 <= imt < 30:
kategori = "Gemuk"
else:
kategori = "Obesitas"
return imt, kategori
def show_sub_menu_status_gizi(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
# Bersihkan frame
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Status Gizi", font=("Arial", 18, "bold"), bg="green", fg="orange", pady=10).pack(pady=20)
# Frame untuk hasil
frame_hasil = tk.Frame(root_frame)
frame_hasil.pack(pady=20)
# Ambil data terakhir dari database
try:
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
cursor.execute("SELECT berat, tinggi FROM data_diri ORDER BY id DESC LIMIT 1")
result = cursor.fetchone()
conn.close()
if result:
berat_badan, tinggi_badan = result
imt, kategori = hitung_status_gizi(berat_badan, tinggi_badan)
tk.Label(frame_hasil, text=f"Berat Badan: {berat_badan} kg", font=("Arial", 12)).pack()
tk.Label(frame_hasil, text=f"Tinggi Badan: {tinggi_badan} cm", font=("Arial", 12)).pack()
tk.Label(frame_hasil, text=f"IMT: {imt:.2f}", font=("Arial", 12, "bold")).pack()
tk.Label(frame_hasil, text=f"Status Gizi: {kategori}", font=("Arial", 12, "bold")).pack()
else:
tk.Label(frame_hasil, text="Data tidak ditemukan. Silakan isi data di menu 'Data Diri'.", font=("Arial", 12), fg="red").pack()
except sqlite3.Error as e:
tk.Label(frame_hasil, text=f"Error membaca database: {e}", font=("Arial", 12), fg="red").pack()
# 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=30)
Dengan kode ini:
- Dia akan membaca data terakhir dari
data_diri.db. - Menampilkan berat, tinggi, IMT, dan kategori status gizi langsung di layar.
- Tidak akan crash jika database kosong → muncul pesan peringatan di layar, bukan messagebox.
- Path sudah sesuai dengan yang kamu pakai di menu Data Diri.
Kalau mau, saya juga bisa tambahkan fitur input manual di halaman Status Gizi supaya user bisa hitung tanpa harus mengubah database.
Mau saya tambahkan juga?
Kode yang benar:
SELECT berat, tinggi FROM data_diri
Sudah tampil Hasil hitungan Status Gizi, langsung ditampilkan di frame (layar) berdasarkan data dari database. Sekarang tambahkan juga hitungan manualnya dengan ada tombol "Hitung Status Gizi"
Oke, berarti kita sudah tahu kolomnya adalah berat dan tinggi, jadi query database sudah aman.
Sekarang saya buatkan versi sub_menu_status_gizi.py yang:
- Menampilkan hasil Status Gizi langsung dari database (data terakhir).
- Menambahkan form input manual untuk menghitung status gizi dengan memasukkan berat & tinggi di kotak entry.
- Menampilkan hasilnya di layar, bukan messagebox.
- Membersihkan kotak entry setelah tombol ditekan.
import tkinter as tk
from tkinter import messagebox
import sqlite3
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def ambil_data_dari_db():
"""Ambil data berat dan tinggi terakhir dari database."""
try:
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
cursor.execute("SELECT berat, tinggi FROM data_diri ORDER BY id DESC LIMIT 1")
data = cursor.fetchone()
conn.close()
return data if data else None
except Exception as e:
print("Error membaca database:", e)
return None
def hitung_status_gizi(berat, tinggi):
"""Hitung IMT dan status gizi berdasarkan berat & tinggi."""
try:
tinggi_m = tinggi / 100 # cm -> meter
imt = berat / (tinggi_m ** 2)
if imt < 18.5:
kategori = "Kurus"
elif 18.5 <= imt < 25:
kategori = "Normal"
elif 25 <= imt < 30:
kategori = "Gemuk"
else:
kategori = "Obesitas"
return imt, kategori
except ZeroDivisionError:
return None, "Tinggi tidak valid"
def show_sub_menu_status_gizi(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
# Bersihkan frame
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Status Gizi", font=("Arial", 18, "bold"),
bg="green", fg="orange", pady=10).pack(pady=20)
# Frame untuk hasil dari database
frame_db = tk.LabelFrame(root_frame, text="Berdasarkan Data dari Database", font=("Arial", 12, "bold"))
frame_db.pack(pady=10, padx=10, fill="x")
hasil_db_label = tk.Label(frame_db, text="", font=("Arial", 12), justify="left")
hasil_db_label.pack(padx=10, pady=10, anchor="w")
# Ambil dan tampilkan hasil dari database
data_db = ambil_data_dari_db()
if data_db:
berat, tinggi = data_db
imt, kategori = hitung_status_gizi(berat, tinggi)
hasil_db_label.config(
text=f"Berat Badan : {berat} kg\nTinggi Badan : {tinggi} cm\nIMT : {imt:.2f}\nStatus Gizi : {kategori}"
)
else:
hasil_db_label.config(text="Belum ada data di database.")
# Separator
tk.Label(root_frame, text="").pack(pady=5)
# Frame untuk hitung manual
frame_manual = tk.LabelFrame(root_frame, text="Hitung Manual", font=("Arial", 12, "bold"))
frame_manual.pack(pady=10, padx=10, fill="x")
# Input manual
tk.Label(frame_manual, text="Berat Badan (kg):", font=("Arial", 12)).grid(row=0, column=0, sticky="w", padx=5, pady=5)
entry_berat = tk.Entry(frame_manual, font=("Arial", 12))
entry_berat.grid(row=0, column=1, padx=5, pady=5)
tk.Label(frame_manual, text="Tinggi Badan (cm):", font=("Arial", 12)).grid(row=1, column=0, sticky="w", padx=5, pady=5)
entry_tinggi = tk.Entry(frame_manual, font=("Arial", 12))
entry_tinggi.grid(row=1, column=1, padx=5, pady=5)
# Label hasil manual
hasil_manual_label = tk.Label(frame_manual, text="", font=("Arial", 12), justify="left", fg="blue")
hasil_manual_label.grid(row=3, column=0, columnspan=2, pady=10)
def proses_hitung_manual():
try:
berat = float(entry_berat.get())
tinggi = float(entry_tinggi.get())
imt, kategori = hitung_status_gizi(berat, tinggi)
if imt:
hasil_manual_label.config(
text=f"IMT : {imt:.2f}\nStatus Gizi : {kategori}"
)
else:
hasil_manual_label.config(text="Tinggi tidak valid.")
# Bersihkan entry
entry_berat.delete(0, tk.END)
entry_tinggi.delete(0, tk.END)
except ValueError:
messagebox.showwarning("Validasi", "Masukkan angka yang benar untuk berat dan tinggi.")
# Tombol hitung manual
tk.Button(frame_manual, text="Hitung Status Gizi", font=("Arial", 12),
bg="#4CAF50", fg="white", command=proses_hitung_manual).grid(row=2, column=0, columnspan=2, pady=10)
# 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=20)
✅ Perubahan yang saya buat:
- Query database sudah pakai
SELECT berat, tinggi. - Hasil dari database langsung tampil di layar.
- Ada bagian hitung manual dengan entry di samping label.
- Setelah tombol ditekan, hasil langsung tampil di layar & entry dibersihkan.
Kalau mau, saya bisa tambahkan validasi otomatis supaya kalau di database berat/tinggi kosong atau 0, bagian database tidak error tapi memberi pesan.
Mau saya tambahkan validasinya juga?
Kategori yang dihasilkan berdasarkan hitungan IMT dan Status Gizi berdasarkan dari database, buatkan warna teks IMT dan Status Gizi beserta nilainya buat berwarna biru.
Oke, berarti kita akan modifikasi bagian hasil dari database supaya nilai IMT dan Status Gizi tampil berwarna biru, sementara label “Berat Badan” dan “Tinggi Badan” tetap warna hitam biasa.
Berikut perbaikannya di file sub_menu_status_gizi.py:
import tkinter as tk
from tkinter import messagebox
import sqlite3
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def ambil_data_dari_db():
"""Ambil data berat dan tinggi terakhir dari database."""
try:
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
cursor.execute("SELECT berat, tinggi FROM data_diri ORDER BY id DESC LIMIT 1")
data = cursor.fetchone()
conn.close()
return data if data else None
except Exception as e:
print("Error membaca database:", e)
return None
def hitung_status_gizi(berat, tinggi):
"""Hitung IMT dan status gizi berdasarkan berat & tinggi."""
try:
tinggi_m = tinggi / 100 # cm -> meter
imt = berat / (tinggi_m ** 2)
if imt < 18.5:
kategori = "Kurus"
elif 18.5 <= imt < 25:
kategori = "Normal"
elif 25 <= imt < 30:
kategori = "Gemuk"
else:
kategori = "Obesitas"
return imt, kategori
except ZeroDivisionError:
return None, "Tinggi tidak valid"
def show_sub_menu_status_gizi(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
# Bersihkan frame
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Status Gizi", font=("Arial", 18, "bold"),
bg="green", fg="orange", pady=10).pack(pady=20)
# Frame untuk hasil dari database
frame_db = tk.LabelFrame(root_frame, text="Berdasarkan Data dari Database", font=("Arial", 12, "bold"))
frame_db.pack(pady=10, padx=10, fill="x")
# Ambil data database
data_db = ambil_data_dari_db()
if data_db:
berat, tinggi = data_db
imt, kategori = hitung_status_gizi(berat, tinggi)
# Berat & Tinggi
tk.Label(frame_db, text=f"Berat Badan : {berat} kg", font=("Arial", 12)).pack(anchor="w", padx=10, pady=2)
tk.Label(frame_db, text=f"Tinggi Badan : {tinggi} cm", font=("Arial", 12)).pack(anchor="w", padx=10, pady=2)
# IMT (warna biru)
tk.Label(frame_db, text=f"IMT : {imt:.2f}", font=("Arial", 12, "bold"), fg="blue").pack(anchor="w", padx=10, pady=2)
# Status Gizi (warna biru)
tk.Label(frame_db, text=f"Status Gizi : {kategori}", font=("Arial", 12, "bold"), fg="blue").pack(anchor="w", padx=10, pady=2)
else:
tk.Label(frame_db, text="Belum ada data di database.", font=("Arial", 12)).pack(anchor="w", padx=10, pady=5)
# Frame untuk hitung manual
frame_manual = tk.LabelFrame(root_frame, text="Hitung Manual", font=("Arial", 12, "bold"))
frame_manual.pack(pady=10, padx=10, fill="x")
tk.Label(frame_manual, text="Berat Badan (kg):", font=("Arial", 12)).grid(row=0, column=0, sticky="w", padx=5, pady=5)
entry_berat = tk.Entry(frame_manual, font=("Arial", 12))
entry_berat.grid(row=0, column=1, padx=5, pady=5)
tk.Label(frame_manual, text="Tinggi Badan (cm):", font=("Arial", 12)).grid(row=1, column=0, sticky="w", padx=5, pady=5)
entry_tinggi = tk.Entry(frame_manual, font=("Arial", 12))
entry_tinggi.grid(row=1, column=1, padx=5, pady=5)
# Label hasil manual
hasil_manual_label = tk.Label(frame_manual, text="", font=("Arial", 12), justify="left")
hasil_manual_label.grid(row=3, column=0, columnspan=2, pady=10)
def proses_hitung_manual():
try:
berat = float(entry_berat.get())
tinggi = float(entry_tinggi.get())
imt, kategori = hitung_status_gizi(berat, tinggi)
if imt:
hasil_manual_label.config(
text=f"IMT : {imt:.2f}\nStatus Gizi : {kategori}",
fg="blue" # Hasil manual juga warna biru
)
else:
hasil_manual_label.config(text="Tinggi tidak valid.", fg="red")
entry_berat.delete(0, tk.END)
entry_tinggi.delete(0, tk.END)
except ValueError:
messagebox.showwarning("Validasi", "Masukkan angka yang benar untuk berat dan tinggi.")
tk.Button(frame_manual, text="Hitung Status Gizi", font=("Arial", 12),
bg="#4CAF50", fg="white", command=proses_hitung_manual).grid(row=2, column=0, columnspan=2, pady=10)
# 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=20)
🔹 Perubahan yang saya buat:
- Nilai IMT dan Status Gizi dari database sekarang tampil dengan warna biru.
- Bagian hitung manual juga akan menampilkan hasilnya dengan warna biru supaya konsisten.
- Format tetap rapi: berat dan tinggi tetap hitam, IMT & Status Gizi saja yang biru.
Kalau mau, saya bisa bikin warna berbeda untuk tiap kategori (misalnya hijau untuk normal, kuning untuk gemuk, merah untuk obesitas).
Mau saya buat begitu juga?
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 tkinter import ttk
from sub_menu_data_diri import show_sub_menu_data_diri
from sub_menu_berat_tinggi_badan import show_sub_menu_berat_tinggi_badan
from sub_menu_indeks_massa_tubuh import show_sub_menu_indeks_massa_tubuh
from sub_menu_riwayat_kesehatan import show_sub_menu_riwayat_kesehatan
from sub_menu_kebutuhan_kalori import show_sub_menu_kebutuhan_kalori
from sub_menu_status_gizi import show_sub_menu_status_gizi
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
tk.Label(
root_frame,
text="Profil Kesehatan",
font=("Arial", 18, "bold"),
bg="green",
fg="orange",
padx=10,
pady=10
).pack(pady=20)
# Daftar submenu sebagai list tuple: (teks tombol, fungsi yang dipanggil)
submenus = [
("Data Diri", show_sub_menu_data_diri),
("Berat & Tinggi Badan", show_sub_menu_berat_tinggi_badan),
# Tambahkan submenu lain di sini, contoh:
# ("Kalori Harian", show_sub_menu_kalori_harian),
# ("Riwayat BMI", show_sub_menu_riwayat_bmi),
("Indeks Massa Tubuh \n(IMT)", show_sub_menu_indeks_massa_tubuh), # Tambahkan ini
("Riwayat Kesehatan", show_sub_menu_riwayat_kesehatan),
("Kebutuhan Kalori Harian", show_sub_menu_kebutuhan_kalori),
("Status Gizi", show_sub_menu_status_gizi),
]
# Buat tombol-tombol sub menu
for teks, fungsi in submenus:
tk.Button(
root_frame,
text=teks,
font=("Arial", 12),
bg="light blue",
fg="black",
command=lambda f=fungsi: f(root_frame)
).pack(pady=10)
# Tambahkan separator antar tombol (kecuali terakhir)
ttk.Separator(root_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# 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_status_gizi.py
Kode programnya adalah berikut:
# Sub Menu Status Gizi
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/data_diri.db"
def ambil_data_dari_db():
"""Ambil data berat dan tinggi terakhir dari database."""
try:
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
cursor.execute("SELECT berat, tinggi FROM data_diri ORDER BY id DESC LIMIT 1")
data = cursor.fetchone()
conn.close()
return data if data else None
except Exception as e:
print("Error membaca database:", e)
return None
def hitung_status_gizi(berat, tinggi):
"""Hitung IMT dan status gizi berdasarkan berat & tinggi."""
try:
tinggi_m = tinggi / 100 # cm -> meter
imt = berat / (tinggi_m ** 2)
if imt < 18.5:
kategori = "Kurus"
elif 18.5 <= imt < 25:
kategori = "Normal"
elif 25 <= imt < 30:
kategori = "Gemuk"
else:
kategori = "Obesitas"
return imt, kategori
except ZeroDivisionError:
return None, "Tinggi tidak valid"
def show_sub_menu_status_gizi(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan
# Bersihkan frame
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Status Gizi", font=("Arial", 18, "bold"),
bg="green", fg="orange", pady=10).pack(pady=20)
# Frame untuk hasil dari database
frame_db = tk.LabelFrame(root_frame, text="Berdasarkan Data dari Database", font=("Arial", 12, "bold"))
frame_db.pack(pady=10, padx=10, fill="x")
# Ambil data database
data_db = ambil_data_dari_db()
if data_db:
berat, tinggi = data_db
imt, kategori = hitung_status_gizi(berat, tinggi)
# Berat & Tinggi
tk.Label(frame_db, text=f"Berat Badan : {berat} kg", font=("Arial", 12)).pack(anchor="w", padx=10, pady=2)
tk.Label(frame_db, text=f"Tinggi Badan : {tinggi} cm", font=("Arial", 12)).pack(anchor="w", padx=10, pady=2)
# IMT (warna biru)
tk.Label(frame_db, text=f"IMT : {imt:.2f}", font=("Arial", 12, "bold"), fg="blue").pack(anchor="w", padx=10, pady=2)
# Status Gizi (warna biru)
tk.Label(frame_db, text=f"Status Gizi : {kategori}", font=("Arial", 12, "bold"), fg="blue").pack(anchor="w", padx=10, pady=2)
else:
tk.Label(frame_db, text="Belum ada data di database.", font=("Arial", 12)).pack(anchor="w", padx=10, pady=5)
# Tambahkan separator antar tombol (kecuali terakhir)
ttk.Separator(root_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# Frame untuk hitung manual
frame_manual = tk.LabelFrame(root_frame, text="Hitung Manual", font=("Arial", 12, "bold"))
frame_manual.pack(pady=10, padx=10, fill="x")
tk.Label(frame_manual, text="Berat Badan (kg):", font=("Arial", 12)).grid(row=0, column=0, sticky="w", padx=5, pady=5)
entry_berat = tk.Entry(frame_manual, font=("Arial", 12))
entry_berat.grid(row=0, column=1, padx=5, pady=5)
tk.Label(frame_manual, text="Tinggi Badan (cm):", font=("Arial", 12)).grid(row=1, column=0, sticky="w", padx=5, pady=5)
entry_tinggi = tk.Entry(frame_manual, font=("Arial", 12))
entry_tinggi.grid(row=1, column=1, padx=5, pady=5)
# Label hasil manual
hasil_manual_label = tk.Label(frame_manual, text="", font=("Arial", 12), justify="left")
hasil_manual_label.grid(row=3, column=0, columnspan=2, pady=10)
def proses_hitung_manual():
try:
berat = float(entry_berat.get())
tinggi = float(entry_tinggi.get())
imt, kategori = hitung_status_gizi(berat, tinggi)
if imt:
hasil_manual_label.config(
text=f"IMT : {imt:.2f}\nStatus Gizi : {kategori}",
fg="blue" # Hasil manual juga warna biru
)
else:
hasil_manual_label.config(text="Tinggi tidak valid.", fg="red")
entry_berat.delete(0, tk.END)
entry_tinggi.delete(0, tk.END)
except ValueError:
messagebox.showwarning("Validasi", "Masukkan angka yang benar untuk berat dan tinggi.")
# Tambahkan separator antar tombol (kecuali terakhir)
ttk.Separator(root_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# Tombol hitung manual
tk.Button(frame_manual, text="Hitung Status Gizi", font=("Arial", 12),
bg="#4CAF50", fg="white", command=proses_hitung_manual).grid(row=2, column=0, columnspan=2, pady=10)
# Tambahkan separator antar tombol (kecuali terakhir)
ttk.Separator(root_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# 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=20)
Bersambung Ke: Konten Sub Menu "Kondisi Khusus"
Comments
Post a Comment