【QT】《Qt5.9 C++開發指南》在桌面上放個伊芙利特

前言

就是像QQ寵物一樣,在電腦屏幕上設計一個“智能點”的窗口或者就放一個可交互的GIF……(提前準備一批透明背景的GIF圖和分解出來的透明背景的PNG圖)


無邊框&透明背景窗口

建一個集成QMainWindow或者QWidget的QT項目。UI編輯裏刪除狀態欄、工具欄、菜單欄。放入一個QLablel,我們就是用QLabelsetMovie方法來顯示圖片。把label設置爲右鍵設置爲柵格佈局,並且記得右下角的佈局屬性設置爲0
在這裏插入圖片描述
接着設置窗口透明、無邊框、始終置於前面。這樣運行會得到一個透明窗口,因爲是透明的所以看不到,需要在任務欄關閉。

//widget.cpp
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);


    //無邊框//保證窗口一直在前面
    setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
    //透明背景
    setAttribute(Qt::WA_TranslucentBackground);

}

實現窗口可拖動

首先需要填充一下背景,只有被填充的窗口部分才能接受到鼠標點擊的信號——到後面我們播放透明背景的GIF圖就明白了,透明的部分的窗口是可以穿過的,只有不透明的地方纔能交互。

//widget.cpp
void Widget::paintEvent(QPaintEvent *event){
	QPainter p(this);
	//顏色填充
    p.fillRect(6,6,width()-12,height()-12,QColor(232, 236, 247));

	//圖片填充
	 //位圖填充
    //QPixmap backBmp("../window_try_2/Background.bmp");
    //  p.drawPixmap(6,6,width()-12,height()-12,backBmp,0,0,backBmp.width(),backBmp.height());

}

在這裏插入圖片描述
可以重寫一下mouseMoveEvent輸出鼠標座標,來看看是否接受到了鼠標消息。

接受到了鼠標消息,拖動就是靠這個消息來手動移動窗口。

//widget.h
protected:
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void paintEvent(QPaintEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

private:
    bool    flag_clicked;        //左鼠標點擊實現移動
    QPoint  currentPos;   //屏幕上點擊的座標點
//widget.cpp
void Widget::mouseMoveEvent(QMouseEvent *event){

    //移動窗口
    if(flag_clicked){
        QPoint tempPos = event->globalPos() - currentPos;
        move(pos() + tempPos);
        currentPos = event->globalPos();
    }

}
void Widget::mousePressEvent(QMouseEvent *event){
    if(event->buttons() == Qt::LeftButton){
        //qDebug()<<"flag_clicked=true";
        flag_clicked = true;
        currentPos = event->globalPos();
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event){

    //qDebug()<<"flag_clicked=false";
    flag_clicked = false;

}

在這裏插入圖片描述

播放GIF

在這裏插入圖片描述
文件太大了,只能放截圖了。官方公佈的兩個GIF圖,找不到透明背景的,所以只有自己處理了(這個之後講)

先播放試試效果。使用QMovie類來加載GIF圖,再使用QLabel的setMovie方法來顯示。

//widget.cpp
    //這個添加到構造函數裏
    //播放GIF
    movie=new QMovie("../window_try_4/1.gif");
    movie->setScaledSize(QSize(200,200));//設置GIF大小
    //movie->setSpeed(100);//默認100%原始動畫速度
    ui->label->setMovie(movie);
    movie->start();

保存爲JPG

爲了更好的操作,必須要PNG圖。用在線的GIF轉JPG沒用,因爲文件太大,轉換出來的都壞了,所以還是自己來轉換。
通過獲取QMovie對象的當前圖像,可以保存爲JPG圖片。另外每次QMovie對象的幀變化時會發射frameChanged信號,所以我們需要自定義一個槽函數on_saveAsJPG來關聯一下。
通過這種方法,可以發現第一個GIF圖有111幀,第二個GIF圖有158幀……

//widget.cpp
void Widget::on_saveAsJPG(){

    static int i=0;
    if(i<movie->frameCount()){ //避免保存太多
        qDebug()<<"save>"<<i;
        QImage p = movie->currentImage();
        p.save(QString::asprintf("E:/幹員1_JPG/1_%d.jpg",i++),"JPG",100);//100表示未壓縮
    }
}

摳圖變成PNG

無論你是想直接播放幾個GIF(下面那步)還是想逐幀播放(下下面那步),都需要摳圖(如果有現成的該多好)……

用PS打開一張JPG圖片,用多邊形套索選擇出來。新建一個圖層,把選擇的內容複製到新的圖層中,再把舊的圖層刪除,保存到PNG文件夾。

[摳圖中]

合成幾個GIF

拿第一個GIF分開的PNG圖做成兩個GIF,一個普通播放的,一個特殊交互的。

在鼠標點擊後,設置特殊GIF播放標記,關掉普通GIF播放。在特殊GIF播放完前,再次點擊不會再觸發播放特殊的。通過記錄幀數來判斷是否播放完,播放完特殊的後,再次初始化標記,並且關掉特殊GIF,開啓普通GIF。
——這裏還需要關聯一下frameChanged信號與paintEvent,因爲這個函數並不是每次都會被執行。

//widget.cpp

void Widget::mousePressEvent(QMouseEvent *event){


    if(event->buttons() == Qt::LeftButton){
        //qDebug()<<"flag_clicked=true";
        flag_clicked = true;
        currentPos = event->globalPos();

        if(!flag_special){ //如果之前播放的是普通GIF
            qDebug()<<"special gif";
            flag_special=true;
            movie->stop();
            delete movie;
            movie=new QMovie("../window_try_4/yifulite2.gif");
            movie->setScaledSize(QSize(200,200));//設置GIF大小
            movie->setSpeed(200);//2倍速
            ui->label->setMovie(movie);
            movie->start();
        }

    }
}
void Widget::paintEvent(QPaintEvent *event){

    static int i=0;
    if(flag_special&&i++>=movie->frameCount()){//在播放特殊GIF,並且放完了
        qDebug()<<"normal gif";
        flag_special=false;
        movie->stop();
        delete movie;
        movie=new QMovie("../window_try_4/yifulite1.gif");
        movie->setScaledSize(QSize(200,200));//設置GIF大小
        movie->setSpeed(200);
        ui->label->setMovie(movie);
        movie->start();
        i=0;
    }

}

有點難受。。。摳了一天,摳了快12個小時,做的效果並不好。。。
由於是一張張的託過來做成GIF,所以伊芙利特的位置就不定。比起播放GIF,還是一幀幀的播放比較靠譜

在這裏插入圖片描述

(手很痛,以後再搞)

與任務欄交互

讓伊芙利特落在桌面底下,踩在任務欄上,根據任務欄的高低而起伏。
這是與其他窗口交互的第一步,先與任務欄交互。需要調用windows api,獲取窗口信息。

使用Microsoft spy++ 工具來查找窗口,爲了得到一個窗口信息,首先需要知道該窗口的類名和標題。任務欄的類名是Shell_TrayWnd,標題沒有。
比如下面是使用這個工具來查找伊芙利特窗口(設置窗口名:this->setWindowTitle("伊芙利特");
在這裏插入圖片描述

在pro文件中添加LIBS += user32.lib
添加頭文件#include <Windows.h>

//widget.cpp
	//添加到paintEvent裏
 	 if(!flag_clicked){//鼠標鬆手
        RECT rect;
        ::GetWindowRect(::FindWindow(TEXT("Shell_TrayWnd"), NULL), &rect);
        if(rect.top>500)//保證任務欄在桌面底下,不在其他位置
            move(QPoint(pos().x(),rect.top-225));
    }

在這裏插入圖片描述

與其他窗口碰撞

雙擊後可放縮、關閉

添加其他功能

參考:

QT學習之路之Movie動畫

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章