<구현이 필요한 기능>
•
애플리케이션 GUI에 사용자 프로필 정보 표출
•
사용자가 먼저 대화를 시작하는 기능
문제 해결 과정
1.
어떻게 GUI를 구성하고, Maria DB로부터 가져온 데이터를 표현할 것인가?
a.
우선, user_db에 사용자 이미지 데이터를 저장할 수 있도록 수정해보자.
USE user_data;
ALTER TABLE users
ADD COLUMN user_image BLOB;
Python
복사
b.
그렇다면 user_id =1인 row에 user_image를 샘플 이미지로 저장해보자.
CODE
c.
DialogueSessionManager에서 get_user_data 함수에서 query에 user_image 추가하기
query = """
SELECT name, gender, date_of_birth, address,
disability_type, disability_grade, special_notes
,user_image
FROM users
WHERE user_id = ?
"""
Python
복사
d.
WireFrame
상단 부분을 위와 같이 적용하고, 하단에 이전에 기능한 부분을 추가하는 방식으로 구현해보기
source code
b.
현재 대화 모듈과 GUI 표현 기능이 모두 동작하지만, 대화 모듈이 모두 끝나야 사용자 프로필을 GUI에 표시되는 문제점이 존재한다.
해결되지 않은 점
GUI에 먼저 사용자 프로필을 보여주고, 대화 모듈을 실행하고 싶으나,
대화 모듈이 종료된 후, GUI에 사용자 프로필을 보여주는 상황임
Fetch 수정하기 전 application.py
import sys
import requests
import base64
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QComboBox, QLineEdit, QPushButton, QGroupBox, QGridLayout)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
"""
# YeoJun's Memo
<QVBoxLayout>
: 위젯을 수직으로 배치(세로)
<QHBoxLayout>
: 위젯을 수평으로 배치(가로)
"""
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.user_data={}
self.initUI()
def initUI(self):
self.setWindowTitle('Demo Test')
self.setGeometry(300, 300, 1000, 700)
# 메인 레이아웃 설정
self.layout = QVBoxLayout()
# 사용자 프로필 그룹 (이미지)
profile_group = QGroupBox("User Profile")
profile_layout = QVBoxLayout()
self.image_label = QLabel(self)
self.image_label.setFixedSize(200, 200)
profile_layout.addWidget(self.image_label, alignment=Qt.AlignCenter)
profile_group.setLayout(profile_layout)
#---------------------------------------
#---------------------------------------
# 사용자 정보 그룹
info_group = QGroupBox("User Information")
info_layout = QVBoxLayout()
labels = ['Name', 'Gender', 'Date of Birth', 'Address', 'Disability Type', 'Disability Grade', 'Special Notes']
self.info_labels={}
for label in labels:
lbl = QLabel(f"{label}: ")
lbl.setWordWrap(True)
# https://wikidocs.net/33889 참조
lbl.setStyleSheet("""
color: #4B8B3B; /* 부드러운 녹색 텍스트 */
border: 1px solid #A9A9A9; /* 연한 회색 테두리 */
background-color: #F5F5F5; /* 연한 회색 배경 */
padding: 8px; /* 텍스트와 테두리 간의 여백 */
border-radius: 5px; /* 모서리를 둥글게 */
font-weight: bold; /* 텍스트를 굵게 */
""")
self.info_labels[label] = lbl
info_layout.addWidget(lbl)
info_group.setLayout(info_layout)
# 상단 레이아웃: 왼쪽 - 프로필, 오른쪽 - 사용자 정보
self.top_layout = QHBoxLayout()
self.top_layout.addWidget(profile_group, 1)
self.top_layout.addWidget(info_group, 2)
self.layout.addLayout(self.top_layout)
# ID Input 그룹
input_group = QGroupBox("Input Field")
input_layout = QHBoxLayout()
# 왼쪽: User Selector와 Event Selector 그룹
selector_group = QGroupBox("Selection")
selector_layout = QVBoxLayout()
self.user_selector = QComboBox(self)
self.user_selector.addItems(["Select User", "홍길동", "김철수", "정다은"])
self.user_selector.currentIndexChanged.connect(self.update_user_id)
self.event_selector = QComboBox(self)
self.event_selector.addItems(["Select Event",
"계속해서 자기 머리를 반복해서 때림",
"비정상적으로 소리 지르며 불안정한 행동을 보임",
"가스레인지 사용 중인데 안전 확인이 필요함",
"정해진 시간에 약을 복용하지 않아 알림이 필요함",
"오랜 시간 동안 움직이지 않고 특정 활동에 과몰입하고 있음"])
self.event_selector.currentIndexChanged.connect(self.update_event_id)
selector_layout.addWidget(QLabel("Select User"))
selector_layout.addWidget(self.user_selector)
selector_layout.addSpacing(10)
selector_layout.addWidget(QLabel("Select Event"))
selector_layout.addWidget(self.event_selector)
selector_group.setLayout(selector_layout)
# 오른쪽: User ID 및 Event ID와 버튼 그룹
input_fields_group = QGroupBox("ID Input")
input_fields_layout = QVBoxLayout()
self.user_id_input = QLineEdit(self)
self.user_id_input.setPlaceholderText("Enter User ID (auto-filled if selected)")
self.event_id_input = QLineEdit(self)
self.event_id_input.setPlaceholderText("Enter Event ID (auto-filled if selected)")
self.btn = QPushButton('Send Request', self)
self.btn.setToolTip('<b>Send the request to the server </b> with User ID and Event ID')
self.btn.clicked.connect(self.send_request)
input_fields_layout.addWidget(QLabel("User ID"))
input_fields_layout.addWidget(self.user_id_input)
input_fields_layout.addWidget(QLabel("Event ID"))
input_fields_layout.addWidget(self.event_id_input)
input_fields_layout.addWidget(self.btn, alignment=Qt.AlignRight)
input_fields_group.setLayout(input_fields_layout)
# ID Input 그룹에 왼쪽과 오른쪽 레이아웃 추가 (5:5 비율)
input_layout.addWidget(selector_group, 1)
input_layout.addWidget(input_fields_group, 1)
input_group.setLayout(input_layout)
self.layout.addWidget(input_group)
# result 그룹
result_group = QGroupBox("Result")
result_layout = QVBoxLayout()
self.result_label = QLabel(self)
self.result_label.setWordWrap(True)
result_layout.addWidget(self.result_label)
result_group.setLayout(result_layout)
self.layout.addWidget(result_group)
# 메인 레이아웃 설정
self.setLayout(self.layout)
self.show()
def update_user_info(self):
self.info_labels['Name'].setText(f"{self.user_data.get('name', 'N/A')}")
self.info_labels['Gender'].setText(f"Gender: {self.user_data.get('gender', 'N/A')}")
self.info_labels['Date of Birth'].setText(f"Date of Birth: {self.user_data.get('date_of_birth', 'N/A')}")
self.info_labels['Address'].setText(f"Address: {self.user_data.get('address', 'N/A')}")
self.info_labels['Disability Type'].setText(f"Disability Type: {self.user_data.get('disability_type', 'N/A')}")
self.info_labels['Disability Grade'].setText(f"Disability Grade: {self.user_data.get('disability_grade', 'N/A')}")
self.info_labels['Special Notes'].setText(f"Special Notes: {self.user_data.get('special_notes', 'N/A')}")
if 'user_image' in self.user_data:
self.load_image(self.user_data['user_image'])
def load_image(self,image_data):
pixmap = QPixmap()
#이미지를 Base64로 Decoding하여 QLabel에 표시
image_data = base64.b64decode(image_data)
pixmap.loadFromData(image_data)
self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio))
def update_user_id(self):
user_id_mapping = {
"홍길동": "1",
"김철수": "20",
"정다은": "29"
}
selected_user = self.user_selector.currentText()
self.user_id_input.setText(user_id_mapping.get(selected_user, ""))
def update_event_id(self):
event_id_mapping = {
"계속해서 자기 머리를 반복해서 때림": "31",
"비정상적으로 소리 지르며 불안정한 행동을 보임": "8",
"가스레인지 사용 중인데 안전 확인이 필요함": "11",
"정해진 시간에 약을 복용하지 않아 알림이 필요함": "9",
"오랜 시간 동안 움직이지 않고 특정 활동에 과몰입하고 있음" : "63"
}
selected_event = self.event_selector.currentText()
self.event_id_input.setText(event_id_mapping.get(selected_event, ""))
def send_request(self):
user_id = self.user_id_input.text()
event_id = self.event_id_input.text()
if user_id and event_id:
try:
user_info_url = f"http://127.0.0.1:5000/user/{user_id}"
user_response = requests.get(user_info_url)
if user_response.status_code == 200:
self.user_data = user_response.json()
self.update_user_info()
else:
self.result_label.setText("사용자 정보를 가져오는 도중에 에러 발생")
return
#--------------------------------
# 멀티 스레드로 구분해야 할 필요가 있음
#-------------------------------
# Flask 서버로 GET 요청을 보내기
url = f"http://127.0.0.1:5000/user/{user_id}/event/{event_id}"
response = requests.get(url)
if response.status_code == 200:
json_response = response.json()
self.result_label.setText(f"Response: {json_response}")
else:
error_message = response.json()
self.result_label.setText(f"Error : {error_message}")
except Exception as e:
self.result_label.setText(f"Exception occurred: {str(e)}")
else:
self.result_label.setText("해당 데이터를 찾을 수 없습니다. User ID와 Event ID를 다시 확인하고 입력해주세요.")
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
Python
복사












