Python QScrollArea和QPainter可能存在的渲染问题
我正在尝试用PyQt5创建一个角色地图可视化工具。使用fontTools库,我提取给定ttf文件中支持的UNICODE代码点。然后使用Python QScrollArea和QPainter可能存在的渲染问题,python,pyqt,pyqt5,qpainter,qscrollarea,Python,Pyqt,Pyqt5,Qpainter,Qscrollarea,我正在尝试用PyQt5创建一个角色地图可视化工具。使用fontTools库,我提取给定ttf文件中支持的UNICODE代码点。然后使用QPainter.drawText在标签上绘制图示符。标签存储在QGridLayout中,布局位于qscrollara 一切正常,除了我尝试滚动的时候。每当我尝试滚动过快时,绘制的图像就会重叠。看起来像这样 当窗口失去焦点时,标签会被正确地重新绘制 这是我到目前为止所做的一切 import sys from PyQt5 import QtCore, QtWidg
QPainter.drawText
在标签上绘制图示符。标签存储在QGridLayout
中,布局位于qscrollara
一切正常,除了我尝试滚动的时候。每当我尝试滚动过快时,绘制的图像就会重叠。看起来像这样
当窗口失去焦点时,标签会被正确地重新绘制
这是我到目前为止所做的一切
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFontDatabase, QFont, QColor, QPainter
from fontTools.ttLib import TTFont
class App(QWidget):
def __init__(self):
super().__init__()
self.fileName = "mukti.ttf" #the ttf file is located in the same path as the script
self.initUI()
def initUI(self):
self.setWindowTitle("Glyph Viewer")
self.setFixedSize(640, 480)
self.move(100, 100)
vBox = QtWidgets.QVBoxLayout()
self.glyphView = GlyphView()
vBox.addWidget(self.glyphView)
self.setLayout(vBox)
self.showGlyphs()
self.show()
def showGlyphs(self):
#Using the fontTools libray, the unicode blocks are obtained from the ttf file
font = TTFont(self.fileName)
charMaps = list()
for cmap in font['cmap'].tables:
charMaps.append(cmap.cmap)
charMap = charMaps[0]
fontDB = QFontDatabase()
fontID = fontDB.addApplicationFont("mukti.ttf")
fonts = fontDB.applicationFontFamilies(fontID)
qFont = QFont(fonts[0])
qFont.setPointSize(28)
self.glyphView.populateGrid(charMap, qFont)
class GlyphView(QtWidgets.QScrollArea):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setWidgetResizable(True)
def populateGrid(self, charMap, qFont):
glyphArea = QtWidgets.QWidget(self)
gridLayout = QtWidgets.QGridLayout()
glyphArea.setLayout(gridLayout)
row, col = 1, 1
for char in charMap:
uni = charMap[char]
gridLayout.addWidget(Glyph(qFont, chr(char)), row, col)
if not col % 4:
col = 1
row += 1
else:
col += 1
self.setWidget(glyphArea)
class Glyph(QtWidgets.QLabel):
def __init__(self, font, char):
super().__init__()
self.font = font
self.char = char
self.initUI()
def initUI(self):
self.setFixedSize(48, 48)
self.setToolTip(self.char)
def paintEvent(self, event):
qp = QPainter(self)
qp.setBrush(QColor(0,0,0))
qp.drawRect(0, 0, 48, 48)
qp.setFont(self.font)
qp.setPen(QColor(255, 255, 255))
qp.drawText(event.rect(), Qt.AlignCenter, self.char)
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
我不确定这是什么原因造成的。感谢您的帮助 paintEvent()方法为我们提供了一个属于QPaintEvent
的对象,该对象通过rect()
方法提供了一个QRect
,该QRect
是当前可见的区域,该信息可用于优化绘制,例如,假设我们有一个小部件,它在几行中显示文本,如果文本很大,那么几行看起来会很浪费资源,因此使用前面提到的QRect
进行适当的计算,我们可以得到这些行,并用很少的资源绘制该部分。在中,我展示了一个使用event.rect()的示例
在您的情况下,不需要使用event.rect()
,因为您将在小部件的一部分中绘制文本。您应该使用的是self.rect()
:
我还认为没有必要覆盖paintEvent()
方法,因为您可以直接指向QLabel
字体、文本和对齐方式:
class Glyph(QtWidgets.QLabel):
def __init__(self, font, char):
super().__init__(font=font, text=char, alignment=Qt.AlignCenter, toolTip=char)
paintEvent()
方法为我们提供了一个属于QPaintEvent
的对象,该对象通过rect()
方法提供了一个QRect
,该QRect
是当前可见的区域,该信息可用于优化绘制,例如,假设我们有一个小部件,它在几行中显示文本,如果文本很大,那么几行看起来会很浪费资源,因此使用前面提到的QRect
进行适当的计算,我们可以得到这些行,并用很少的资源绘制该部分。在中,我展示了一个使用event.rect()的示例
在您的情况下,不需要使用event.rect()
,因为您将在小部件的一部分中绘制文本。您应该使用的是self.rect()
:
我还认为没有必要覆盖paintEvent()
方法,因为您可以直接指向QLabel
字体、文本和对齐方式:
class Glyph(QtWidgets.QLabel):
def __init__(self, font, char):
super().__init__(font=font, text=char, alignment=Qt.AlignCenter, toolTip=char)
谢谢你的解释!谢谢你的解释!