이 페이지에서

반투명 배경

이 예제는 반투명 배경을 가진 둥근 창을 만드는 방법을 보여줍니다.

텍스트 위에 겹쳐진 반투명한 시계

배경을 반투명하게 설정된 위젯은 채색되지 않은 모든 픽셀에 대해 투명하게 표시되며, 불투명도가 100% 미만인 픽셀을 통해 배경이 비쳐 보입니다. 전혀 채색되지 않은 픽셀은 마우스 입력도 받지 않습니다. 이 기능을 활용하여 최상위 위젯의 모양을 사용자 정의할 수 있습니다. 대부분의 윈도우 시스템에서는 특정 윈도우 플래그를 설정하면 윈도우 장식(제목 표시줄, 윈도우 테두리, 버튼)이 비활성화되어 특수한 모양의 윈도우를 만들 수 있습니다. 이 예제에서는 이 기능을 사용하여 아날로그 시계가 포함된 원형 윈도우를 만듭니다.

이 예제의 창에는 ‘ File ’ 메뉴나 닫기 버튼이 없으므로, 예제를 닫을 수 있도록 ‘ Exit ’ 항목이 포함된 컨텍스트 메뉴를 제공합니다. 창 위에서 마우스 오른쪽 버튼을 클릭하면 이 메뉴가 열립니다.

ShapedClock 클래스 정의

ShapedClock 클래스는 아날로그 시계 예제에서 정의된 AnalogClock 클래스를 기반으로 합니다. 전체 클래스 정의는 다음과 같습니다:

class ShapedClock : public QWidget
{
    Q_OBJECT

public:
    ShapedClock(QWidget *parent = nullptr);
    QSize sizeHint() const override;

protected:
    void mouseMoveEvent(QMouseEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

private:
    QPoint dragPosition;
};

paintEvent() 구현은 반투명한 배경(시계 문자판) 위에 아날로그 시계를 그립니다. 또한, 위젯의 크기를 명시적으로 조정할 필요가 없도록 sizeHint()을 구현합니다.

시계 위젯이 포함된 창에는 제목 표시줄이 없으므로, 시계를 화면 내로 드래그할 수 있도록 mouseMoveEvent() 및 mousePressEvent() 메서드의 구현을 제공합니다. dragPosition 변수를 통해 사용자가 위젯에서 마지막으로 클릭한 위치를 추적할 수 있습니다.

ShapedClock 클래스 구현

ShapedClock 생성자는 타이머를 설정하고 이를 위젯의 update() 슬롯에 연결합니다. 또한, 위젯에 액션을 추가하면 위젯을 마우스 오른쪽 버튼으로 클릭했을 때 컨텍스트 메뉴를 통해 해당 액션이 자동으로 사용 가능해집니다.

ShapedClock::ShapedClock(QWidget *parent)
    : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint)
{
    setAttribute(Qt::WA_TranslucentBackground);
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, QOverload<>::of(&ShapedClock::update));
    timer->start(1000);

    QAction *quitAction = new QAction(tr("E&xit"), this);
    quitAction->setShortcut(tr("Ctrl+Q"));
    connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
    addAction(quitAction);

    setContextMenuPolicy(Qt::ActionsContextMenu);
    setToolTip(tr("Drag the clock with the left mouse button.\n"
                  "Use the right mouse button to open a context menu."));
    setWindowTitle(tr("Shaped Analog Clock"));
}

Qt::WA_TranslucentBackground 위젯 속성을 설정하여 투명한 창을 요청합니다. 또한 위젯에 Qt::FramelessWindowHint 플래그를 설정하여 창 관리자에게 이 위젯에 창 테두리를 적용하지 않도록 알립니다. 그 결과, 사용자가 화면에서 시계를 이동할 수 있는 방법을 제공해야 합니다.

마우스 버튼 이벤트는 ` mousePressEvent() ` 핸들러로 전달됩니다:

void ShapedClock::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft();
        event->accept();
    }
}

위젯 위에서 마우스 왼쪽 버튼이 눌리면, 위젯 프레임의 왼쪽 상단 위치(숨겨진 경우에도 포함)와 마우스 클릭이 발생한 지점 사이의 전역(화면) 좌표상 변위량을 기록합니다. 이 변위량은 사용자가 마우스 왼쪽 버튼을 누른 상태로 마우스를 이동할 때 사용됩니다. 이벤트에 대한 처리를 수행했으므로, accept() 함수를 호출하여 이벤트를 수락합니다.

시계 문자판에 대한 드래그 위치

mouseMoveEvent() 핸들러는 마우스가 위젯 위에서 이동할 때 호출됩니다.

void ShapedClock::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        move(event->globalPosition().toPoint() - dragPosition);
        event->accept();
    }
}

마우스를 이동하는 동안 왼쪽 버튼을 누르고 있으면, 위젯의 왼쪽 상단 모서리가 전역 좌표계에서 현재 커서 위치에서 ` dragPosition ` 값을 뺀 지점으로 이동합니다. 위젯을 드래그할 때도 이 이벤트를 수신합니다.

paintEvent() 함수는 주로 아날로그 시계 예제에서 설명한 것과 동일합니다. 추가된 점은 QPainter::drawEllipse()를 사용하여 둥근 시계 문자판을 그리는 것입니다. 페인터의 불투명도를 90%로 낮추고, 팔레트의 기본 배경색을 사용합니다.

void ShapedClock::paintEvent(QPaintEvent *)
{
    static const QPoint hourHand[4] = {
        QPoint(5, 14),
        QPoint(-5, 14),
        QPoint(-4, -71),
        QPoint(4, -71)
    };
    static const QPoint minuteHand[4] = {
        QPoint(4, 14),
        QPoint(-4, 14),
        QPoint(-3, -89),
        QPoint(3, -89)
    };
    static const QPoint secondsHand[4] = {
       QPoint(1, 14),
       QPoint(-1, 14),
       QPoint(-1, -89),
       QPoint(1, -89)
    };

    const QColor hourColor(palette().color(QPalette::Text));
    const QColor minuteColor(palette().color(QPalette::Text));
    const QColor secondsColor(palette().color(QPalette::Accent));

    int side = qMin(width(), height());
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width() / 2, height() / 2);
    painter.scale(side / 200.0, side / 200.0);

    painter.setPen(Qt::NoPen);
    painter.setBrush(palette().window());
    painter.setOpacity(0.9);
    painter.drawEllipse(QPoint(0, 0), 98, 98);
    painter.setOpacity(1.0);

    QTime time = QTime::currentTime();
    painter.setPen(Qt::NoPen);
    painter.setBrush(hourColor);

    {
        QPainterStateGuard guard(&painter);
        painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
        painter.drawConvexPolygon(hourHand, 4);
    }

    for (int i = 0; i < 12; ++i) {
        painter.drawRect(73, -3, 16, 6);
        painter.rotate(30.0);
    }

    painter.setBrush(minuteColor);

    {
        QPainterStateGuard guard(&painter);
        painter.rotate(6.0 * time.minute());
        painter.drawConvexPolygon(minuteHand, 4);
    }

    painter.setBrush(secondsColor);

    {
        QPainterStateGuard guard(&painter);
        painter.rotate(6.0 * time.second());
        painter.drawConvexPolygon(secondsHand, 4);
        painter.drawEllipse(-3, -3, 6, 6);
        painter.drawEllipse(-5, -68, 10, 10);
    }

    painter.setPen(minuteColor);

    for (int j = 0; j < 60; ++j) {
        painter.drawLine(92, 0, 96, 0);
        painter.rotate(6.0);
    }
}

마지막으로, 위젯이 처음 표시될 때 적절한 기본 크기를 갖도록 sizeHint() 를 구현합니다:

QSize ShapedClock::sizeHint() const
{
    return QSize(200, 200);
}

예제 프로젝트 @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.