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)