Database 매뉴얼 · Chapter 8

버튼 이벤트 — ViewRun 핸들러

샘플의 모든 사용자 동작은 ViewRun.xms 의 6 개 클릭 핸들러 를 통해 시작됩니다. 각 핸들러는 한 줄로 Data:: 모듈 함수 호출만 하는 얇은 layer 라, 비즈니스 로직과 UI 이벤트가 깔끔하게 분리됩니다.

ViewRun (UI 이벤트)            Data (DB 비즈니스 로직)
─────────────────────────      ──────────────────────────
OnOpenClick    ───►           DB_Open()
OnAddClick     ───►           DB_InsertSample()
OnUpdateClick  ───►           DB_UpdateSelected()
OnModifyClick  ───►           DB_OpenModifyDlg() ──► GUI.ShowDialog → DB_UpdateModified()
OnDeleteClick  ───►           DB_DeleteSelected()
OnCloseClick   ───►           DB_Close()

1) 버튼 핸들러 표준 시그니처

QMachineStudio 의 클릭 핸들러는 모두 동일한 시그니처입니다.

FUNCTION OnXxxClick(string sender, int tag, array params)
{
   // sender : 버튼 컨트롤의 이름
   // tag    : 버튼의 Tag 속성값 (분류용)
   // params : 추가 인자 (대부분 사용 안 함)
 
   Data::DB_Xxx();
}

샘플의 6 개 핸들러는 모두 Data:: 함수를 호출하는 한 줄짜리 wrapper 입니다.

FUNCTION OnOpenClick   (string sender, int tag, array params) { Data::DB_Open();             }
FUNCTION OnAddClick    (string sender, int tag, array params) { Data::DB_InsertSample();     }
FUNCTION OnUpdateClick (string sender, int tag, array params) { Data::DB_UpdateSelected();   }
FUNCTION OnModifyClick (string sender, int tag, array params) { Data::DB_OpenModifyDlg();    }
FUNCTION OnDeleteClick (string sender, int tag, array params) { Data::DB_DeleteSelected();   }
FUNCTION OnCloseClick  (string sender, int tag, array params) { Data::DB_Close();            }

이 분리가 가져다주는 효과:

  • DB 함수만 단위 테스트 하면 충분 — UI 가 없어도 검증 가능
  • 같은 함수를 다른 화면(ViewMain) 또는 시퀀스에서 그대로 재사용 가능
  • 디버깅 시 어디서 막혔는지(이벤트인지 DB 호출인지) 빠르게 분리됨

2) 버튼과 핸들러 연결

ViewRun 의 디자인 모드에서 각 버튼의 Click 이벤트 → Function 이름 을 다음과 같이 지정합니다.

버튼(Caption)컨트롤 이름Click 이벤트 함수
OpenBtnOpenOnOpenClick
AddBtnAddOnAddClick
UpdateBtnUpdateOnUpdateClick
ModifyBtnModifyOnModifyClick
DeleteBtnDeleteOnDeleteClick
CloseBtnCloseOnCloseClick

(sender, tag, params) 파라미터는 항상 받아두기만 하고 본문에서는 무시해도 됩니다. 같은 핸들러를 여러 버튼이 공유하고 tag 로 분기하는 경우에만 의미가 생깁니다.


3) ModifyDlg 흐름 — 두 단계 호출

Modify 버튼은 다른 핸들러와 달리 다이얼로그 모달 호출 + 결과 분기 가 들어갑니다. 실제 분기는 Data::DB_OpenModifyDlg() 안에 들어 있어 ViewRun 측은 여전히 한 줄입니다.

[Modify 버튼 클릭]


ViewRun.OnModifyClick


Data.DB_OpenModifyDlg

       ├─ 1. SELECT 행 → Edit* 필드 복사
       ├─ 2. GUI.ShowDialog("ModifyDlg")
       │      │
       │      ├─ true  (OK)     ──► DB_UpdateModified() → DB_Refresh()
       │      └─ false (Cancel) ──► 그대로 종료


   반환

GUI.ShowDialog호출 시점에 블록되므로 — 다이얼로그가 닫힐 때까지 다음 줄은 실행되지 않습니다. 즉, OnModifyClick 의 한 줄 호출이 끝나는 시점은 사용자가 OK 또는 Cancel 을 누른 뒤 입니다.

Dialog 내부 이벤트

ModifyDlg.xms 자체에는 비즈니스 로직이 들어 있지 않습니다 — 진단용 로그만 있습니다.

FUNCTION OnShow()
{
   // 다이얼로그 표시 직전 - 편집 필드는 호출 측에서 이미 채움
   Log($"ModifyDlg OnShow : id={Data::EditId} order_no={Data::EditOrderNo}");
}
 
FUNCTION OnHide()
{
   // 다이얼로그 종료 직후
}

OK / Cancel 두 버튼은 단지 DialogResult 만 설정하면 되고, 실제 UPDATE 는 호출 측 DB_OpenModifyDlgShowDialog 의 반환값으로 분기해 처리합니다. 다이얼로그가 자기 자신의 비즈니스 로직을 알지 못해도 되는 구조 — 재사용성에 유리합니다.


4) Init / Mon / Event 와의 관계

샘플 프로젝트는 다음 모듈도 함께 갖고 있습니다 — DB 와 직접 관련은 없지만 일반 자동화 프로젝트의 표준 구조라 잠깐 짚고 넘어갑니다.

모듈타입용도
InitInit부팅 시 1 회 실행 — 데이터 초기화, 타워램프 세팅
MonMonitor주기적 모니터링 — Door / IO / 안전 등
EventEvent이벤트(통신, 외부 신호) 수신
DataMonitor이번 튜토리얼의 주인공 — DB 함수 보유
WorkSequence메인 시퀀스 (DB 와 무관한 모듈)

DB 작업을 Data 모듈에 넣은 이유는 장비 시퀀스(Work) 와 분리 해 두기 위해서입니다. DB 가 잠시 끊겨도 시퀀스는 계속 돌아야 하고, 시퀀스 측은 Data::DB_* 함수만 호출하면 됩니다.

다음 챕터로

이제 백업과 운영 — WAL 모드, BackupFolder, 자동 백업 옵션을 정리합니다.