在 python 中的文本后面制作一个矩形框
Making a rectangle box behind text in python
我正在开发文本编辑器。留给我的唯一问题是在文本后面绘制一个矩形框(颜色为不透明度 50%),该文本应该能够在文本工作时随文本拖放到任何地方。此外,文本应始终适合该矩形框。提前致谢。
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PIL import Image, ImageFont, ImageDraw, ImageEnhance
class PhotoViewer(QtWidgets.QGraphicsView):
photoClicked = QtCore.pyqtSignal(QtCore.QPoint)
def __init__(self, parent):
super(PhotoViewer, self).__init__(parent)
self._zoom = 0
self._empty = True
self._scene = QtWidgets.QGraphicsScene(self)
self._photo = QtWidgets.QGraphicsPixmapItem()
self._textLayer = QtWidgets.QGraphicsSimpleTextItem ()
#self._textLayer.setFont(QFont ())
self._scene.addItem(self._photo)
self._scene.addItem(self._textLayer)
self.setScene(self._scene)
self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(80, 30, 30)))
self.setFrameShape(QtWidgets.QFrame.NoFrame)
self._textLayer.setFlags(QGraphicsItem.ItemIsMovable)
def hasPhoto(self):
return not self._empty
def fitInView(self, scale=True):
rect = QtCore.QRectF(self._photo.pixmap().rect())
if not rect.isNull():
self.setSceneRect(rect)
if self.hasPhoto():
unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
self.scale(1 / unity.width(), 1 / unity.height())
viewrect = self.viewport().rect()
scenerect = self.transform().mapRect(rect)
factor = min(viewrect.width() / scenerect.width(),
viewrect.height() / scenerect.height())
self.scale(factor, factor)
self._zoom = 0
def updateText(self,text,font_size=50):
# Load the font:
font_db = QFontDatabase()
font_id = font_db.addApplicationFont("fonts/Summer's Victory Over Spring - TTF.ttf")
#families = font_db.applicationFontFamilies(font_id)
#print (families)
myFont = QFont("Summers Victory Over Spring")
myFont.setPixelSize(font_size*1.5)
self._textLayer.setFont(myFont)
self._textLayer.setText(text)
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.show()
def setPhoto(self, pixmap=None):
self._zoom = 0
if not pixmap.isNull():
self._empty = False
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self._photo.setPixmap(pixmap)
else:
self._empty = True
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
self._photo.setPixmap(QPixmap())
self.fitInView()
def wheelEvent(self, event):
if self.hasPhoto():
if event.angleDelta().y() > 0:
factor = 1.25
self._zoom += 1
else:
factor = 0.8
self._zoom -= 1
if self._zoom > 0:
self.scale(factor, factor)
elif self._zoom == 0:
self.fitInView()
else:
self._zoom = 0
def toggleDragMode(self):
if self.dragMode() == QtWidgets.QGraphicsView.ScrollHandDrag:
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
elif not self._photo.pixmap().isNull():
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
def mousePressEvent(self, event):
if self._photo.isUnderMouse():
self.photoClicked.emit(QtCore.QPoint(event.pos()))
super(PhotoViewer, self).mousePressEvent(event)
def keyReleaseEvent(self, event):
print ('Key event: %d' % event.key())
if event.key() == Qt.Key_A:
#print (dir(self._scene))
#print (dir(self._photo))
#print (dir(self._textLayer))
print ("scene Rect:",self._scene.sceneRect())
print ("scene WH:",self._scene.width(),self._scene.height())
print ("gfxPhoto pos:" ,self._photo.pos().x(),self._photo.pos().y())
print ("gfxPhoto scenepos:" ,self._photo.scenePos())
#print ("gfxPhoto Rect:",self._photo.boundingRect())
print ("gfxPhoto XY:",self._photo.x(),self._photo.y())
print ("gfxtext Rect:",self._textLayer.boundingRect())
print ("gfxtext scenepos:" ,self._textLayer.scenePos().x(),self._textLayer.scenePos().y())
print ("gfxtext pos:",self._textLayer.pos().x(),self._textLayer.pos().y())
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.viewer = PhotoViewer(self)
# 'Load image' button
self.btnLoad = QtWidgets.QToolButton(self)
self.btnLoad.setText('Load image')
self.btnLoad.clicked.connect(self.loadImage)
# Button to change from drag/pan to getting pixel info
self.btnPixInfo = QtWidgets.QToolButton(self)
self.btnPixInfo.setText('Create Text')
self.btnPixInfo.clicked.connect(self.loadText)
self.fontSize =QtWidgets.QSpinBox()
self.fontSize.valueChanged.connect(self.loadText)
self.editPixInfo = QtWidgets.QLineEdit(self)
#self.editPixInfo.setReadOnly(True)
self.viewer.photoClicked.connect(self.photoClicked)
# Arrange layout
VBlayout = QtWidgets.QVBoxLayout(self)
HBlayout = QtWidgets.QHBoxLayout()
HBlayout.setAlignment(QtCore.Qt.AlignLeft)
HBlayout.addWidget(self.btnLoad)
HBlayout.addWidget(self.btnPixInfo)
HBlayout.addWidget(self.editPixInfo)
VBlayout.addLayout(HBlayout)
VBlayout.addWidget(self.viewer)
HBlayout.addWidget(self.fontSize)
self.editPixInfo.setText("Sheeda")
self.fontSize.setValue(20)
self.loadImage()
self.loadText()
self.frame = QFrame()
self.frame.setFrameStyle(QFrame.StyledPanel)
self.frame.setLineWidth(20)
def loadImage(self):
print(os.path.exists(os.path.abspath('E:\Dpinner\images\pic2.png')))
self.viewer.setPhoto(QtGui.QPixmap(os.path.abspath('E:\Dpinner\images\pic2.png')))
def loadText(self):
#self.viewer.toggleDragMode()
self.viewer.updateText(self.editPixInfo.text(),self.fontSize.value())
def photoClicked(self, pos):
if self.viewer.dragMode() == QtWidgets.QGraphicsView.NoDrag:
self.editPixInfo.setText('%d, %d' % (pos.x(), pos.y()))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 800, 600)
window.show()
sys.exit(app.exec_())
代码结束。提前致谢
如果您想在文本上添加一个矩形,您可以创建自定义 QGraphicsSimpleTextItem
,如下所示:
class GraphicsSimpleTextItem(QtWidgets.QGraphicsSimpleTextItem):
def paint(self, painter, option, widget):
super(GraphicsSimpleTextItem, self).paint(painter, option, widget)
painter.save()
color = QtGui.QColor(QtCore.Qt.red)
color.setAlpha(127)
painter.fillRect(self.boundingRect(), QtGui.QBrush(color))
painter.restore()
然后你把它放在你的代码中:
self._textLayer = GraphicsSimpleTextItem()
我正在开发文本编辑器。留给我的唯一问题是在文本后面绘制一个矩形框(颜色为不透明度 50%),该文本应该能够在文本工作时随文本拖放到任何地方。此外,文本应始终适合该矩形框。提前致谢。
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PIL import Image, ImageFont, ImageDraw, ImageEnhance
class PhotoViewer(QtWidgets.QGraphicsView):
photoClicked = QtCore.pyqtSignal(QtCore.QPoint)
def __init__(self, parent):
super(PhotoViewer, self).__init__(parent)
self._zoom = 0
self._empty = True
self._scene = QtWidgets.QGraphicsScene(self)
self._photo = QtWidgets.QGraphicsPixmapItem()
self._textLayer = QtWidgets.QGraphicsSimpleTextItem ()
#self._textLayer.setFont(QFont ())
self._scene.addItem(self._photo)
self._scene.addItem(self._textLayer)
self.setScene(self._scene)
self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(80, 30, 30)))
self.setFrameShape(QtWidgets.QFrame.NoFrame)
self._textLayer.setFlags(QGraphicsItem.ItemIsMovable)
def hasPhoto(self):
return not self._empty
def fitInView(self, scale=True):
rect = QtCore.QRectF(self._photo.pixmap().rect())
if not rect.isNull():
self.setSceneRect(rect)
if self.hasPhoto():
unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
self.scale(1 / unity.width(), 1 / unity.height())
viewrect = self.viewport().rect()
scenerect = self.transform().mapRect(rect)
factor = min(viewrect.width() / scenerect.width(),
viewrect.height() / scenerect.height())
self.scale(factor, factor)
self._zoom = 0
def updateText(self,text,font_size=50):
# Load the font:
font_db = QFontDatabase()
font_id = font_db.addApplicationFont("fonts/Summer's Victory Over Spring - TTF.ttf")
#families = font_db.applicationFontFamilies(font_id)
#print (families)
myFont = QFont("Summers Victory Over Spring")
myFont.setPixelSize(font_size*1.5)
self._textLayer.setFont(myFont)
self._textLayer.setText(text)
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.show()
def setPhoto(self, pixmap=None):
self._zoom = 0
if not pixmap.isNull():
self._empty = False
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self._photo.setPixmap(pixmap)
else:
self._empty = True
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
self._photo.setPixmap(QPixmap())
self.fitInView()
def wheelEvent(self, event):
if self.hasPhoto():
if event.angleDelta().y() > 0:
factor = 1.25
self._zoom += 1
else:
factor = 0.8
self._zoom -= 1
if self._zoom > 0:
self.scale(factor, factor)
elif self._zoom == 0:
self.fitInView()
else:
self._zoom = 0
def toggleDragMode(self):
if self.dragMode() == QtWidgets.QGraphicsView.ScrollHandDrag:
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
elif not self._photo.pixmap().isNull():
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
def mousePressEvent(self, event):
if self._photo.isUnderMouse():
self.photoClicked.emit(QtCore.QPoint(event.pos()))
super(PhotoViewer, self).mousePressEvent(event)
def keyReleaseEvent(self, event):
print ('Key event: %d' % event.key())
if event.key() == Qt.Key_A:
#print (dir(self._scene))
#print (dir(self._photo))
#print (dir(self._textLayer))
print ("scene Rect:",self._scene.sceneRect())
print ("scene WH:",self._scene.width(),self._scene.height())
print ("gfxPhoto pos:" ,self._photo.pos().x(),self._photo.pos().y())
print ("gfxPhoto scenepos:" ,self._photo.scenePos())
#print ("gfxPhoto Rect:",self._photo.boundingRect())
print ("gfxPhoto XY:",self._photo.x(),self._photo.y())
print ("gfxtext Rect:",self._textLayer.boundingRect())
print ("gfxtext scenepos:" ,self._textLayer.scenePos().x(),self._textLayer.scenePos().y())
print ("gfxtext pos:",self._textLayer.pos().x(),self._textLayer.pos().y())
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.viewer = PhotoViewer(self)
# 'Load image' button
self.btnLoad = QtWidgets.QToolButton(self)
self.btnLoad.setText('Load image')
self.btnLoad.clicked.connect(self.loadImage)
# Button to change from drag/pan to getting pixel info
self.btnPixInfo = QtWidgets.QToolButton(self)
self.btnPixInfo.setText('Create Text')
self.btnPixInfo.clicked.connect(self.loadText)
self.fontSize =QtWidgets.QSpinBox()
self.fontSize.valueChanged.connect(self.loadText)
self.editPixInfo = QtWidgets.QLineEdit(self)
#self.editPixInfo.setReadOnly(True)
self.viewer.photoClicked.connect(self.photoClicked)
# Arrange layout
VBlayout = QtWidgets.QVBoxLayout(self)
HBlayout = QtWidgets.QHBoxLayout()
HBlayout.setAlignment(QtCore.Qt.AlignLeft)
HBlayout.addWidget(self.btnLoad)
HBlayout.addWidget(self.btnPixInfo)
HBlayout.addWidget(self.editPixInfo)
VBlayout.addLayout(HBlayout)
VBlayout.addWidget(self.viewer)
HBlayout.addWidget(self.fontSize)
self.editPixInfo.setText("Sheeda")
self.fontSize.setValue(20)
self.loadImage()
self.loadText()
self.frame = QFrame()
self.frame.setFrameStyle(QFrame.StyledPanel)
self.frame.setLineWidth(20)
def loadImage(self):
print(os.path.exists(os.path.abspath('E:\Dpinner\images\pic2.png')))
self.viewer.setPhoto(QtGui.QPixmap(os.path.abspath('E:\Dpinner\images\pic2.png')))
def loadText(self):
#self.viewer.toggleDragMode()
self.viewer.updateText(self.editPixInfo.text(),self.fontSize.value())
def photoClicked(self, pos):
if self.viewer.dragMode() == QtWidgets.QGraphicsView.NoDrag:
self.editPixInfo.setText('%d, %d' % (pos.x(), pos.y()))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 800, 600)
window.show()
sys.exit(app.exec_())
代码结束。提前致谢
如果您想在文本上添加一个矩形,您可以创建自定义 QGraphicsSimpleTextItem
,如下所示:
class GraphicsSimpleTextItem(QtWidgets.QGraphicsSimpleTextItem):
def paint(self, painter, option, widget):
super(GraphicsSimpleTextItem, self).paint(painter, option, widget)
painter.save()
color = QtGui.QColor(QtCore.Qt.red)
color.setAlpha(127)
painter.fillRect(self.boundingRect(), QtGui.QBrush(color))
painter.restore()
然后你把它放在你的代码中:
self._textLayer = GraphicsSimpleTextItem()