Files
2026-02-24 18:30:51 +09:00

212 lines
5.9 KiB
C++

#include "pagetotalpay.h"
#include "ui_pagetotalpay.h"
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsProxyWidget>
#include <QVariantAnimation>
#include <QVBoxLayout>
#include <QLabel>
#include <QEvent>
#include <QMouseEvent>
#include <QResizeEvent>
#include <QTimer>
#include <QtMath>
#include <QPainter>
#include <QPen>
#include <QEasingCurve>
PageTotalPay::PageTotalPay(QWidget *parent)
: QWidget(parent)
, ui(new Ui::PageTotalPay)
{
ui->setupUi(this);
if (objectName().isEmpty())
setObjectName("PageTotalPay");
// ✅ 여기 추가
setStyleSheet("QWidget#PageTotalPay { background-color: rgb(34,197,94); }");
// ✅ Scene/View
m_scene = new QGraphicsScene(this);
m_view = new QGraphicsView(this);
m_view->setScene(m_scene);
m_view->setFrameShape(QFrame::NoFrame);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setStyleSheet("background: transparent;");
m_view->setAlignment(Qt::AlignCenter);
// 클릭 이벤트를 view/viewport에서도 잡기
m_view->viewport()->installEventFilter(this);
m_view->installEventFilter(this);
// ✅ content 위젯(아이콘+텍스트)
m_content = new QWidget();
m_content->setAttribute(Qt::WA_TranslucentBackground);
m_content->installEventFilter(this);
auto *lay = new QVBoxLayout(m_content);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(28);
lay->setAlignment(Qt::AlignCenter);
QLabel *lblIcon = new QLabel(m_content);
lblIcon->setFixedSize(140, 140);
lblIcon->setAlignment(Qt::AlignCenter);
lblIcon->setPixmap(makeCheckIcon(128));
lblIcon->setStyleSheet("background: transparent;");
QLabel *lblTitle = new QLabel("구매해주셔서 감사합니다", m_content);
lblTitle->setAlignment(Qt::AlignCenter);
lblTitle->setStyleSheet(
"background: transparent;"
"color: rgb(0,0,0);"
"font-weight: 900;"
"font-size: 44px;"
);
QLabel *lblSub = new QLabel("화면을 다시 눌러 시작하기", m_content);
lblSub->setAlignment(Qt::AlignCenter);
lblSub->setStyleSheet(
"background: transparent;"
"color: rgb(0,0,0);"
"font-weight: 700;"
"font-size: 22px;"
);
lay->addWidget(lblIcon, 0, Qt::AlignCenter);
lay->addWidget(lblTitle, 0, Qt::AlignCenter);
lay->addWidget(lblSub, 0, Qt::AlignCenter);
// ✅ proxy로 올리기(스케일 애니메이션 대상)
m_proxy = m_scene->addWidget(m_content);
m_proxy->setTransformOriginPoint(m_proxy->boundingRect().center());
// ✅ 레이아웃 붙이기 (중요: 기존 레이아웃 있으면 거기에 붙임)
if (this->layout()) {
this->layout()->setContentsMargins(0,0,0,0);
this->layout()->addWidget(m_view);
} else {
auto *root = new QVBoxLayout(this);
root->setContentsMargins(0,0,0,0);
root->addWidget(m_view);
}
// ✅❗️여기가 너 코드에서 크래시 난 부분: m_pulseAnim을 반드시 생성해야 함
m_pulseAnim = new QVariantAnimation(this);
// ✅ 코사인 루프 (자연스럽게 1.0 -> 1.15 -> 1.0, 점프 없음)
m_pulseAnim->setStartValue(0.0);
m_pulseAnim->setEndValue(2.0 * M_PI);
m_pulseAnim->setDuration(2000);
m_pulseAnim->setLoopCount(-1);
m_pulseAnim->setEasingCurve(QEasingCurve::Linear);
connect(m_pulseAnim, &QVariantAnimation::valueChanged, this, [this](const QVariant &v){
const qreal t = v.toReal();
const qreal amp = 0.15;
const qreal scale = 1.0 + amp * 0.5 * (1.0 - qCos(t));
if (m_proxy) m_proxy->setScale(scale);
});
m_pulseAnim->start();
// ✅ viewport size가 0일 수 있으니 show 이후에 중앙 정렬
QTimer::singleShot(0, this, [this](){ centerProxy(); });
}
PageTotalPay::~PageTotalPay()
{
delete ui;
}
QPixmap PageTotalPay::makeCheckIcon(int sizePx) const
{
const int pad = 6;
QPixmap pm(sizePx + pad*2, sizePx + pad*2);
pm.fill(Qt::transparent);
QPainter p(&pm);
p.setRenderHint(QPainter::Antialiasing, true);
// ✅ 초록색 (Tailwind green-500 비슷)
QColor green(34, 197, 94);
// circle stroke
QPen pen(green); // ✅ 여기!
pen.setWidthF(sizePx * 0.07);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
p.setPen(pen);
p.setBrush(Qt::NoBrush);
QRectF rc(pad, pad, sizePx, sizePx);
p.drawEllipse(rc);
// check
p.setPen(Qt::NoPen);
p.setBrush(green);
p.drawEllipse(rc);
// 체크: 흰색
QPen pen2(Qt::white);
pen2.setWidthF(sizePx * 0.09);
pen2.setCapStyle(Qt::RoundCap);
pen2.setJoinStyle(Qt::RoundJoin);
p.setPen(pen2);
p.setBrush(Qt::NoBrush);
QPointF a(rc.left() + sizePx*0.28, rc.top() + sizePx*0.55);
QPointF b(rc.left() + sizePx*0.46, rc.top() + sizePx*0.70);
QPointF c(rc.left() + sizePx*0.74, rc.top() + sizePx*0.36);
p.drawLine(a, b);
p.drawLine(b, c);
return pm;
}
void PageTotalPay::centerProxy()
{
if (!m_view || !m_scene || !m_proxy) return;
const QSize vsz = m_view->viewport()->size();
if (vsz.width() <= 0 || vsz.height() <= 0) return; // ✅ 0이면 아직 표시 전
m_scene->setSceneRect(0, 0, vsz.width(), vsz.height());
const QPointF origin = m_proxy->boundingRect().center();
m_proxy->setTransformOriginPoint(origin);
const QPointF sceneCenter = m_scene->sceneRect().center();
m_proxy->setPos(sceneCenter - origin);
}
void PageTotalPay::resizeEvent(QResizeEvent *e)
{
QWidget::resizeEvent(e);
centerProxy();
}
bool PageTotalPay::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress) {
emit backToStartClicked();
return true;
}
return QWidget::eventFilter(obj, event);
}
void PageTotalPay::mousePressEvent(QMouseEvent *e)
{
emit backToStartClicked();
QWidget::mousePressEvent(e);
}