PYTHON GUI

[ PySide6 ] 천 단위 쉼표 자동 추가 QLineEdit 만들기

나루하루001 2025. 6. 1. 23:05
반응형
목차
  1. 천 단위 쉼표 자동 입력의 필요성
  2. PySide6와 QLineEdit 기본 이해하기
  3. 입력 제한 설정: 숫자만 입력받기
  4. 천 단위 쉼표 자동 추가 기능 구현
  5. 커서 위치 유지하기
  6. 포커스 이벤트 처리하기
  7. 전체 코드 분석 및 활용 방법



천 단위 쉼표 자동 입력의 필요성

 

금액이나 큰 숫자를 다루는 애플리케이션을 개발할 때,

사용자 경험을 향상시키는 중요한 기능 중 하나가 바로 천 단위 쉼표 자동 추가 기능입니다.

 

예를 들어 '1000000'이라는 숫자보다

'1,000,000'으로 표시하는 것이 가독성이 훨씬 좋습니다.

 

이러한 기능은 금융 애플리케이션, 회계 프로그램, 판매 관리 시스템 등

숫자를 많이 다루는 다양한 소프트웨어에서 필수적입니다.

 

사용자가 직접 쉼표를 입력하게 하는 것보다 자동으로 처리해주면

입력 오류를 줄이고 사용자 경험을 크게 향상시킬 수 있습니다.

왜 천 단위 쉼표가 중요할까요?
큰 숫자를 읽을 때 천 단위 쉼표는 숫자의 크기를 직관적으로 파악하는 데 도움을 줍니다. 특히 금융 데이터나 통계 정보를 다룰 때, 사용자가 숫자의 규모를 빠르게 인식할 수 있도록 도와줍니다. 또한 국제 표준에 맞는 숫자 표기법을 따르는 것은 전문적인 애플리케이션 개발에 있어 기본적인 요소입니다.

이 글에서는 PySide6를 사용하여 사용자가 숫자를 입력할 때

자동으로 천 단위 쉼표를 추가해주는 QLineEdit 위젯을 구현하는 방법을 알아보겠습니다.

 

PySide6와 QLineEdit 기본 이해하기

 

PySide6는 Qt 프레임워크의 파이썬 바인딩으로,

크로스 플랫폼 GUI 애플리케이션을 개발할 수 있게 해주는 강력한 도구입니다.

 

QLineEdit은 PySide6에서 제공하는 한 줄 텍스트 입력 위젯으로, 사용자로부터 텍스트 입력을 받을 수 있습니다.

 

QLineEdit의 주요 기능

 

QLineEdit은 다음과 같은 다양한 기능을 제공합니다:

  • 텍스트 입력 및 편집: 사용자가 키보드로 텍스트를 입력하고 편집할 수 있습니다.
  • 입력 마스크: 특정 형식(예: 전화번호, 날짜 등)에 맞는 입력만 허용할 수 있습니다.
  • 유효성 검사(Validation): QValidator를 사용하여 입력값의 유효성을 검사할 수 있습니다.
  • 이벤트 처리: textChanged, editingFinished 등의 시그널을 통해 다양한 이벤트를 처리할 수 있습니다.
  • 스타일 및 모양 설정: 테두리, 배경색, 글꼴 등을 설정할 수 있습니다.

기본 QLineEdit 설정하기

 

먼저 기본적인 QLineEdit을 설정하는 코드를 살펴보겠습니다:


import sys
from PySide6.QtWidgets import QApplication, QWidget
from line_edit_test_ui import Ui_Form

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()
        
        # UI 설정
        self.ui = Ui_Form()
        self.ui.setupUi(self)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MyWidget()
    widget.show()
    sys.exit(app.exec())

 

위 코드는 Qt Designer로 만든 UI 파일을 불러와 기본적인 위젯을 설정하는 코드입니다.

이제 이 기본 코드에 천 단위 쉼표 자동 추가 기능을 구현해 보겠습니다.

 

입력 제한 설정: 숫자만 입력받기

 

천 단위 쉼표 자동 추가 기능을 구현하기 전에,

먼저 QLineEdit에 숫자만 입력할 수 있도록 제한해야 합니다.

 

이를 위해 PySide6의 QRegularExpressionValidator를 사용하겠습니다.

 

정규 표현식 Validator 설정하기

rx = QRegularExpression("^[0-9,]*$")
validator = QRegularExpressionValidator(rx)
self.ui.lineEdit.setValidator(validator)

 

위 코드에서 사용한 정규 표현식 "^[0-9,]*$"는 다음을 의미합니다:

  • ^: 문자열의 시작
  • [0-9,]: 숫자(0-9)와 쉼표(,)만 허용
  • *: 앞의 패턴이 0번 이상 반복될 수 있음
  • $: 문자열의 끝

이 정규 표현식은 숫자와 쉼표만 입력할 수 있도록 제한합니다.

쉼표를 허용하는 이유는 우리가 자동으로 쉼표를 추가할 것이기 때문입니다.

정규 표현식 이해하기
정규 표현식(Regular Expression)은 문자열의 패턴을 정의하는 강력한 도구입니다. 여기서는 간단히 숫자와 쉼표만 허용하는 패턴을 사용했지만, 정규 표현식을 더 복잡하게 구성하여 다양한 입력 형식(예: 이메일, 전화번호, 날짜 등)을 검증할 수 있습니다. 정규 표현식에 대해 더 알고 싶다면 온라인 정규 표현식 테스트 도구를 활용해 보세요.

 

천 단위 쉼표 자동 추가 기능 구현

 

이제 사용자가 숫자를 입력할 때마다 천 단위로 쉼표를 자동으로 추가하는 기능을 구현해 보겠습니다.

이를 위해 QLineEdit의 textChanged 시그널에 연결할 함수를 작성합니다.

 

textChanged 시그널 연결하기

self.ui.lineEdit.textChanged.connect(self.format_number)

 

위 코드는 QLineEdit의 텍스트가 변경될 때마다 format_number 함수를 호출하도록 설정합니다.

 

format_number 함수 구현하기


def format_number(self, text):
    """텍스트가 변경될 때 호출되어 1000단위 쉼표를 추가합니다."""
    if not text:
        return
        
    # 현재 커서 위치 저장
    cursor_pos = self.ui.lineEdit.cursorPosition()
    
    # 쉼표 제거
    text_without_commas = text.replace(',', '')
    
    # 숫자가 아닌 문자가 있으면 처리하지 않음
    if not text_without_commas.isdigit() and text_without_commas:
        return
        
    # 쉼표 추가 전 텍스트 길이
    old_len = len(text)
    
    # 1000단위 쉼표 추가
    if text_without_commas:
        number = int(text_without_commas)
        formatted_text = f"{number:,}"
        
        # 텍스트 변경 시그널 일시 차단
        self.ui.lineEdit.blockSignals(True)
        self.ui.lineEdit.setText(formatted_text)
        self.ui.lineEdit.blockSignals(False)
        
        # 새 텍스트 길이
        new_len = len(formatted_text)
        
        # 커서 위치 조정 (쉼표가 추가되었을 때 커서 위치 유지)
        diff = new_len - old_len
        self.ui.lineEdit.setCursorPosition(cursor_pos + diff)

 

위 함수는 다음과 같은 단계로 천 단위 쉼표를 자동으로 추가합니다:

  1. 입력된 텍스트가 비어있는지 확인합니다.
  2. 현재 커서 위치를 저장합니다.
  3. 입력된 텍스트에서 모든 쉼표를 제거합니다.
  4. 쉼표가 제거된 텍스트가 숫자인지 확인합니다.
  5. 숫자라면, 천 단위 쉼표를 추가한 새 텍스트를 생성합니다.
  6. QLineEdit의 텍스트를 새 텍스트로 설정합니다.
  7. 커서 위치를 적절히 조정합니다.
blockSignals의 중요성
blockSignals(True)를 호출하여 시그널을 일시적으로 차단하는 것은 매우 중요합니다. 이렇게 하지 않으면 setText()를 호출할 때 다시 textChanged 시그널이 발생하여 무한 루프에 빠질 수 있습니다. 작업이 완료된 후에는 반드시 blockSignals(False)를 호출하여 시그널을 다시 활성화해야 합니다.

 

반응형

커서 위치 유지하기

 

천 단위 쉼표 자동 추가 기능을 구현할 때 가장 까다로운 부분 중 하나는

사용자의 커서 위치를 적절하게 유지하는 것입니다.

 

사용자가 숫자를 입력하면 쉼표가 추가되면서 텍스트의 길이가 변하게 되고,

이에 따라 커서 위치도 조정해야 합니다.

 

커서 위치 조정 로직


# 쉼표 추가 전 텍스트 길이
old_len = len(text)

# ... 쉼표 추가 작업 ...

# 새 텍스트 길이
new_len = len(formatted_text)

# 커서 위치 조정 (쉼표가 추가되었을 때 커서 위치 유지)
diff = new_len - old_len
self.ui.lineEdit.setCursorPosition(cursor_pos + diff)

위 코드에서는 다음과 같은 방식으로 커서 위치를 조정합니다:

  1. 쉼표 추가 전 텍스트의 길이를 저장합니다.
  2. 쉼표가 추가된 후 텍스트의 길이를 계산합니다.
  3. 두 길이의 차이를 계산합니다.
  4. 원래 커서 위치에 이 차이를 더하여 새 커서 위치를 설정합니다.

이렇게 하면 사용자가 숫자를 입력할 때 커서가 갑자기 다른 위치로 이동하는 불편함 없이 자연스럽게 천 단위 쉼표가 추가됩니다.

사용자 경험 향상 팁
커서 위치 관리는 사용자 경험에 큰 영향을 미칩니다. 사용자가 입력하는 동안 커서가 예상치 못한 위치로 이동하면 혼란스럽고 불편함을 느낄 수 있습니다. 특히 숫자 입력 필드에서는 이러한 세부 사항에 주의를 기울여 사용자가 자연스럽게 입력할 수 있도록 해야 합니다.

 

포커스 이벤트 처리하기

 

사용자가 QLineEdit에서 포커스를 잃을 때(예: 다른 위젯을 클릭할 때)

최종적으로 형식을 맞추는 것이 좋습니다.

 

이를 위해 QLineEdit의 focusOutEvent를 오버라이드하여 처리합니다.

 

focusOutEvent 오버라이드하기


# 포커스 이벤트 연결
self.ui.lineEdit.focusOutEvent = self.on_focus_out

def on_focus_out(self, event):
    """포커스를 잃을 때 호출되어 최종적으로 형식을 맞춥니다."""
    text = self.ui.lineEdit.text()
    if text:
        # 쉼표 제거
        text_without_commas = text.replace(',', '')
        
        if text_without_commas:
            # 숫자로 변환 후 다시 포맷팅
            number = int(text_without_commas)
            formatted_text = f"{number:,}"
            self.ui.lineEdit.setText(formatted_text)
            
    # 기본 이벤트 처리
    super(MyWidget, self).focusOutEvent(event)

 

위 코드는 다음과 같은 작업을 수행합니다:

  1. QLineEdit의 focusOutEvent를 우리가 정의한 on_focus_out 함수로 대체합니다.
  2. 포커스를 잃을 때 현재 텍스트를 가져옵니다.
  3. 텍스트에서 쉼표를 제거합니다.
  4. 숫자로 변환한 후 다시 천 단위 쉼표를 추가합니다.
  5. 기본 focusOutEvent를 호출하여 원래의 이벤트 처리를 수행합니다.

이 기능은 사용자가 입력을 완료하고 다른 위젯으로 이동할 때 최종적으로 형식을 정리하는 데 유용합니다.

 

전체 코드 분석 및 활용 방법

 

이제 전체 코드를 살펴보고 어떻게 활용할 수 있는지 알아보겠습니다.


# -*- coding: utf-8 -*-

import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QRegularExpressionValidator
from PySide6.QtCore import QRegularExpression
from line_edit_test_ui import Ui_Form

class MyWidget(QWidget):
    def __init__(self):
        super().__init__()
        
        # UI 설정
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        
        # 숫자만 입력 가능하도록 validator 설정
        # 쉼표를 포함한 숫자 패턴을 허용 (쉼표는 자동으로 추가되기 때문)
        rx = QRegularExpression("^[0-9,]*$")
        validator = QRegularExpressionValidator(rx)
        self.ui.lineEdit.setValidator(validator)
        
        # 텍스트 변경 시그널 연결
        self.ui.lineEdit.textChanged.connect(self.format_number)
        
        # 포커스 이벤트 연결
        self.ui.lineEdit.focusOutEvent = self.on_focus_out
        
    def format_number(self, text):
        """텍스트가 변경될 때 호출되어 1000단위 쉼표를 추가합니다."""
        if not text:
            return
            
        # 현재 커서 위치 저장
        cursor_pos = self.ui.lineEdit.cursorPosition()
        
        # 쉼표 제거
        text_without_commas = text.replace(',', '')
        
        # 숫자가 아닌 문자가 있으면 처리하지 않음
        if not text_without_commas.isdigit() and text_without_commas:
            return
            
        # 쉼표 추가 전 텍스트 길이
        old_len = len(text)
        
        # 1000단위 쉼표 추가
        if text_without_commas:
            number = int(text_without_commas)
            formatted_text = f"{number:,}"
            
            # 텍스트 변경 시그널 일시 차단
            self.ui.lineEdit.blockSignals(True)
            self.ui.lineEdit.setText(formatted_text)
            self.ui.lineEdit.blockSignals(False)
            
            # 새 텍스트 길이
            new_len = len(formatted_text)
            
            # 커서 위치 조정 (쉼표가 추가되었을 때 커서 위치 유지)
            diff = new_len - old_len
            self.ui.lineEdit.setCursorPosition(cursor_pos + diff)
    
    def on_focus_out(self, event):
        """포커스를 잃을 때 호출되어 최종적으로 형식을 맞춥니다."""
        text = self.ui.lineEdit.text()
        if text:
            # 쉼표 제거
            text_without_commas = text.replace(',', '')
            
            if text_without_commas:
                # 숫자로 변환 후 다시 포맷팅
                number = int(text_without_commas)
                formatted_text = f"{number:,}"
                self.ui.lineEdit.setText(formatted_text)
                
        # 기본 이벤트 처리
        super(MyWidget, self).focusOutEvent(event)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = MyWidget()
    widget.show()
    sys.exit(app.exec())

위 코드는 PySide6를 사용하여 천 단위 쉼표 자동 추가 기능을 구현한 전체 예제입니다.

 

활용 방법

이 코드를 활용하는 방법은 다음과 같습니다:

  1. 기존 프로젝트에 통합: 위 코드의 format_number와 on_focus_out 함수를 기존 프로젝트에 추가하고, QLineEdit 위젯에 연결합니다.
  2. 커스텀 위젯 생성: QLineEdit을 상속받아 천 단위 쉼표 자동 추가 기능을 가진 커스텀 위젯을 만들어 재사용할 수 있습니다.
  3. 기능 확장: 필요에 따라 소수점 처리, 통화 기호 추가 등의 기능을 추가할 수 있습니다.

커스텀 위젯 예제

 

다음은 QLineEdit을 상속받아 만든 커스텀 위젯 예제입니다:


from PySide6.QtWidgets import QLineEdit
from PySide6.QtGui import QRegularExpressionValidator
from PySide6.QtCore import QRegularExpression

class CommaNumberLineEdit(QLineEdit):
    """천 단위 쉼표가 자동으로 추가되는 QLineEdit 커스텀 위젯"""
    
    def __init__(self, parent=None):
        super().__init__(parent)
        
        # 숫자와 쉼표만 입력 가능하도록 설정
        rx = QRegularExpression("^[0-9,]*$")
        validator = QRegularExpressionValidator(rx)
        self.setValidator(validator)
        
        # 텍스트 변경 시그널 연결
        self.textChanged.connect(self.format_number)
    
    def format_number(self, text):
        """텍스트가 변경될 때 호출되어 1000단위 쉼표를 추가합니다."""
        if not text:
            return
            
        # 현재 커서 위치 저장
        cursor_pos = self.cursorPosition()
        
        # 쉼표 제거
        text_without_commas = text.replace(',', '')
        
        # 숫자가 아닌 문자가 있으면 처리하지 않음
        if not text_without_commas.isdigit() and text_without_commas:
            return
            
        # 쉼표 추가 전 텍스트 길이
        old_len = len(text)
        
        # 1000단위 쉼표 추가
        if text_without_commas:
            number = int(text_without_commas)
            formatted_text = f"{number:,}"
            
            # 텍스트 변경 시그널 일시 차단
            self.blockSignals(True)
            self.setText(formatted_text)
            self.blockSignals(False)
            
            # 새 텍스트 길이
            new_len = len(formatted_text)
            
            # 커서 위치 조정 (쉼표가 추가되었을 때 커서 위치 유지)
            diff = new_len - old_len
            self.setCursorPosition(cursor_pos + diff)
    
    def focusOutEvent(self, event):
        """포커스를 잃을 때 호출되어 최종적으로 형식을 맞춥니다."""
        text = self.text()
        if text:
            # 쉼표 제거
            text_without_commas = text.replace(',', '')
            
            if text_without_commas:
                # 숫자로 변환 후 다시 포맷팅
                number = int(text_without_commas)
                formatted_text = f"{number:,}"
                self.setText(formatted_text)
                
        # 기본 이벤트 처리
        super().focusOutEvent(event)
        
    def get_value(self):
        """쉼표가 제거된 숫자 값을 반환합니다."""
        text = self.text()
        if not text:
            return 0
            
        text_without_commas = text.replace(',', '')
        return int(text_without_commas) if text_without_commas else 0

 

이 커스텀 위젯은 다음과 같이 사용할 수 있습니다:


from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
import sys

class TestWidget(QWidget):
    def __init__(self):
        super().__init__()
        
        layout = QVBoxLayout()
        
        label = QLabel("금액 입력:")
        self.amount_edit = CommaNumberLineEdit()
        
        layout.addWidget(label)
        layout.addWidget(self.amount_edit)
        
        self.setLayout(layout)
        self.setWindowTitle("천 단위 쉼표 자동 추가 예제")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = TestWidget()
    widget.show()
    sys.exit(app.exec())

이렇게 만든 커스텀 위젯은 프로젝트 내 여러 곳에서 재사용할 수 있어 코드 중복을 줄이고 유지보수를 용이하게 합니다.

기능 확장 아이디어
  • 소수점 지원: 정수뿐만 아니라 소수점이 있는 실수도 처리할 수 있도록 확장할 수 있습니다.
  • 통화 기호 추가: 원화(₩), 달러($) 등의 통화 기호를 자동으로 추가할 수 있습니다.
  • 최대값 제한: 입력할 수 있는 최대값을 설정하여 유효한 범위 내의 숫자만 입력받을 수 있습니다.
  • 음수 지원: 필요에 따라 음수 입력을 허용하고 처리할 수 있습니다.

 

결론

 

이 글에서는 PySide6를 사용하여 QLineEdit에 천 단위 쉼표 자동 추가 기능을 구현하는 방법을 알아보았습니다.

주요 내용을 요약하면 다음과 같습니다:

  1. QRegularExpressionValidator를 사용하여 입력을 숫자와 쉼표로 제한했습니다.
  2. textChanged 시그널을 연결하여 텍스트가 변경될 때마다 천 단위 쉼표를 자동으로 추가했습니다.
  3. 커서 위치를 적절히 조정하여 사용자 경험을 향상시켰습니다.
  4. focusOutEvent를 오버라이드하여 포커스를 잃을 때 최종적으로 형식을 맞추도록 했습니다.
  5. QLineEdit을 상속받아 재사용 가능한 커스텀 위젯을 만들었습니다.

이러한 기능은 금융 애플리케이션, 회계 프로그램, 판매 관리 시스템 등

숫자 입력이 많은 애플리케이션에서 사용자 경험을 크게 향상시킬 수 있습니다.

 

또한 이 기본 코드를 확장하여 소수점 처리, 통화 기호 추가, 최대값 제한 등 다양한 기능을 추가할 수 있습니다.

 

PySide6의 강력한 기능과 파이썬의 유연성을 활용하면 사용자 친화적인 GUI 애플리케이션을 쉽게 개발할 수 있습니다.

[ 파이썬 관련 블로그 글 목록 ] 

파이썬(Python) 블로그 목록
반응형