반투명 배경
이 예는 반투명 배경을 가진 둥근 창을 만드는 방법을 보여줍니다.
배경을 반투명으로 설정한 위젯은 페인트되지 않은 모든 픽셀이 투명해지고 불투명도 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); painter.save(); painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); painter.drawConvexPolygon(hourHand, 4); painter.restore(); for (int i = 0; i < 12; ++i) { painter.drawRect(73, -3, 16, 6); painter.rotate(30.0); } painter.setBrush(minuteColor); painter.save(); painter.rotate(6.0 * time.minute()); painter.drawConvexPolygon(minuteHand, 4); painter.restore(); painter.setBrush(secondsColor); painter.save(); painter.rotate(6.0 * time.second()); painter.drawConvexPolygon(secondsHand, 4); painter.drawEllipse(-3, -3, 6, 6); painter.drawEllipse(-5, -68, 10, 10); painter.restore(); painter.setPen(minuteColor); for (int j = 0; j < 60; ++j) { painter.drawLine(92, 0, 96, 0); painter.rotate(6.0); } }
마지막으로 위젯이 처음 표시될 때 적절한 기본 크기가 지정되도록 sizeHint()
을 구현합니다:
© 2025 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.