Qt實現的窗口樣式默認使用的是當前操做系統的原生窗口樣式,在不一樣操做系統下原生窗口樣式顯示的風格是不同的。
能夠爲每一個Widget設置風格:setStyle(QStyle style)
獲取當前平臺支持的原有QStyle樣式QStyleFactory.keys()
對QApplication設置QStyle樣式QApplication.setStyle(QStyleFactory.create(「WindowsXP」))
若是其它Widget沒有設置QStyle,則默認使用QApplication使用的QStyle。git
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QHBoxLayout() label = QLabel("Set Style:",self) combo = QComboBox(self) combo.addItems(QStyleFactory.keys()) # 選擇當前窗口風格 index = combo.findText(QApplication.style().objectName(), Qt.MatchFixedString) # 設置當前窗口風格 combo.setCurrentIndex(index) combo.activated[str].connect(self.onCurrentIndexChanged) self.layout.addWidget(label) self.layout.addWidget(combo) self.setLayout(self.layout) self.setWindowTitle("Application Style") self.resize(300, 100) def onCurrentIndexChanged(self, style): QApplication.setStyle(style) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
PyQt5使用setWindowFlags(Qt.WindowFlags)函數設置窗口樣式。
Qt的窗口類型以下:
Qt.Widget:默認窗口,由最大化、最小化、關閉按鈕
Qt.Window:普通窗口,有最大化、最小化、關閉按鈕
Qt.Dialog:對話框窗口,有問號和關閉按鈕
Qt.Popup:彈出窗口,窗口無邊框
Qt.ToolTip:提示窗口,窗口無邊框,無任務欄
Qt.SplashScreen:閃屏,窗口無邊框,無任務欄
Qt.SubWindow:子窗口,窗口無按鈕,但有標題欄
Qt自定義的頂層窗口外觀標識:
Qt.MSWindowsFixedSizeDialogHint:窗口沒法調整大小
Qt.FrameLessWindowHint:窗口無邊框
Qt.CustomWinodwHint:有邊框但無標題欄和按鈕,不能移動和拖動
Qt.WindowTitleHint:添加一個標題欄和一個關閉按鈕
Qt.WindowSystemMenuHint:添加系統目錄和一個關閉按鈕
Qt.WindowMaximizeButtonHint:激活最大化和關閉按鈕,禁止最小化按鈕
Qt.WindowMinimizeButtonHint:激活最小化和關閉按鈕,禁止最大化按鈕
Qt.WindowMinMaxButtonsHint:激活最大化、最小化和關閉按鈕
Qt.WindowCloseButtonHint:增長一個關閉按鈕
Qt.WindowContextHelpButtonHint:增長問號和關閉按鈕
Qt.WindowStaysOnTopHint:窗口始終處於頂層位置
Qt.WindowStaysOnBottomHint:窗口始終處於底層位置github
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") self.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) self.resize(400, 200) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
自定義一個無邊框、鋪滿整個顯示屏的窗口實現以下:app
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") self.setWindowFlags(Qt.WindowMinMaxButtonsHint | Qt.WindowCloseButtonHint) self.setStyleSheet("background-color:blue;") def showMaximized(self): # 獲取桌面控件 desktop = QApplication.desktop() # 獲取屏幕可顯示矩形區域 rect = desktop.availableGeometry() # 設置窗口尺寸 self.setGeometry(rect) self.show() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.showMaximized() sys.exit(app.exec_())
Qt中有四個圖像類,QPixmap、QImage、QPicture、QBitmap。
QPixmap專爲繪圖而設計,在繪製圖片時須要QPixmap。
QImage提供了一個與硬件無關的圖像表示函數,能夠用於圖片的像素級訪問。
QPicture是繪圖設備類,繼承自QPainter,可使用QPainter的begin函數在QPicture上繪圖,使用end結束繪圖,使用QPicture的save函數將QPainter使用過的繪圖指令保存到文件中。
QBitmap是一個繼承自QPixmap的便利類,提供了1bit深度的二值圖像的類,提供的單×××像能夠用來製做遊標QCursor或者畫刷QBrush。ide
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.pix = QPixmap(400, 400) self.pix.fill(Qt.white) self.lastPoint = QPoint() self.endPoint = QPoint() self.setWindowFlags(Qt.WindowTitleHint) self.resize(400, 400) def paintEvent(self, event): painter = QPainter(self.pix) painter.drawLine(self.lastPoint, self.endPoint) self.lastPoint = self.endPoint painter = QPainter(self) painter.drawPixmap(0, 0, self.pix) def mouseMoveEvent(self, event): if event.buttons() and Qt.LeftButton: self.endPoint = event.pos() self.update() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.lastPoint = event.pos() self.endPoint = self.lastPoint def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.endPoint = event.pos() self.update() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.pix = QPixmap(400, 400) self.pix.fill(Qt.white) self.lastPoint = QPoint() self.endPoint = QPoint() self.setWindowFlags(Qt.WindowTitleHint) self.resize(400, 400) def paintEvent(self, event): painter1 = QPainter(self) x = self.lastPoint.x() y = self.lastPoint.y() w = self.endPoint.x() - x h = self.endPoint.y() - y # 將圖形會值在PixMap畫布 painter2 = QPainter(self.pix) painter2.drawRect(x, y, w, h) # 將pximap繪製到窗口 painter1.drawPixmap(0, 0, self.pix) def mouseMoveEvent(self, event): if event.buttons() and Qt.LeftButton: self.endPoint = event.pos() self.update() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.lastPoint = event.pos() self.endPoint = self.lastPoint def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.endPoint = event.pos() self.update() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
上述代碼中,首先使用painter將圖形繪製在Pixmap上,而後將Pixmap繪製到窗口中。在拖動鼠標繪製矩形的過程當中會出現重影,鼠標拖動過程當中,屏幕會刷新不少次,paintEvent函數會被執行不少次,每次都會繪製一個矩形。
爲了不重影,可使用雙緩衝繪製技術。即便用兩塊畫布,pix和tempPix,tempPix做爲臨時緩衝區,當拖動鼠標繪製矩形時,將內容先繪製到tempPix上,而後再將tempPix繪製到界面窗口。當釋放鼠標完成矩形繪製時,將tempPix的內容複製到pix緩衝區,最終完成繪製到窗口。函數
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.pix = QPixmap(400, 400) self.pix.fill(Qt.white) self.lastPoint = QPoint() self.endPoint = QPoint() self.setWindowFlags(Qt.WindowTitleHint) self.resize(400, 400) self.isDrawing = False self.tempPix = QPixmap() def paintEvent(self, event): painter = QPainter(self) x = self.lastPoint.x() y = self.lastPoint.y() w = self.endPoint.x() - x h = self.endPoint.y() - y if self.isDrawing: self.tempPix = self.pix pp = QPainter(self.tempPix) pp.drawRect(x, y, w, h) painter.drawPixmap(0, 0, self.tempPix) else: pp = QPainter(self.pix) pp.drawRect(x, y, w, h) painter.drawPixmap(0, 0, self.pix) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.lastPoint = event.pos() self.endPoint = self.lastPoint self.isDrawing = True def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.endPoint = event.pos() self.update() self.isDrawing = False if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
QSS(Qt Style Sheets),即Qt樣式表,是用來自定義控件外觀的一種機制。QSS語法規則與CSS大致相同,QSS樣式由兩部分組成,選擇器用於指定哪些控件受到影響,聲明用於指定哪些屬性應該在控件上進行設置。聲明部分是一系列的「屬性:值」,使用分號分隔各個不一樣的屬性值對,使用大括號將全部的聲明包括在內。QPushButton{color:red;}
表示設置QPushButton及其子類全部實例的前景色爲紅色,QPushButton表示選擇器,指定全部的QPushButton類及其子類都會受到影響。
可使用多個選擇器指定相關的聲明,使用逗號將各個選擇器分隔,如QPushButton,QLineEdit{color:red;}
ui
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) button = QPushButton("Button") self.layout = QHBoxLayout() self.layout.addWidget(button) self.setLayout(self.layout) qss = "QPushButton{color:red;}" self.setStyleSheet(qss) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
QSS選擇器有以下幾種類型:
一、通配選擇器:*
,匹配全部的控件
二、類型選擇器,如QPushButton,用於匹配全部的類及其子類的實例。
三、屬性選擇器:匹配全部的屬性及屬性值的實例,如QPushButton[name=」okButton」]將匹配全部的name屬性爲okButton的按鈕實例。
四、類選擇器:.ClassName,如.QPushButton用於匹配全部的QPushButton實例,但不匹配其子類。
五、ID選擇器:#objectName,如#okButton匹配全部的ID爲okButton的控件,ID即爲obejctName。
六、後代選擇器:如QDialog QPushButton,匹配全部的QDialog容器中包含的QPushButton,不論是直接的仍是間接的。
七、子選擇器:如QDialog > QPushButton,匹配全部的QDialog容器中包含的QPushButton,要求QPushButton的直接父容器是QDialog。
三、QSS子控件
QSS子控件是一種選擇器,一般應用在複雜控件上,如QComboBox,QComboBox有一個矩形的外邊框,右邊有一個下拉箭頭,點擊後會彈出下拉列表。
::drop-down子控件選擇器能夠與選擇器組合使用,QComboBox#combo::drop-down{imge:url(dropdown.png)}
表示爲指定ID爲combo的QComboBox控件的下拉箭頭自定義圖標。url
QSS僞狀態選擇器是以:開頭的一個選擇表達式,如:hover,表示當鼠標通過時的狀態。僞狀態選擇器限制了當控件處於某種狀態時纔可使用的QSS規則,僞狀態只能描述一個控件或複合控件的子控件狀態,所以只能放在選擇器的最後面。QComboBox::drop-down:hover{background-color:red;}
操作系統
QDarkStyleSheet是一個用於PyQt應用的深黑色樣式表。
GitHub:
https://github.com/ColinDuquesnoy/QDarkStyleSheet設計
窗口背景主要包括背景色和背景圖片。設置窗口背景主要有三種方法:QSS設置窗口背景;QPalette設置窗口背景;paintEvent函數內部使用QPainter繪製窗口背景。code
經過QSS能夠設置窗口的背景色或背景圖片。
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setObjectName("mainWindow") qss = "QWidget#mainWindow{background-color:black;}" # qss = "QWidget#mainWindow{border-image:url(background.png);}" self.setStyleSheet(qss) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
使用QPalette設置窗口背景顏色。
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) palette = QPalette() palette.setColor(QPalette.Background, Qt.black) self.setPalette(palette) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
使用QPalette設置窗口背景圖片時,須要考慮背景圖片的尺寸,當背景圖片的寬度和高度大於窗口的寬度和高度時,背景圖片將會平鋪整個窗口;當背景圖片的寬度和高度小於窗口的寬度和高度時,則加載多個背景圖片。
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) palette = QPalette() palette.setBrush(QPalette.Background, QBrush(QPixmap("background.png"))) self.setPalette(palette) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
在paintEvent函數內部繪製背景色:
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") def paintEvent(self, event): painter = QPainter(self) painter.setBrush(Qt.black) painter.drawRect(self.rect()) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
在paintEvent函數內部繪製背景圖片:
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") def paintEvent(self, event): painter = QPainter(self) pixmap = QPixmap("background.png") painter.drawPixmap(self.rect(), pixmap) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") self.layout = QVBoxLayout() label = QLabel() label.setStyleSheet("QLabel{border-image:url(background.png);}") label.setFixedHeight(400) label.setFixedWidth(600) self.layout.addWidget(label) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") self.layout = QVBoxLayout() button = QPushButton("Button") button.setMaximumSize(60, 30) button.setObjectName("okButton") button.setStyleSheet("QPushButton#okButton{border-image:url(background.png);}") self.layout.addWidget(button) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") self.layout = QVBoxLayout() label = QLabel() img = QImage("background.png") result = img.scaled(label.width(), label.height(),Qt.IgnoreAspectRatio, Qt.SmoothTransformation) label.setPixmap(QPixmap.fromImage(result)) self.layout.addWidget(label) self.setLayout(self.layout) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
若是窗口是透明的,經過窗口能夠看到桌面,要想實現窗口的透明效果,須要設置窗口透明度。透明度取值範圍爲0(徹底透明)到1(不透明)。
import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class MainWindow(QWidget): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("MainWindow") self.setWindowOpacity(0.5) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
Qt中,爲了下降耦合性,將UI代碼與業務邏輯代碼進行分離,一般會定義QSS文件,編寫各類控件的樣式,最後使用QApplication.setStyleSheet或QWidget.setStyleSheet設置QSS。
一般編寫QSS文件須要加載到qrc資源文件中,而後編寫一個公用類加載QSS。
class CommonHelper(object): @staticmethod def setStyleSheet(filename): if filename is not None: style = "" with open(filename, "r") as f: style = f.read() qApp.setStyleSheet(style)