Linux->Qt音乐播放器:坚持到无能为力

Linux->ubuntu22.04->Qt5.9.0

具体效果:

实现的功能:播放歌曲、切换歌曲,进度条拖动、滚动歌词、循环单曲随机播放、可保存的喜欢、快进快退、歌曲的倍速播放、专辑封面滚轮动画、大背景图切换、播放历史喜欢列表和播放列表、音量控制、播放歌曲MV。

默认背景:

播放效果:

歌曲列表:

MV播放效果:

使用到的UI:

UI布局(都说丑丑的但我嘴硬并不承认),参考哈

具体实现:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSlider>
#include <QLabel>
#include <QString>
#include <QTimer>
#include <QMap>
#include <QTableWidget>
#include <vector>
#include <random>
#include <QPixmap>
#include <QPropertyAnimation>
#include <QTransform>
#include <QPainter>
#include <QResizeEvent>
#include <QGraphicsBlurEffect>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QPaintEvent>
#include <QProcess>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
protected:
    void resizeEvent(QResizeEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void paintEvent(QPaintEvent *event) override;
public:
    void prepareCircularPixmap();
    void rotateImage();
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();
    void updateLikeButtonVisibility();
    void loadLikeSongList();
    void updateLikeSongList();
    void mplayerInit();
    void my_search_dir();
    void changeSong(int current_song);
    void requestCurrentTime();
    void loadLyrics(const QString &songName);
    void update_lyrics_display(int currentTime);
    void pauseTimer();
    void resumeTimer();
    void updateSongNameLabel(const QString &songName);
    void updateSongerNameLabel(const QString &songerName);
    void populateSongList();
    enum PlaybackMode { Normal, SingleLoop, Shuffle };
    void playCurrentSongAgain();
    void playRandomSong();
    void nextSong();
    void updateCurrentSongDisplay();
    void updateBackground();
    void playVideoWithGStreamer(const QString &videoPath);
    void updateHistoryTable(const QString &songName);
    void setupHistoryTable();
private slots:
    void on_nextBtn_clicked();
    void on_pauseBtn_clicked();
    void on_backBtn_clicked();
    void set_total_time_label(int total_time);
    void update_current_time(int current_time);
    void sliderMoved(int position);
    void sliderPressed();
    void sliderReleased();
    void on_songTable_doubleClicked(QTableWidgetItem* item);
    void on_editBtn_pressed();
    void on_likeBtn1_pressed();
    void on_likeBtn2_pressed();
    void setCurrentPlayingSong(const QString &name);  
    void processMPlayerResponse(const QString &response);
    void on_likeSongListTableWidget_doubleClicked(QTableWidgetItem* item);
    void setPlaybackMode(int modeIndex);
    void setVolume(int volume);
    void toggleVolumeSlider();
    void toggleMute();
    void updateVolumeButtons(int volume);
    void changePlaybackSpeed(const QString& speed);
    void on_playBtn_clicked();
    void on_quiteBackBtn_clicked();
    void on_quiteNextBtn_clicked();
signals:
    void setTotalTime(int total_time);
    void setCurrentTime(int current_time);
private:
    Ui::Widget *ui;
    QPixmap backgroundPixmap;
    QPixmap totalbackgroundPixmap;
    int fifo_fd;
    std::vector<QString> songList;
    int current_song;
    int fd[2];
    bool isPlaying;
    int total_time;
    QTimer *timer;
    bool sliderIsPressed = false;
    int lastSliderPosition = 0;
    QString currentSongName;
    float currentTime;
    QMultiMap<int, QString> lyricsMap;
    QString currentPlayingSong;
    static void *read_mplayer_ans(void *arg);
    QTimer *rotationTimer;
    int rotationAngle = 0;
    std::mt19937 rng;
    PlaybackMode currentMode = Normal;
    QPixmap circularBackgroundPixmap;
    QPropertyAnimation* rotationAnimation;
    void setLabelGreen(QLabel* label);
    QProcess* mvProcess = nullptr; 
};

#endif // WIDGET_H

//.cpp文件
#include "widget.h"
#include "ui_widget.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <QDebug>
#include <QFile>
#include <QVBoxLayout>
#include <QDir>
#include <QTime>
#include <QFont>
#include <QPalette>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    currentTime(0),
    total_time(0)
{
    ui->setupUi(this);
    this->setWindowTitle("小小凤的音乐播放器");
    mplayerInit();
    ui->likeBtn2->hide();
    my_search_dir();
    current_song = -1;
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Widget::requestCurrentTime);
    timer->start(500);
    ui->songListTabWidget->setVisible(false);
    loadLikeSongList();
    prepareCircularPixmap();
    setupHistoryTable();
    totalbackgroundPixmap.load("./song_background/background.png");
    backgroundPixmap.load("./song_pic/background.png");
    ui->picLabel->setPixmap(backgroundPixmap.scaled(ui->picLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    rotationAnimation = new QPropertyAnimation(ui->picLabel, "rotation");
    rotationAnimation->setDuration(10000);
    rotationAnimation->setStartValue(0);
    rotationAnimation->setEndValue(360);
    rotationAnimation->setLoopCount(-1);
    rotationAnimation->setEasingCurve(QEasingCurve::Linear);
    ui->setVolumeVerticalSlider->setRange(70, 100);
    ui->setVolumeVerticalSlider->setValue(80);
    ui->playBtn->hide();  // playBtn 默认隐藏
    ui->pauseBtn->show();  // pauseBtn 默认显示
    ui->historyTableWidget->setColumnCount(1);  // 只有一列,用于显示歌曲名
    ui->historyTableWidget->setHorizontalHeaderLabels(QStringList() << "History Played Songs");


    updateVolumeButtons(ui->setVolumeVerticalSlider->value()); // 初始化按钮状态
    ui->setVolumeVerticalSlider->hide();
    rotationTimer = new QTimer(this);
    connect(rotationTimer, &QTimer::timeout, this, &Widget::rotateImage);
    rotationTimer->start(100);


    // 设置 songNameLabel 字体加粗和字号
    QFont songNameFont;
    songNameFont.setBold(true);
    songNameFont.setPointSize(20);
    ui->songNameLabel->setFont(songNameFont);

    // 设置 songerNameLabel 字体加粗和字号
    QFont songerNameFont;
    songerNameFont.setBold(true);
    songerNameFont.setPointSize(18);
    ui->songerNameLabel->setFont(songerNameFont);

    // 字体加粗设置
    QFont boldFont;
    boldFont.setBold(true);
    ui->backbackSongLabel->setAlignment(Qt::AlignCenter);
    ui->nextnextSongLabel->setAlignment(Qt::AlignCenter);
    ui->nextSongLabel->setAlignment(Qt::AlignCenter);
    ui->nowSongLabel->setAlignment(Qt::AlignCenter);
    ui->backSongLabel->setAlignment(Qt::AlignCenter);
    ui->songNameLabel->setAlignment(Qt::AlignCenter);
    ui->songerNameLabel->setAlignment(Qt::AlignCenter);

    // 设置backSongLabel的特殊字体和颜色
    QFont backSongFont;
    backSongFont.setBold(true);
    backSongFont.setPointSize(20);

    QPalette redPalette;
    redPalette.setColor(QPalette::WindowText, Qt::red);

    ui->backSongLabel->setFont(backSongFont);
    ui->backSongLabel->setPalette(redPalette);

    // 其他标签的字体设置
    ui->nowSongLabel->setFont(boldFont);
    ui->backbackSongLabel->setFont(boldFont);
    ui->nextSongLabel->setFont(boldFont);
    ui->nextnextSongLabel->setFont(boldFont);
    // 其他标签的字体颜色设置
    setLabelGreen(ui->nowSongLabel);
    setLabelGreen(ui->backbackSongLabel);
    setLabelGreen(ui->nextSongLabel);
    setLabelGreen(ui->nextnextSongLabel);

    connect(this, &Widget::setTotalTime, this, &Widget::set_total_time_label);
    connect(this, &Widget::setCurrentTime, this, &Widget::update_current_time);
    connect(ui->progressBar, &QSlider::sliderPressed, this, &Widget::sliderPressed);
    connect(ui->progressBar, &QSlider::sliderReleased, this, &Widget::sliderReleased);
    connect(ui->progressBar, &QSlider::sliderMoved, this, &Widget::sliderMoved);
    connect(ui->songTable, &QTableWidget::itemDoubleClicked, this, &Widget::on_songTable_doubleClicked);
    connect(ui->likeSongListTableWidget, &QTableWidget::itemDoubleClicked, this, &Widget::on_likeSongListTableWidget_doubleClicked);
    connect(ui->modeSelectionBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setPlaybackMode(int)));
    connect(ui->setVolumeVerticalSlider, &QSlider::valueChanged, this, &Widget::setVolume);
    connect(ui->setVolumeBtn, &QPushButton::clicked, this, &Widget::toggleVolumeSlider);
    connect(ui->muteBtn, &QPushButton::clicked, this, &Widget::toggleMute);
    connect(ui->setVolumeVerticalSlider, &QSlider::valueChanged, this, &Widget::updateVolumeButtons);
    connect(ui->playBtn, &QPushButton::clicked, this, &Widget::on_playBtn_clicked);
    connect(ui->pauseBtn, &QPushButton::clicked, this, &Widget::on_pauseBtn_clicked);
    connect(ui->speedComboBox, SIGNAL(currentTextChanged(const QString&)), this, SLOT(changePlaybackSpeed(const QString&)));
    connect(ui->quiteBackBtn, &QPushButton::clicked, this, &Widget::on_quiteBackBtn_clicked);
    connect(ui->quiteNextBtn, &QPushButton::clicked, this, &Widget::on_quiteNextBtn_clicked);
    connect(ui->playMVPushButton, &QPushButton::clicked, this, [this]() {
        on_pauseBtn_clicked();
        QString mvFilePath = "./song_mv/" + currentPlayingSong.section('.', 0, 0).trimmed() + ".mp4";
        playVideoWithGStreamer(mvFilePath);
    });

}
void Widget::setupHistoryTable() {
    ui->historyTableWidget->setColumnCount(1);  // 只有一列
    ui->historyTableWidget->setHorizontalHeaderLabels(QStringList() << "History Played Songs");
    ui->historyTableWidget->horizontalHeader()->setStretchLastSection(true); // 设置列宽自适应表格宽度
    ui->historyTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);  // 禁止编辑
    ui->historyTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 让列宽自动调整以填满空间
}
void Widget::updateHistoryTable(const QString &songName) {
    bool alreadyExists = false;
    int rowCount = ui->historyTableWidget->rowCount();
    for (int i = 0; i < rowCount; ++i) {
        QTableWidgetItem *item = ui->historyTableWidget->item(i, 0);
        if (item && item->text() == songName) {
            alreadyExists = true;
            break;
        }
    }

    if (!alreadyExists) {
        ui->historyTableWidget->insertRow(rowCount);
        QTableWidgetItem *newItem = new QTableWidgetItem(songName);
        newItem->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
        ui->historyTableWidget->setItem(rowCount, 0, newItem);
    }
}


void Widget::playVideoWithGStreamer(const QString &videoPath) {
    if (mvProcess) {
        mvProcess->terminate(); // 尝试终止当前进程
        mvProcess->waitForFinished(); // 等待进程结束
        delete mvProcess; // 删除进程对象
    }

 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值