警告
本节包含自动从C++翻译到Python的代码片段,可能包含错误。
图像合成示例#
展示了如何使用QPainter中的合成模式。
图像合成示例允许用户使用QPainter支持的任何合成模式组合图像,详细描述在《合成模式》中。
设置资源文件#
图像合成示例需要两个源图像,分别是butterfly.png和checker.png,它们嵌入在imagecomposition.qrc文件中。该文件包含以下代码
<Code snippet "/data/qt5-full-670/6.7.0/Src/qtbase/painting/imagecomposition/imagecomposition.qrc" not found>
有关资源文件的更多信息,请参阅《Qt资源系统》。
ImageComposer类定义#
ImageComposer
类是QWidget
的子类,实现了三个私有槽,分别为chooseSource("
、chooseDestination()
和recalculateResult()
。
class ImageComposer(QWidget): Q_OBJECT # public ImageComposer() # private slots def chooseSource(): def chooseDestination(): def recalculateResult():
此外,ImageComposer
包含五个私有函数,分别为addOp()
、chooseImage()
、loadImage()
、currentMode()
和imagePos()
,以及私有实例的QToolButton
、QComboBox
、QLabel
和QImage
。
# private def addOp(mode, name): def chooseImage(title, image, button): def loadImage(fileName, image, button): QPainter.CompositionMode currentMode() imagePos = QPoint(QImage image) sourceButton = QToolButton() destinationButton = QToolButton() operatorComboBox = QComboBox() equalLabel = QLabel() resultLabel = QLabel() sourceImage = QImage() destinationImage = QImage() resultImage = QImage()
ImageComposer类实现#
我们声明了一个名为resultSize
的QSize对象,作为静态常量,宽度和高度均为200。
resultSize = QSize(200, 200)
在构造函数中,我们实例化了一个QToolButton
对象,名为sourceButton
,并将其iconSize
属性设置为resultSize
。然后使用addOp()
函数实例化了operatorComboBox
,并使用该函数填充。此函数接受QPainter::CompositionMode,名为mode
,以及一个表示合成模式名称的QString,名为name
。
def __init__(self): sourceButton = QToolButton() sourceButton.setIconSize(resultSize) operatorComboBox = QComboBox() addOp(QPainter.CompositionMode_SourceOver, tr("SourceOver")) addOp(QPainter.CompositionMode_DestinationOver, tr("DestinationOver")) addOp(QPainter.CompositionMode_Clear, tr("Clear")) addOp(QPainter.CompositionMode_Source, tr("Source")) addOp(QPainter.CompositionMode_Destination, tr("Destination")) addOp(QPainter.CompositionMode_SourceIn, tr("SourceIn")) addOp(QPainter.CompositionMode_DestinationIn, tr("DestinationIn")) addOp(QPainter.CompositionMode_SourceOut, tr("SourceOut")) addOp(QPainter.CompositionMode_DestinationOut, tr("DestinationOut")) addOp(QPainter.CompositionMode_SourceAtop, tr("SourceAtop")) addOp(QPainter.CompositionMode_DestinationAtop, tr("DestinationAtop")) addOp(QPainter.CompositionMode_Xor, tr("Xor")) addOp(QPainter.CompositionMode_Plus, tr("Plus")) addOp(QPainter.CompositionMode_Multiply, tr("Multiply")) addOp(QPainter.CompositionMode_Screen, tr("Screen")) addOp(QPainter.CompositionMode_Overlay, tr("Overlay")) addOp(QPainter.CompositionMode_Darken, tr("Darken")) addOp(QPainter.CompositionMode_Lighten, tr("Lighten")) addOp(QPainter.CompositionMode_ColorDodge, tr("ColorDodge")) addOp(QPainter.CompositionMode_ColorBurn, tr("ColorBurn")) addOp(QPainter.CompositionMode_HardLight, tr("HardLight")) addOp(QPainter.CompositionMode_SoftLight, tr("SoftLight")) addOp(QPainter.CompositionMode_Difference, tr("Difference")) addOp(QPainter.CompositionMode_Exclusion, tr("Exclusion"))
实例化了 destinationButton
并设置了其 iconSize
属性为 resultSize
。同时创建了 QLabel
对象 equalLabel
和 resultLabel
,并且设置了 resultLabel
的 minimumWidth
。
destinationButton = QToolButton() destinationButton.setIconSize(resultSize) equalLabel = QLabel(tr("=")) resultLabel = QLabel() resultLabel.setMinimumWidth(resultSize.width())
我们将以下信号连接到相应的槽函数
将
sourceButton
的clicked()
信号连接到chooseSource()
,将
operatorComboBox
的activated()
信号连接到recalculateResult()
,以及将
destinationButton
的clicked()
信号连接到chooseDestination()
。sourceButton.clicked.connect( self.chooseSource) operatorComboBox.activated.connect( self.recalculateResult) destinationButton.clicked.connect( self.chooseDestination)
使用了 QGridLayout
对象 mainLayout
来放置所有的小部件。请注意,将 mainLayout
的 sizeConstraint
属性设置为 SetFixedSize
,这意味着 ImageComposer
的大小不能被调整。
mainLayout = QGridLayout() mainLayout.addWidget(sourceButton, 0, 0, 3, 1) mainLayout.addWidget(operatorComboBox, 1, 1) mainLayout.addWidget(destinationButton, 0, 2, 3, 1) mainLayout.addWidget(equalLabel, 1, 3) mainLayout.addWidget(resultLabel, 0, 4, 3, 1) mainLayout.setSizeConstraint(QLayout.SetFixedSize) setLayout(mainLayout)
创建了一个 QImage
对象,resultImage
,并调用了两次 loadImage()
函数来加载 imagecomposition.qrc 文件中的两个图像文件。然后,我们将 windowTitle
属性设置为“Image Composition”。
resultImage = QImage(resultSize, QImage.Format_ARGB32_Premultiplied) loadImage(":/images/butterfly.png", sourceImage, sourceButton) loadImage(":/images/checker.png", destinationImage, destinationButton) setWindowTitle(tr("Image Composition"))
chooseSource()
和 chooseDestination()
是一些方便的函数,它们使用特定的参数调用 chooseImage()
。
def chooseSource(self): chooseImage(tr("Choose Source Image"), sourceImage, sourceButton) def chooseDestination(self): chooseImage(tr("Choose Destination Image"), destinationImage, destinationButton)
chooseImage()
函数根据 title
,image
和 button
来加载用户选择的图像。
def chooseImage(self, title, image,): QToolButton button) fileName = QFileDialog.getOpenFileName(self, title) if not fileName.isEmpty(): loadImage(fileName, image, button)
recalculateResult()
函数用于计算并显示用户选择的组合模式下的两个图像组合的结果。
def recalculateResult(self): QPainter.CompositionMode mode = currentMode() painter = QPainter(resultImage) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.fillRect(resultImage.rect(), Qt.transparent) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawImage(0, 0, destinationImage) painter.setCompositionMode(mode) painter.drawImage(0, 0, sourceImage) painter.setCompositionMode(QPainter.CompositionMode_DestinationOver) painter.fillRect(resultImage.rect(), Qt.white) painter.end() resultLabel.setPixmap(QPixmap.fromImage(resultImage))
addOp()
函数用于向 operatorComboBox
添加一个项目,使用 QComboBox
的 addItem
方法。此函数接受一个 QPainter::CompositionMode,mode
,以及一个 QString,name
。矩形以 Qt::Transparent 填充,然后绘制 sourceImage
和 destinationImage
,最后在 resultLabel
上显示。
def addOp(self, mode, name): operatorComboBox.addItem(name, mode)
loadImage()
函数使用 fillRect() 绘制透明背景,并使用 drawImage() 在中央位置绘制 image
。然后,将此 image
设置为 button
的图标。
def loadImage(self, fileName, image,): QToolButton button) image.load(fileName) # Scale the image to given size image = image.scaled(resultSize, Qt.KeepAspectRatio) fixedImage = QImage(resultSize, QImage.Format_ARGB32_Premultiplied) painter = QPainter(fixedImage) painter.setCompositionMode(QPainter.CompositionMode_Source) painter.fillRect(fixedImage.rect(), Qt.transparent) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.drawImage(imagePos(image), image) painter.end() button.setIcon(QPixmap.fromImage(fixedImage)) image = fixedImage recalculateResult()
currentMode()
函数返回在 operatorComboBox
中选中的合成模式。
QPainter.CompositionMode ImageComposer.currentMode() return (QPainter.CompositionMode) operatorComboBox.itemData(operatorComboBox.currentIndex()).toInt()
我们使用 imagePos()
函数确保 QToolButton
对象,sourceButton
和 destinationButton
,的图像居中。
def imagePos(self, QImage image): return QPoint((resultSize.width() - image.width()) / 2, (resultSize.height() - image.height()) / 2)
`` main()``
函数#
main()
函数创建 QApplication
和 ImageComposer
的实例,并调用其 show()
方法。
if __name__ == "__main__": app = QApplication([]) composer = ImageComposer() composer.show() sys.exit(app.exec())