После woboq QPaintDevice и woboq QPaintEngine , я попытался переопределить QPaintEngine
& QPaintDevice
. Подробнее, QPaintEngineState
.
Это мое первое испытание, и я не смог найти достаточно решений.
Повторная реализация QPaintDevice
, вероятно, не была проблемой, но в случае QPaintEngine
Я не мог конвертировать из C++
в python
код гладко. Если я создаю экземпляр QPaintEventState
, приложение не работает.
Особенно, drawTextItem
явно содержит C++
внутренний код, я не могу преобразовать в python
, я в растерянности.
Возможно, было бы хорошо, если бы я делегировал выполнение по умолчанию QPaintEngine
,
Например, вместо
def drawTextItem(self, p, textItem):
path = QtGui.QPainterPath()
path.setFillRule(QtCore.Qt.WindingFill);
if not path.isEmpty():
self.painter().save()
self.painter().setRenderHint(QtGui.QPainter.Antialiasing,
bool((self.painter().renderHints() & QtGui.QPainter.TextAntialiasing)
and not (self.painter().font().styleStrategy() & QtGui.QFont.NoAntialias)))
self.painter().translate(p.x(), p.y())
self.painter().fillPath(path, self.painter().pen().brush())
self.painter().restore()
def drawTextItem(self, p, textItem):
#I write here before the default drawTextItem
QtGui.QPaintEngine.drawTextItem(p, textItem)
вот так .
Или самого кода C++
недостаточно для создания подкласса? (поскольку QPaintDevice.width () возвращает pdmWidth, но по умолчанию его нет в функции metri c (dev).)
QPaintEngine
, QPaintDevice
, QPaintEngineState
, как их правильно использовать ?
Как переопределить наименее исполняемый код, как мне это сделать? Я хочу получить любую информацию.
Это мой пробный код, может быть несколько проблемы ... В настоящее время мне удалось установить QPaintDevice
подкласса на QAbstractTextDocumentLayout.setPaintDevice()
.
import os
import PySide2
from PySide2 import QtWidgets , QtGui , QtCore, QtPrintSupport, QtOpenGL
import sys
import math
dirname = os.path.dirname(PySide2.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path
class PE(QtGui.QPaintEngine):
def __init__(self, features = QtGui.QPaintEngine.AllFeatures):
super(PE, self).__init__(features=features)
self.qt_polygon_recursion = 0
self.paintEngineEx = {}
self.types = [QtGui.QPaintEngine.Type.X11, QtGui.QPaintEngine.Type.Windows, QtGui.QPaintEngine.MacPrinter, QtGui.QPaintEngine.CoreGraphics,\
QtGui.QPaintEngine.Type.QuickDraw, QtGui.QPaintEngine.QWindowSystem, QtGui.QPaintEngine.PostScript, QtGui.QPaintEngine.OpenGL,\
QtGui.QPaintEngine.Type.Picture, QtGui.QPaintEngine.SVG, QtGui.QPaintEngine.Raster, QtGui.QPaintEngine.Direct3D,\
QtGui.QPaintEngine.Type.Pdf, QtGui.QPaintEngine.OpenVG, QtGui.QPaintEngine.User, QtGui.QPaintEngine.MaxUser, QtGui.QPaintEngine.OpenGL2,\
QtGui.QPaintEngine.Type.PaintBuffer, QtGui.QPaintEngine.Blitter]
def begin(self, paintDevice):
if isinstance(paintDevice, QtGui.QPaintDevice):
print(24, "in begin func")
return True
else:
return False
def drawPolygon(self, points, pointCount, mode):
if type(points[0]) == QtCore.QPointF:
self.qt_polygon_recursion = self
p = [QtCore.QPointF() for i in range(pointCount)]
for i in range(pointCount):
p[i].x = round(points[i].x())
p[i].y = round(points[i].y())
self.drawPolygon(p, pointCount, mode)
self.qt_polygon_recursion = 0
elif type(points[0]) == QtCore.QPoint:
self.qt_polygon_recursion = self
p = [QtCore.QPointF() for i in range(pointCount)]
for i in range(pointCount):
p[i].x = round(points[i].x())
p[i].y = round(points[i].y())
self.drawPolygon(p, pointCount, mode)
self.qt_polygon_recursion = 0
def drawPoints(self, points, pointCount):
if type(points[0]) == QtCore.QPoint:
fp = [QtCore.QPointF() for i in range(256)]
while pointCount:
i = 0
while i < pointCount and i < 256:
fp[i].x = points[i].x()
fp[i].y = points[i].y()
i += 1
self.drawPoints(QtCore.QPointF(fp), i)
points += i
pointCount -= i
elif type(points[0]) == QtCore.QPointF:
p = self.painter()
pen = p.pen()
penWidth = pen.widthF()
if penWidth == 0:
penWidth = 1
ellipses = pen.capStyle() == QtCore.Qt.RoundCap
p.save()
transForm = QtGui.QTransform()
if self.qt_pen_is_cosmetic(pen, p.renderHints()):
p.setTransform(transForm)
p.setBrush(pen.brush())
p.setPen(QtCore.Qt.NoPen)
for i in range(pointCount):
pos = transForm.map(points[i])
rectF = QtCore.QRectF(pos.x() - penWidth /2, pos.y() - penWidth / 2, penWidth, penWidth)
if ellipses:
p.drawEllipse(rectF)
else:
p.drawRect(rectF)
p.restore()
def drawEllipse(self, rect):
if type(rect) == QtCore.QRect:
self.drawEllipse(QtCore.QRectF(rect))
elif type(rect) == QtCore.QRectF:
path = QtGui.QPainterPath()
path.addEllipse(rect)
if self.hasFeature(QtGui.QPaintEngine.PainterPaths):
self.drawPath(path)
else:
polygon = path.toFillPolygon()
self.drawPolygon(polygon.data(), polygon.size(), QtGui.QPaintEngine.ConvexMode)
def qt_fill_tile(self, tile, pixmap):
p = QtGui.QPainter(tile)
p.drawPixmap(0, 0, pixmap)
x = pixmap.width()
while x < tile.width():
p.drawPixmap(x, 0, tile, 0, 0, x, pixmap.height())
x *= 2
y = pixmap.height()
while y < tile.height():
p.drawPixmap(0, y, tile, 0, 0, tile.width(), y)
y *= 2
def qt_draw_tile(self, gc, x, y, w, h, pixmap, xOffset, yOffset):
yPos = y
yOff = yOffset
while yPos < y+h:
drawH = pixmap.height() - yOff
if (yPos + drawH > y + h):
drawH = y + h - yPos
xPos = x
xOff = xOffset
while (xPos < x + w):
drawW = pixmap.width() - xOff
if (xPos + drawW > x + w):
drawW = x + w - xPos
if (drawW > 0 and drawH > 0):
gc.drawPixmap(QtCore.QRectF(xPos, yPos, drawW, drawH), pixmap, QtCore.QRectF(xOff, yOff, drawW, drawH))
xPos += drawW
xOff = 0
yPos += drawH
yOff = 0
def drawTiledPixmap(self, rect, pixmap, p):
sw = pixmap.width()
sh = pixmap.height()
if sw*sh < 8192 and sw*sh < 16*rect.width()*rect.height():
tw = sw, th = sh
while (tw*th < 32678 and tw < rect.width()/2):
tw *= 2
while (tw*th < 32678 and th < rect.height()/2):
th *= 2
tile = QtGui.QPixmap()
if pixmap.depth() == 1:
tile = QtGui.QBitmap(tw, th)
else:
tile = QtGui.QPixmap(tw, th)
if pixmap.hasAlphaChannel():
tile.fill(QtCore.Qt.transparent)
self.qt_draw_fill(tile, pixmap)
self.qt_draw_tile(self, rect.x(), rect.y(), rect.width(), rect.height(), tile, p.x(), p.y())
else:
self.qt_draw_tile(self, rect.x(), rect.y(), rect.width(), rect.height(), pixmap, p.x(), p.y())
def drawImage(self, r, image, sr, flags = QtCore.Qt.AutoColor):
#Confirmed
baseSize = QtCore.QRectF(0, 0, image.width(), image.height())
im = image
if baseSize != sr:
im = im.copy(math.floor(sr.x()), math.floor(sr.y()), math.ceil(sr.width()), math.ceil(sr.height()))
pm = QtGui.QPixmap.fromImage(im, flags)
self.drawPixmap(r, pm, QtCore.QRectF(QtCore.QPointF(0, 0), pm.size()))
def drawPath(self, path):
#confirmed
if self.hasFeature(QtGui.QPaintEngine.PainterPaths):
print(path.isEmpty())
print("QPaintEngine::drawPath: Must be implemented when feature PainterPaths is set")
def drawTextItem(self, p, textItem):
path = QtGui.QPainterPath()
path.setFillRule(QtCore.Qt.WindingFill);
if not path.isEmpty():
self.painter().save()
self.painter().setRenderHint(QtGui.QPainter.Antialiasing,
bool((self.painter().renderHints() & QtGui.QPainter.TextAntialiasing)
and not (self.painter().font().styleStrategy() & QtGui.QFont.NoAntialias)))
self.painter().translate(p.x(), p.y())
self.painter().fillPath(path, self.painter().pen().brush())
self.painter().restore()
def drawLines(self, lines, lineCount):
if type(lines[0]) == QtCore.QLine:
pts = []
for i in range(lineCount):
pts = [QtCore.PointF(lines[i].p1()), QtCore.QPointF(lines[i].p2())]
if pts[0] == pts[1]:
if self.state.pen().capStyle() != QtCore.Qt.FlatCap:
self.drawPoints(pts, 1)
continue
else:
pts = []
for i in range(lineCount):
pts = [lines[i].p1(), lines[i].p2()]
if pts[0] == pts[1]:
if self.state.pen().capStyle() != QtCore.Qt.FlatCap:
self.drawPoints(pts, 1)
continue
self.drawPolygon(pts, 2, self.PolylineMode)
def drawRects(self, rects, rectCount):
print(rects)
if type(rects[0]) == QtCore.QRect:
fr = [QtCore.QRectF() for i in range(256)]
while rectCount:
i = 0
while (i < rectCount and i < 256):
fr[i].x = rects[i].x()
fr[i].y = rects[i].y()
fr[i].w = rects[i].width()
fr[i].h = rects[i].height()
i+=1
self.drawRects(fr, i)
rects += i
rectCount -= i
elif type(rects[0]) == QtCore.QRectF:
if self.hasFeature(self.PainterPaths) :
for i in range(rectCount):
path = QtGui.QPainterPath()
path.addRect(rects[i])
if path.isEmpty():
continue
self.drawPath(path)
else:
for i in range(rectCount):
rf = rects[i]
pts = [QtCore.QPointF(rf.x(), rf.y()),
QtCore.QPointF(rf.x() + rf.width(), rf.y()),
QtCore.QPointF(rf.x() + rf.width(), rf.y() + rf.height()),
QtCore.QPointF(rf.x() + rf.y() + rf.height())]
self.drawPolygon(pts, 4, self.ConvexMode)
def coordinateOffset(self):
return QtCore.QPoint()
def qt_pen_is_cosmetic(self, pen, hints):
return pen.isCosmetic()|(hints and QtGui.QPainter.Qt4CompatiblePainting)
def end(self):
return True
def type(self):
return QtGui.QPaintEngine.Type.Windows
def updateState(self, state):
self.state = state
class PD(QtGui.QPaintDevice):
def __init__(self, parent=None):
super(PD, self).__init__(parent=None)
self._paintEngine = PE()
def devType(self):
#I think this is a deviceType() QPrinter, QImage, QPicture, QPixmap, QTextEdit, and so on.
paintEngine = self.paintEngine()
device = paintEngine.paintDevice()
print(device)
if type(device) == QtGui.QImage:
return QtGui.QImage.devType()
elif type(device) == QtGui.QPicture:
return QtGui.QPicture.devType()
elif type(device) == QtGui.QPixmap:
return QtGui.QPixmap.devType()
elif type(device) == QtPrintSupport.QPrinter:
return QtPrintSupport.QPrinter.devType()
elif type(device) == QtOpenGL.QGLPixelBuffer:
return QtOpenGL.QGLPixelBuffer.devType()
elif type(device) == QtWidgets.QWidget:
return QtWidgets.QWidget.devType()
else:
return 0
def redirected(self, point):
return self
def sharedPainter(self):
painter = QtGui.QPainter()
return painter
def initPainter(self, painter):
print(painter)
pass
def metric(self, m):
if m == self.PdmDevicePixelRatioScaled:
return self.metric(self.PdmDevicePixelRatio) * self.devicePixelRatioFScale()
if m == self.PdmDpiX:
return 72
elif m == self.PdmDpiY:
return 72
elif m == self.PdmNumColors:
return 256
elif m == self.PdmDevicePixelRatio:
return 1
else:
print("Unrecognized metric %d!", m)
return 0
def paintEngine(self):
paintEngine = self._paintEngine
print(277, paintEngine)
return self._paintEngine
class TextEdit(QtWidgets.QTextEdit):
def __init__(self, parent=None):
super(TextEdit, self).__init__(parent=None)
paintDevice = PD()
self.document().documentLayout().setPaintDevice(paintDevice)
def main():
if QtWidgets.QApplication.instance() is None:
app = QtWidgets.QApplication([])
else:
app = QtWidgets.QApplication.instance()
textEdit = TextEdit()
textEdit.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()