1. 程式人生 > >Qt實現半透明、無邊框、可自由移動、不規則的窗體

Qt實現半透明、無邊框、可自由移動、不規則的窗體

先出示效果圖一張,如果不是讀者需要的,讀者可以看完效果圖之後就關閉本網頁啦。

功能要點

  • 視窗無邊框
  • 可自由拖動
  • 背景透明度自定義
  • 邊框可設定為異形

實現步驟

                第1步:新建一個QWidget的子類,這裡命名為BaseWidget

                第2步:設定關鍵成員

  private:
    QRect m_areaMovable;//可移動視窗的區域,滑鼠只有在該區域按下才能移動視窗
    bool m_bPressed;//滑鼠按下標誌(不分左右鍵)
    QPoint m_ptPress;//滑鼠按下的初始位置

              第3步:實現三個虛擬函式

                          (1)標頭檔案裡新增以下程式碼

  protected:
    void mousePressEvent(QMouseEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
            (2)cpp檔案裡新增
BaseWidget::BaseWidget(QWidget *parent) :
    QWidget(parent)
{
    //設定無邊框透明
    setWindowFlags(Qt::FramelessWindowHint|Qt::Tool);//無邊框
    this->setStyleSheet(QString("background-color: rgb(0, 255, 0);"));

    m_bPressed = false;

}

void BaseWidget::setAreaMovable(const QRect rt)
{
    if(m_areaMovable != rt)
    {
        m_areaMovable = rt;
    }
}

void BaseWidget::mousePressEvent(QMouseEvent *e)
{
    //滑鼠左鍵
    if(e->button() == Qt::LeftButton)
    {
        m_ptPress = e->pos();
        m_bPressed = m_areaMovable.contains(m_ptPress);
        setAreaMovable(this->rect());
    }
}

void BaseWidget::mouseMoveEvent(QMouseEvent *e)
{
    if(m_bPressed)
    {
        move(pos() + e->pos() - m_ptPress);
    }
}

void BaseWidget::mouseReleaseEvent(QMouseEvent *e)
{
    m_bPressed = false;

}

在MainWindow.cpp中使用:

    bsw = new BaseWidget(this);
    bsw->resize(100,100);
    bsw->show();

以上程式碼可以實現:無邊框、透明、可拖動

但是呢,滑鼠只有落在左上角區域時才能拖動,於是改進一步:

void BaseWidget::showEvent(QShowEvent *)
{

    setAreaMovable(this->rect());

}

這樣就可以實現點選窗體的任何處進行拖動啦

不過可能有人的需求是實現異形視窗,我的demo思路是:新建一個QLabel 子類

,然後設定視窗背景透明,新增一個png圖片。

異形無邊框半透明視窗實現如下:

                    第1步:在作圖軟體中製作一張大小合適的png圖片

                   第2步:讀取圖片並顯示到控制元件上

在建構函式裡新增:

    QImage img;
    img.load("arrowhead.png");
    this->setPixmap(QPixmap::fromImage(img));

最終效果如下:

在分享程式碼之前,想先分享總結:

第1個坑:原本我是想把控制元件設定為懸浮的,於是新建了QDialog子類還設定了setWindowFlags(Qt::Popup),但是這樣一來,這個視窗的優先順序就凌駕於其他所有視窗以及所有控制元件之上,意味著,這個不能點選關閉的視窗還攔著我不讓我與其他控制元件 產生互動。

後來使用了Qt::Tool這個flag,情況好轉。

第2個坑:在往QLabel子類中設定圖片時,使用了

    QPicture temp;
    temp.load("arrowhead.png");
    this->setPixmap(temp);
但是出現了報錯:QPicturePaintEngine::checkFormat: Incorrect header

我現在不是很懂這是為啥……【擦汗】,但是我找到了可以繞開它達成目的的方法:

    QImage img;
    img.load("arrowhead.png");
    this->setPixmap(QPixmap::fromImage(img));
說完了兩個坑之後,在這裡我推薦大家一款軟體,下載免積分,可以用來在windows平臺上錄製gif圖,網址如下:

最後,結尾了,感謝網上那些無私分享技術的人,本次學習參考了以下關鍵博文:

最後,我的demo程式碼傳送門: