QComboBox 확장하여 우측 삭제 버튼 기능 구현

기존 QComboBox의 한계와 개선 방향

Qt에서 QComboBox는 사용자에게 미리 정의된 항목 중 하나를 선택하게 하는 핵심 위젯 중 하나다. 기본적으로 선택 항목을 표시하고, 클릭 시 드롭다운 리스트를 보여주는 기능을 제공하지만, UI/UX 측면에서 더 직관적인 조작을 원할 경우 확장이 필요하다. 특히 웹 인터페이스에서 흔히 볼 수 있는 'X' 버튼 클릭으로 선택 해제 기능을 네이티브 데스크톱 애플리케이션에서도 구현하고자 하는 요구가 자주 발생한다.

요구사항 분석 및 설계 전략

목표는 QComboBox의 오른쪽 끝, 기존 드롭다운 화살표 위치에 마우스 커서가 올라갔을 때 아이콘이 '×'로 변경되며, 클릭 시 현재 선택된 항목을 초기화하는 것이다. 이를 위해 다음과 같은 접근이 필요하다:

  • 선택 상태에 따라 시각적 피드백 제공 (아이콘 전환)
  • 마우스 입력 영역 정밀 판별
  • 기본 동작 재정의 및 사용자 정의 이벤트 처리

동적 스타일 속성 기반 아이콘 전환

Qt 스타일시트는 정적 정의 외에도 setProperty()를 통해 동적으로 속성을 부여함으로써 다양한 상태를 표현할 수 있다. 아래 코드는 선택 여부에 따라 Type 속성을 설정하고, 스타일을 갱신하는 예시이다.

#include <QComboBox>
#include <QMouseEvent>
#include <QStyleOption>

class EditableComboBox : public QComboBox
{
    Q_OBJECT

public:
    explicit EditableComboBox(QWidget *parent = nullptr) : QComboBox(parent)
    {
        connect(this, &QComboBox::currentIndexChanged,
                this, &EditableComboBox::updateIconType);
        setFocusPolicy(Qt::StrongFocus);
    }

private slots:
    void updateIconType(int index)
    {
        const QString iconState = (index == -1) ? "arrow" : "clear";
        setProperty("iconMode", iconState);
        style()->polish(this); // 스타일 재적용
    }
};

선택 해제 로직 구현

선택된 항목을 비우는 것은 단순히 setCurrentIndex(-1)를 호출하면 된다. 이는 Qt에서 유효하지 않은 인덱스로 해석되어 표시 텍스트를 비우는 효과를 낸다.

입력 이벤트 오버라이딩을 통한 정밀 제어

마우스 이벤트를 재정의하여, 특정 영역(드롭다운/삭제 아이콘)에서의 클릭을 감지해야 한다. Qt는 hitTestComplexControl() 함수를 통해 복합 위젯 내 하위 요소를 식별할 수 있도록 지원한다.

void EditableComboBox::mouseReleaseEvent(QMouseEvent *event)
{
    QStyleOptionComboBox option;
    initStyleOption(&option);

    const QStyle::SubControl control = style()->hitTestComplexControl(
        QStyle::CC_ComboBox, &option, event->pos(), this);

    // 우클릭 무시
    if (event->button() == Qt::RightButton) {
        event->accept();
        return;
    }

    // 삭제 모드에서 왼쪽 클릭이 화살표 영역에 있을 경우
    if (property("iconMode").toString() == "clear" &&
        event->button() == Qt::LeftButton &&
        control == QStyle::SC_ComboBoxArrow) {

        setCurrentIndex(-1); // 선택 해제
        event->accept();
        return;
    }

    // 그 외의 경우 기본 드롭다운 동작 수행
    QComboBox::mouseReleaseEvent(event);
}

불필요한 동작 억제

기본 QComboBox는 마우스를 누르고 있을 때 드롭다운이 열리는 경우가 있는데, 이를 방지하기 위해 mousePressEvent를 가로채서 차단한다.

void EditableComboBox::mousePressEvent(QMouseEvent *event)
{
    // 드래그 시 드롭다운 방지
    Q_UNUSED(event);
}

CSS 기반 시각적 표현

다음과 같은 스타일시트를 적용하면, iconMode 속성에 따라 아이콘이 전환된다.

EditableComboBox[iconMode="arrow"] {
    padding-right: 20px;
    selection-background-color: #4a90e2;
}

EditableComboBox[iconMode="clear"] {
    padding-right: 20px;
    qproperty-icon: url(:/icons/close.svg); /* 또는 border-image 등 */
}

실제 프로젝트에서는 qproperty-icon 대신 border-image나 폰트 아이콘(Font Awesome 등)을 활용해도 좋다.

태그: Qt C++ QComboBox CustomWidget EventHandling

7월 28일 13:43에 게시됨