import sys from PyQt5 import QtCore, QtGui,QtWidgets class Widget(QtWidgets.QWidget): def __init__(self, parent=None): super(Widget, self).__init__(parent) self.setMinimumSize(600,500) self.transform = QtGui.QTransform() self.viewport = QtCore.QRect() self.window = QtCore.QRect() self.poslist = [] self.setToolTip("click me") self.setAttribute(QtCore.Qt.WA_StyledBackground,True) self.setStyleSheet("background-color:grey;") def setTransform(self, trans): self.transform = trans self.update() def setViewPort(self, rect): self.viewport = rect self.update() def setWindow(self, rect): self.window = rect self.update() def clear(self): self.poslist = [] self.update() def paintEvent(self, evt): painter = QtGui.QPainter(self) painter.setRenderHint(QtGui.QPainter.Antialiasing, False) print('|'*50) # trans = painter.worldTransform() # trans = painter.deviceTransform() trans = painter.transform() print(trans.m11(), trans.m12(), trans.m13(), ) print(trans.m21(), trans.m22(), trans.m23(), ) print(trans.m31(), trans.m32(), trans.m33()) for pos in self.poslist: self.doPaint(painter, pos, "original") if not self.viewport.isNull(): painter.setViewport(self.viewport) if not self.window.isNull(): painter.setWindow(self.window) print('+'*50) print(painter.viewport()) print(painter.window()) print('-'*50) # trans = painter.worldTransform() # trans = painter.deviceTransform() trans = painter.transform() print(trans.m11(), trans.m12(), trans.m13(), ) print(trans.m21(), trans.m22(), trans.m23(), ) print(trans.m31(), trans.m32(), trans.m33()) print('*' * 50) trans = self.transform print(trans.m11(), trans.m12(), trans.m13(), ) print(trans.m21(), trans.m22(), trans.m23(), ) print(trans.m31(), trans.m32(), trans.m33()) painter.setTransform(self.transform) # trans = painter.combinedTransform().inverted()[0] trans = painter.transform().inverted()[0] print('='*50) print(trans.m11(),trans.m12(),trans.m13(),) print(trans.m21(),trans.m22(),trans.m23(),) print(trans.m31(),trans.m32(),trans.m33()) for pos in self.poslist: self.doPaint(painter, trans.map(pos), "with transform") def mousePressEvent(self, evt): self.poslist.append(evt.pos()) self.update() return super(Widget, self).mousePressEvent(evt) def doPaint(self, painter, pos, flag): x, y = pos.x(), pos.y() painter.save() trans = painter.transform() print(trans.m11(), trans.m22(), ) painter.drawLine(QtCore.QLineF(x-10, y, x+10, y)) painter.drawLine(QtCore.QLineF(x, y-10, x, y+10)) painter.setPen(QtCore.Qt.blue); painter.drawText(x, y, flag) painter.restore() class Dialog(QtWidgets.QDialog): def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.widget = Widget() grid = QtWidgets.QGridLayout() self.m11Edit = self.createEdit(-300, 300, 1, grid, 0, 0) self.m12Edit = self.createEdit(-300, 300, 0, grid, 0, 1) self.m13Edit = self.createEdit(-300, 300, 0, grid, 0, 2) self.m21Edit = self.createEdit(-300, 300, 0, grid, 1, 0) self.m22Edit = self.createEdit(-300, 300, 1, grid, 1, 1) self.m23Edit = self.createEdit(-300, 300, 0, grid, 1, 2) self.m31Edit = self.createEdit(-300, 300, 0, grid, 2, 0) self.m32Edit = self.createEdit(-300, 300, 0, grid, 2, 1) self.m33Edit = self.createEdit(-300, 300, 1, grid, 2, 2) self.transformOkButton = QtWidgets.QPushButton("Use This Transform") grid.addWidget(self.transformOkButton, 3, 0, 1, 3) grid2 = QtWidgets.QGridLayout() self.vxEdit = self.createEdit(-1, 800, 0, grid2, 0, 0, False) self.vyEdit = self.createEdit(-1, 800, 0, grid2, 0, 1, False) self.vwEdit = self.createEdit(-1, 800, 600, grid2, 0, 2, False) self.vhEdit = self.createEdit(-1, 800, 500, grid2, 0, 3, False) self.viewportOkButton = QtWidgets.QPushButton("Use This Viewport") grid2.addWidget(self.viewportOkButton, 1, 0, 1, 4) grid3 = QtWidgets.QGridLayout() self.wxEdit = self.createEdit(-800, 800, 0, grid3, 0, 0, False) self.wyEdit = self.createEdit(-800, 800, 0, grid3, 0, 1, False) self.wwEdit = self.createEdit(-1, 800, 600, grid3, 0, 2, False) self.whEdit = self.createEdit(-1, 800, 500, grid3, 0, 3, False) self.windowOkButton = QtWidgets.QPushButton("Use This Window") grid3.addWidget(self.windowOkButton, 1, 0, 1, 4) self.clearbutton = QtWidgets.QPushButton('clear') vbox = QtWidgets.QVBoxLayout() vbox.addLayout(grid) vbox.addLayout(grid2) vbox.addLayout(grid3) vbox.addWidget(self.clearbutton) vbox.addItem(QtWidgets.QSpacerItem(10,10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)) hbox = QtWidgets.QHBoxLayout(self) hbox.addWidget(self.widget) hbox.addLayout(vbox) self.setWindowTitle('Qt Coordinate System') self.transformOkButton.clicked.connect(self.onTransformChanged) self.viewportOkButton.clicked.connect(self.onViewportChanged) self.windowOkButton.clicked.connect(self.onWindowChanged) self.clearbutton.clicked.connect(self.onClear) print(self.widget.geometry()) print(self.widget.frameGeometry()) pass def createEdit(self, minimum, maximum, value, grid, i, j, d = True): edit = QtWidgets.QDoubleSpinBox() if d else QtWidgets.QSpinBox() edit.setRange(minimum, maximum) edit.setValue(value) edit.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) #edit.setMaximumWidth(50) grid.addWidget(edit, i, j) return edit def onTransformChanged(self): m11 = self.m11Edit.value() m12 = self.m12Edit.value() m13 = self.m13Edit.value() m21 = self.m21Edit.value() m22 = self.m22Edit.value() m23 = self.m23Edit.value() m31 = self.m31Edit.value() m32 = self.m32Edit.value() m33 = self.m33Edit.value() self.widget.setTransform(QtGui.QTransform(m11, m12, m13, m21, m22, m23, m31, m32, m33)) def onViewportChanged(self): x = self.vxEdit.value() y = self.vyEdit.value() w = self.vwEdit.value() h = self.vhEdit.value() self.widget.setViewPort(QtCore.QRect(x,y,w,h)) def onWindowChanged(self): x = self.wxEdit.value() y = self.wyEdit.value() w = self.wwEdit.value() h = self.whEdit.value() self.widget.setWindow(QtCore.QRect(x,y,w,h)) def onClear(self): self.widget.poslist.clear() self.widget.update() if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) dlg = Dialog() dlg.show() sys.exit(app.exec_()) ''' https://blog.csdn.net/weixin_39583140/article/details/92798127 https://blog.csdn.net/fanyun_01/article/details/53129781 https://blog.csdn.net/u012487272/article/details/24269017 https://blog.csdn.net/fanyun_01/article/details/53129781 '''