Qt를 이용한 MP3 플레이어 인터페이스 및 프레임리스 윈도우 구현

Qt Creator 환경에서 멀티미디어 애플리케이션을 개발할 때, 기본 윈도우 프레임을 제거하고 사용자 정의 UI를 구성하는 것은 매우 일반적인 요구사항입니다. 이 문서에서는 Qt의 QMediaPlayer, Network 모듈 및 SQL 모듈을 활용하기 위한 기본 환경 구성과 마우스 드래그로 이동 가능한 커스텀 인터페이스를 구현하는 방법을 설명합니다.

1. 프로젝트 설정 (Project File)

네트워크 통신, 멀티미디어 재생, 데이터베이스 사용을 위해 .pro 파일에 필요한 모듈을 추가해야 합니다. 또한 C++17 표준을 사용하도록 설정합니다.

QT += core gui network multimedia sql

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

SOURCES += main.cpp \
           player_widget.cpp

HEADERS += player_widget.h

FORMS += player_widget.ui

RESOURCES += resources.qrc

2. 커스텀 인터페이스 및 윈도우 설정

애플리케이션의 시각적 완성도를 높이기 위해 배경 이미지를 직접 드로잉하고, 기본 윈도우 타이틀 바를 제거합니다.

배경 이미지 렌더링

paintEvent를 오버라이드하여 윈도우 배경에 이미지를 출력합니다.

void PlayerWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.drawPixmap(0, 0, width(), height(), QPixmap(":/images/bg_main.jpg"));
}

윈도우 스타일 제어

프레임리스 윈도우를 설정하고 크기를 고정하는 코드입니다. UI 디자이너에서 버튼의 flat 속성을 활성화하고 스타일시트에서 배경을 투명하게 처리할 수 있습니다.

// 생성자 내 설정
this->setFixedSize(this->geometry().size());     // 창 크기 고정
this->setWindowFlag(Qt::FramelessWindowHint);    // 타이틀 바 제거

// 스타일시트를 통한 투명화
// background-color: transparent;
// color: #FFFFFF;

3. 마우스 이벤트를 이용한 창 이동 구현

타이틀 바를 제거하면 마우스로 창을 이동할 수 없게 됩니다. 이를 해결하기 위해 마우스 이벤트를 재정의하여 드래그 기능을 직접 구현합니다.

void PlayerWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        isDragging = true;
        // 클릭 지점과 창 좌측 상단 사이의 거리 계산
        dragOffset = event->globalPos() - frameGeometry().topLeft();
    }
}

void PlayerWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (isDragging && (event->buttons() & Qt::LeftButton)) {
        // 계산된 오프셋을 유지하며 창 이동
        move(event->globalPos() - dragOffset);
    }
}

void PlayerWidget::mouseReleaseEvent(QMouseEvent *event)
{
    isDragging = false;
}

4. 주요 클래스 정의 (Header)

네트워크 요청 처리 및 JSON 파싱, 오디오 제어를 위한 멤버 함수와 변수를 선언합니다.

#ifndef PLAYER_WIDGET_H
#define PLAYER_WIDGET_H

#include <QWidget>
#include <QPoint>
#include <QMediaPlayer>
#include <QNetworkAccessManager>
#include <QJsonObject>
#include <QJsonArray>
#include <QSqlDatabase>

QT_BEGIN_NAMESPACE
namespace Ui { class PlayerWidget; }
QT_END_NAMESPACE

class PlayerWidget : public QWidget
{
    Q_OBJECT

public:
    PlayerWidget(QWidget *parent = nullptr);
    ~PlayerWidget();

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

    // 데이터 처리 관련 메서드
    void fetchMusicData(QString musicId, QString authHash);
    void processJsonResponse(QByteArray rawData);

private slots:
    void on_btnExit_clicked();

private:
    Ui::PlayerWidget *ui;
    QPoint dragOffset;
    bool isDragging = false;
    
    QNetworkAccessManager *networkManager;
    QMediaPlayer *audioPlayer;
};

#endif // PLAYER_WIDGET_H

5. 소스 코드 구현 (Implementation)

위에서 정의한 로직을 바탕으로 버튼 클릭 이벤트 및 초기화 과정을 구현합니다.

#include "player_widget.h"
#include "ui_player_widget.h"
#include <QPainter>
#include <QMouseEvent>

PlayerWidget::PlayerWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::PlayerWidget)
{
    ui->setupUi(this);
    
    // UI 초기 설정
    setWindowFlag(Qt::FramelessWindowHint);
    setFixedSize(width(), height());
}

PlayerWidget::~PlayerWidget()
{
    delete ui;
}

void PlayerWidget::on_btnExit_clicked()
{
    this->close();
}

void PlayerWidget::fetchMusicData(QString musicId, QString authHash)
{
    // API 호출 및 음악 다운로드 로직 구현 예정
}

void PlayerWidget::processJsonResponse(QByteArray rawData)
{
    // JSON 파싱을 통한 곡 정보 추출 로직
}

태그: Qt cpp QMediaPlayer FramelessWindow GUI

7월 23일 16:48에 게시됨