1. 程式人生 > >Pyqt實現無邊框視窗拖動及改變視窗大小

Pyqt實現無邊框視窗拖動及改變視窗大小

做個記錄,繪製邊框陰影可以忽略這裡不是主要

根據網上某位仁兄Qt的實現轉過來的大笑,上完整程式碼

# coding:utf-8
from PyQt4.Qt import *
import sys

PADDING=4 
sys.setrecursionlimit(10000)
class ShadowWidget(QWidget):
    def __init__(self,parent=None):
        super(ShadowWidget,self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowSystemMenuHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.SHADOW_WIDTH=0   #邊框距離
        self.isLeftPressDown = False #滑鼠左鍵是否按下
        self.dragPosition=0     #拖動時座標
        self.Numbers = self.enum(UP=0, DOWN=1, LEFT=2, RIGHT=3, LEFTTOP=4, LEFTBOTTOM=5, RIGHTBOTTOM=6, RIGHTTOP=7, NONE=8) #列舉引數
        self.setMinimumHeight(500)  #窗體最小高度
        self.setMinimumWidth(1000) #窗體最小寬度
        self.dir=self.Numbers.NONE #初始滑鼠狀態
        self.setMouseTracking(True)

    #繪製邊框陰影
    def drawShadow(self,painter):
        #繪製左上角、左下角、右上角、右下角、上、下、左、右邊框
        self.pixmaps=QStringList()
        self.pixmaps.append(QString("./img/border/left_top.png"))
        self.pixmaps.append(QString("./img/border/left_bottom.png"))
        self.pixmaps.append(QString("./img/border/right_top.png"))
        self.pixmaps.append(QString("./img/border/right_bottom.png"))
        self.pixmaps.append(QString("./img/border/top_mid.png"))
        self.pixmaps.append(QString("./img/border/bottom_mid.png"))
        self.pixmaps.append(QString("./img/border/left_mid.png"))
        self.pixmaps.append(QString("./img/border/right_mid.png"))
        painter.drawPixmap(0, 0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[0]))   #左上角
        painter.drawPixmap(self.width()-self.SHADOW_WIDTH, 0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[2]))   #右上角
        painter.drawPixmap(0,self.height()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[1]))   #左下角
        painter.drawPixmap(self.width()-self.SHADOW_WIDTH, self.height()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[3]))  #右下角
        painter.drawPixmap(0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH, QPixmap(self.pixmaps[6]).scaled(self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH)) #左
        painter.drawPixmap(self.width()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH, QPixmap(self.pixmaps[7]).scaled(self.SHADOW_WIDTH, self.height()- 2*self.SHADOW_WIDTH)) #右
        painter.drawPixmap(self.SHADOW_WIDTH, 0, self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[4]).scaled(self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH)) #上
        painter.drawPixmap(self.SHADOW_WIDTH, self.height()-self.SHADOW_WIDTH, self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[5]).scaled(self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH))   #下

    #列舉引數
    def enum(self,**enums):
        return type('Enum', (), enums)

    def region(self,cursorGlobalPoint):
        #獲取窗體在螢幕上的位置區域,tl為topleft點,rb為rightbottom點
        rect = self.rect()
        tl = self.mapToGlobal(rect.topLeft())
        rb = self.mapToGlobal(rect.bottomRight())

        x = cursorGlobalPoint.x()
        y = cursorGlobalPoint.y()

        if(tl.x() + PADDING >= x and tl.x() <= x and tl.y() + PADDING >= y and tl.y() <= y):
            #左上角
            self.dir = self.Numbers.LEFTTOP
            self.setCursor(QCursor(Qt.SizeFDiagCursor))   #設定滑鼠形狀
        elif(x >= rb.x() - PADDING and x <= rb.x() and y >= rb.y() - PADDING and y <= rb.y()):
            #右下角
            self.dir = self.Numbers.RIGHTBOTTOM
            self.setCursor(QCursor(Qt.SizeFDiagCursor))
        elif(x <= tl.x() + PADDING and x >= tl.x() and y >= rb.y() - PADDING and y <= rb.y()):
            #左下角
            self.dir = self.Numbers.LEFTBOTTOM
            self.setCursor(QCursor(Qt.SizeBDiagCursor))
        elif(x <= rb.x() and x >= rb.x() - PADDING and y >= tl.y() and y <= tl.y() + PADDING):
            #右上角
            self.dir = self.Numbers.RIGHTTOP
            self.setCursor(QCursor(Qt.SizeBDiagCursor))
        elif(x <= tl.x() + PADDING and x >= tl.x()):
            #左邊
            self.dir = self.Numbers.LEFT
            self.setCursor(QCursor(Qt.SizeHorCursor))
        elif( x <= rb.x() and x >= rb.x() - PADDING):
            #右邊

            self.dir = self.Numbers.RIGHT
            self.setCursor(QCursor(Qt.SizeHorCursor))
        elif(y >= tl.y() and y <= tl.y() + PADDING):
            #上邊
            self.dir = self.Numbers.UP
            self.setCursor(QCursor(Qt.SizeVerCursor))
        elif(y <= rb.y() and y >= rb.y() - PADDING):
            #下邊
            self.dir = self.Numbers.DOWN
            self.setCursor(QCursor(Qt.SizeVerCursor))
        else:
            #預設
            self.dir = self.Numbers.NONE
            self.setCursor(QCursor(Qt.ArrowCursor))

    def mouseReleaseEvent(self,event):
        if(event.button() == Qt.LeftButton):
            self.isLeftPressDown = False
            if(self.dir != self.Numbers.NONE):
                self.releaseMouse()
                self.setCursor(QCursor(Qt.ArrowCursor))

    def mousePressEvent(self,event):
        if(event.button()==Qt.LeftButton):
            self.isLeftPressDown=True
            if(self.dir != self.Numbers.NONE):
                self.mouseGrabber()
            else:
                self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()

    def mouseMoveEvent(self,event):
        gloPoint = event.globalPos()
        rect = self.rect()
        tl = self.mapToGlobal(rect.topLeft())
        rb = self.mapToGlobal(rect.bottomRight())

        if(not self.isLeftPressDown):
            self.region(gloPoint)  
        else:
            if(self.dir != self.Numbers.NONE):
                rmove=QRect(tl, rb)
                if(self.dir==self.Numbers.LEFT):
                    if(rb.x() - gloPoint.x() <= self.minimumWidth()):
                        rmove.setX(tl.x())
                    else:
                        rmove.setX(gloPoint.x())
                elif(self.dir==self.Numbers.RIGHT):
                    print u"youbian"
                    rmove.setWidth(gloPoint.x() - tl.x())
                elif(self.dir==self.Numbers.UP):
                    if(rb.y() - gloPoint.y() <= self.minimumHeight()):
                        rmove.setY(tl.y())
                    else:
                        rmove.setY(gloPoint.y())
                elif(self.dir==self.Numbers.DOWN):
                    rmove.setHeight(gloPoint.y() - tl.y())
                elif(self.dir==self.Numbers.LEFTTOP):
                    if(rb.x() - gloPoint.x() <= self.minimumWidth()):
                        rmove.setX(tl.x())
                    else:
                        rmove.setX(gloPoint.x())
                    if(rb.y() - gloPoint.y() <= self.minimumHeight()):
                        rmove.setY(tl.y())
                    else:
                        rmove.setY(gloPoint.y())
                elif(self.dir==self.Numbers.RIGHTTOP):
                    rmove.setWidth(gloPoint.x() - tl.x())
                    rmove.setY(gloPoint.y())
                elif(self.dir==self.Numbers.LEFTBOTTOM):
                    rmove.setX(gloPoint.x())
                    rmove.setHeight(gloPoint.y() - tl.y())
                elif(self.dir==self.Numbers.RIGHTBOTTOM):
                    rmove.setWidth(gloPoint.x() - tl.x())
                    rmove.setHeight(gloPoint.y() - tl.y())
                else:
                   pass
                self.setGeometry(rmove)
            else:
                self.move(event.globalPos() - self.dragPosition)
                event.accept()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    shadow = ShadowWidget()
    shadow.show()
    sys.exit(app.exec_())


相關推薦

Pyqt實現邊框視窗改變視窗大小

做個記錄,繪製邊框陰影可以忽略這裡不是主要 根據網上某位仁兄Qt的實現轉過來的,上完整程式碼 # coding:utf-8 from PyQt4.Qt import * import sys PADDING=4 sys.setrecursionlimit(10000)

Winform邊框視窗改變視窗大小

Winform無邊框視窗(FormBorderStyle屬性為None)預設是不可以拖動或者改變大小的。 1.      拖動無邊框視窗改變位置 方法1:通過mousedown、mousemove、mouseup、事件來改變視窗Location。 方法2:通過截獲訊息,進行

pyqt5_控件_自定義邊框窗體

spa 窗體拖動 ica 定義 event sta track gets button from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * import sy

Qt quick實現邊框拽風格

由來:     現在大量的軟體採用簡潔的風格,即移除系統的標題欄及邊框並自己實現標題欄以達到定製的目的,由於我們寫要用Qt寫一個類似IM的軟體,故有此需求。 方法: 去除系統邊框比較簡單,setFlags(Qt::Window | Qt::Framel

Qt 邊框無非客戶區視窗、縮放改變大小、滑鼠變形,windows同款,完美實現

簡單點說,是在windows下實現視窗拖動和改變大小,一種方法是過載mousePressEvent系列全家福函式,然後在mouseMoveEvent中實現邊移滑鼠視窗就一邊重繪。這種方法網上資料很多,見下:這種方法缺點是移動的時候視窗閃爍厲害。摒棄。但該方法給了一個很好的思路

pyqt實現自定義視窗大小,到桌面邊框自動影藏

#-*- coding:utf-8 -*- from PyQt4.QtGui import * from PyQt4.QtCore import * import sys from ctypes import * from time import sleep impor

Qt邊框視窗實現改變大小(修改)

先前發的程式碼有問題,主要是當視窗達到最大和最小尺寸的時候視窗改變大小的實際效果不符合邏輯,現在修改以後沒問題了。 下面我主要分享一下我的思考過程: 當我們改變一個視窗的大小時,如果視窗的寬度(高度)已經最小(最大),那麼很顯然只能放大(減小),同時拖動4個

C# 鼠標點擊移動窗體代碼,可以實現邊框窗體的

點擊 obj cat += tar sender see sed false private static bool IsDrag = false; private int enterX; private int enterY;

C#Winform實現邊框窗體滑鼠

在有時候我們為了實現軟體的美觀,我們需要把窗體的邊框隱藏,但是問題也會隨之而來,在屬性中設定了FormBorderStyle應該為None,邊框便可以隱藏,但是我們在使用軟體時卻無法拖動窗體,

JFrame實現邊框實現實現關閉按鈕,開啟實現儲存檔案到本地,實現頭像放大功能,實現圖片瀏覽器

package SwingTest3; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.even

winform 邊框窗體實現

sed style windows part fse use left clas void using System; using System.Collections.Generic; using System.ComponentModel; using Syst

Qt 標題邊框程序的改變大小

又一 through poi rip 有時 target ram internal 以及 最近做項目遇到的問題,總結下。 有時候我們覺得系統的標題欄和按鈕太醜太呆板,想做自己的標題欄以及最大化、最小化、關閉,菜單按鈕,我們就需要 [cpp] view p

MFC 中實現在客戶區視窗的方法總結

VC++實現無標題欄對話方塊的拖動 其實說白了就是欺騙,欺騙誰了?呵呵,當然是欺騙windows,本來是移動標題欄可以拖動窗體,那麼我們現在是拖動客戶區來移動,當我們拖動標題欄的時候windows產生一個WM_NCHITTEST訊息,這個訊息確定滑鼠點選的哪個位置,這個訊息

C#如何實現控制元件移動

1 //在picturebox滑鼠移動 2 private void picBox_MouseMove(object sender, MouseEventArgs e) 3 { 4 if (MoveFlag) 5 { 6 picBox.Left += Convert.To

ActionScript 3.0對文字實現Tween類特效處理

先說明一下Tween類: 我們看一下Tween類的建構函式: Tween(obj:Object, prop:String, func:Function, begin:Number,finish:Number, duration:Number, useSeconds:Bool

C#實現邊框winfrom介面

winfrom介面其實也可以扁平化,讓外觀提升一個level,整體為360風格。先上圖: 首先在介面屬性中,將FormBorderStyle設定為None,然後介面變為正常的Panel。此時需要新增頂欄拖動、最小化和關閉按鈕。 [DllImp

Android 簡單實現可全屏,可點選的View

首先,我們都知道,拖動一個view,需要給它設定touchListener,或者重寫他的touchEvent。我們以ImageView為例,自定義一個DragView,繼承ImageView。 單純的只是想讓view拖動,我們只需要在ACTION_DOWN

table實現列寬的效果

部門有一個專案介面用的html,所有的列表都用的原生table控制元件,一個同事找到我問有沒有辦法實現table的列寬拖動,好幾年沒摸過前臺了,還真給問住了,經過網上查詢資料等,最終解決,記錄下: <!DOCTYPE html> &l

Qt實現邊框窗體的移動

本文內容,基本參考自網際網路,所以定義為轉載。 我們知道360安全衛士的介面是沒有外邊框的,去除外邊框 setWindowFlags(Qt::FramelessWindowHint);  但是去除邊框之後,無法移動整個窗體,為了實現這個移動效果,需要重新實現三個函式

Qt 之自定義介面(實現邊框、可移動)

簡述 UI設計是指對軟體的人機互動、操作邏輯、介面美觀的整體設計。好的UI設計不僅是讓軟體變得有個性、有品位,還要讓軟體的操作變得舒適簡單、自由,充分體現軟體的定位和特點。 愛美之心人皆有之。其實軟體介面就像工業造型一樣,是產品的重要賣點。一個產品擁有美觀的