fork download
  1. /* package whatever; // don't place package name! */
  2.  
  3. import java.util.*;
  4. import java.lang.*;
  5. import java.io.*;
  6.  
  7. /* Name of the class has to be "Main" only if the class is public. */
  8. class Ideone
  9. {
  10. public static void main (String[] args) throws java.lang.Exception
  11. {
  12. // your code goes here
  13. }
  14. }
Success #stdin #stdout 0.06s 54568KB
stdin
import tkinter as tk
from tkinter import ttk
import math

class SoundWaveApp:
    def __init__(self, root):
        self.root = root
        self.root.title("소리의 3요소 파동 실험실 (과학 수행평가)")
        self.root.geometry("900x650")
        self.root.configure(bg="#f0f4f8")

        # 데이터 저장용 변수
        self.amplitude = 50   # 초기 진폭 (소리 크기)
        self.frequency = 2   # 초기 진동수 (소리 높낮이)
        self.instrument = "실로폰" # 초기 악기 (소리 맵시)
        self.captured_waves = [] # 캡처된 파동 저장 리스트

        self.setup_ui()
        self.draw_wave()

    def setup_ui(self):
        # --- 상단 타이틀 ---
        title_label = tk.Label(self.root, text="🔊 소리의 성질 및 파동 비교 프로그램", font=("맑은 고딕", 18, "bold"), bg="#f0f4f8", fg="#333333")
        title_label.pack(pady=10)

        # 메인 프레임 (좌우 분할)
        main_frame = tk.Frame(self.root, bg="#f0f4f8")
        main_frame.pack(fill=tk.BOTH, expand=True, px=10, py=5)

        # --- 왼쪽 프레임: 조작 및 실시간 그래프 ---
        left_frame = tk.Frame(main_frame, bg="#f0f4f8")
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, px=10)

        # 1. 실시간 그래프 캔버스
        self.canvas = tk.Canvas(left_frame, width=500, height=250, bg="white", highlightthickness=1, highlightbackground="#cccccc")
        self.canvas.pack(pady=5)

        # 2. 제어판 프레임
        control_frame = tk.LabelFrame(left_frame, text="🎛️ 파동 제어판", font=("맑은 고딕", 11, "bold"), bg="#ffffff", px=15, py=10)
        control_frame.pack(fill=tk.X, pady=10)

        # 악기 선택 (소리의 맵시 - 파형 결정)
        tk.Label(control_frame, text="🎵 악기 선택 (음색/파형):", bg="#ffffff", font=("맑은 고딕", 10)).grid(row=0, column=0, sticky="w", pady=5)
        self.inst_combo = ttk.Combobox(control_frame, values=["실로폰 (정현파)", "리코더 (복합파)", "드럼 (맥동파)"], state="readonly", width=18)
        self.inst_combo.current(0)
        self.inst_combo.grid(row=0, column=1, sticky="w", pady=5)
        self.inst_combo.bind("<<ComboboxSelected>>", self.on_inst_change)

        # 소리 세기 조절 (진폭)
        tk.Label(control_frame, text="🔊 소리 세기 (진폭):", bg="#ffffff", font=("맑은 고딕", 10)).grid(row=1, column=0, sticky="w", pady=5)
        self.amp_slider = tk.Scale(control_frame, from_=10, to=100, orientation=tk.HORIZONTAL, bg="#ffffff", highlightthickness=0, command=self.on_amp_change)
        self.amp_slider.set(self.amplitude)
        self.amp_slider.grid(row=1, column=1, fill=tk.X, pady=5)

        # 소리 높낮이 조절 (진동수)
        tk.Label(control_frame, text="🎼 소리 높낮이 (진동수):", bg="#ffffff", font=("맑은 고딕", 10)).grid(row=2, column=0, sticky="w", pady=5)
        self.freq_slider = tk.Scale(control_frame, from_=1, to=5, resolution=0.5, orientation=tk.HORIZONTAL, bg="#ffffff", highlightthickness=0, command=self.on_freq_change)
        self.freq_slider.set(self.frequency)
        self.freq_slider.grid(row=2, column=1, fill=tk.X, pady=5)

        # 캡처 버튼
        capture_btn = tk.Button(left_frame, text="📸 현재 파동 캡처하기", font=("맑은 고딕", 11, "bold"), bg="#4CAF50", fg="white", reply=10, command=self.capture_wave)
        capture_btn.pack(fill=tk.X, pady=5)


        # --- 오른쪽 프레임: 캡처 리스트 및 중첩 비교 그래프 ---
        right_frame = tk.Frame(main_frame, bg="#f0f4f8")
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, px=10)

        # 1. 중첩 비교 그래프 캔버스
        tk.Label(right_frame, text="🔄 파동 중첩 비교 (겹쳐보기)", font=("맑은 고딕", 11, "bold"), bg="#f0f4f8").pack(anchor="w")
        self.compare_canvas = tk.Canvas(right_frame, width=320, height=200, bg="#222222", highlightthickness=1)
        self.compare_canvas.pack(pady=5)

        # 2. 캡처된 기록 리스트박스
        tk.Label(right_frame, text="📋 캡처된 파동 목록 (최대 3개)", font=("맑은 고딕", 11, "bold"), bg="#f0f4f8").pack(anchor="w", pady=(10, 0))
        self.history_box = tk.Listbox(right_frame, height=6, font=("맑은 고딕", 10))
        self.history_box.pack(fill=tk.BOTH, expand=True, pady=5)

        # 초기화 버튼
        reset_btn = tk.Button(right_frame, text="🗑️ 캡처 초기화", font=("맑은 고딕", 10), bg="#f44336", fg="white", command=self.reset_captures)
        reset_btn.pack(fill=tk.X, pady=5)

    # 파동 수학적 계산 및 그리기
    def calculate_wave_points(self, amp, freq, inst, width, height):
        points = []
        center_y = height / 2
        
        for x in range(0, width, 2):
            # 기본 진동식 (실로폰: 깨끗한 사인파)
            theta = (x / width) * 2 * math.pi * freq
            y_offset = math.sin(theta)
            
            # 악기별 파형(맵시) 변형
            if "리코더" in inst:
                # 고조파를 섞어 뾰족한 복합파 생성
                y_offset += 0.3 * math.sin(3 * theta)
            elif "드럼" in inst:
                # 지수함수를 곱해 소리가 감쇄하는 형태 표현
                y_offset = math.sin(theta * 1.5) * math.exp(-x / (width * 0.6))
            
            y = center_y - (y_offset * amp)
            points.append((x, y))
        return points

    def draw_wave(self):
        # 1. 실시간 캔버스 그리기
        self.canvas.delete("all")
        w, h = 500, 250
        
        # 모눈종이 가이드라인
        self.canvas.create_line(0, h/2, w, h/2, fill="#aaaaaa", dash=(4, 4))
        for x in range(0, w, 40):
            self.canvas.create_line(x, 0, x, h, fill="#f0f0f0")
        for y in range(0, h, 40):
            self.canvas.create_line(0, y, w, y, fill="#f0f0f0")

        # 파동선 그리기
        points = self.calculate_wave_points(self.amplitude, self.frequency, self.instrument, w, h)
        for i in range(len(points) - 1):
            self.canvas.create_line(points[i][0], points[i][1], points[i+1][0], points[i+1][1], fill="#007BFF", width=3)
            
        # 상태 텍스트 표시
        info_text = f"선택된 악기: {self.instrument} | 진폭(크기): {self.amplitude} | 진동수(높낮이): {self.frequency}Hz"
        self.canvas.create_text(15, h - 15, text=info_text, anchor="w", font=("맑은 고딕", 10, "bold"), fill="#333333")

    def draw_compare_canvas(self):
        # 2. 중첩 캔버스 그리기
        self.compare_canvas.delete("all")
        w, h = 320, 200
        self.compare_canvas.create_line(0, h/2, w, h/2, fill="#555555", dash=(2, 2))

        colors = ["#FF5722", "#4CAF50", "#E91E63"] # 캡처 파동 색상 (주황, 초록, 핑크)
        
        for idx, wave in enumerate(self.captured_waves):
            pts = self.calculate_wave_points(wave['amp'], wave['freq'], wave['inst'], w, h)
            for i in range(len(pts) - 1):
                self.compare_canvas.create_line(pts[i][0], pts[i][1], pts[i+1][0], pts[i+1][1], fill=colors[idx], width=2)

    # 이벤트 함수들
    def on_amp_change(self, val):
        self.amplitude = int(val)
        self.draw_wave()

    def on_freq_change(self, val):
        self.frequency = float(val)
        self.draw_wave()

    def on_inst_change(self, event):
        self.instrument = self.inst_combo.get()
        self.draw_wave()

    def capture_wave(self):
        if len(self.captured_waves) >= 3:
            self.captured_waves.pop(0) # 3개 넘으면 제일 오래된 것 삭제
            self.history_box.delete(0)

        # 현재 상태 저장
        wave_data = {
            'inst': self.instrument,
            'amp': self.amplitude,
            'freq': self.frequency
        }
        self.captured_waves.append(wave_data)
        
        # 리스트박스에 표시
        colors_text = ["🔴", "🟢", "🔵"]
        idx = len(self.captured_waves) - 1
        display_text = f"{colors_text[idx]} [{wave_data['inst'].split()[0]}] 진폭:{wave_data['amp']} / 진동수:{wave_data['freq']}"
        self.history_box.insert(tk.END, display_text)
        
        # 중첩 그래프 업데이트
        self.draw_compare_canvas()

    def reset_captures(self):
        self.captured_waves = []
        self.history_box.delete(0, tk.END)
        self.compare_canvas.delete("all")

if __name__ == "__main__":
    root = tk.Tk()
    app = SoundWaveApp(root)
    root.mainloop()
stdout
Standard output is empty