我有一个QTreeWidget,它有一个顶级“分支”和一个秒级“分支”。每个分支都有QTreeWidgetItems,该QTreeWidgetItems具有QLabel和Qpixmap,并且为了节省内存,仅当用户展开分支项目时才生成Qpixmap。此QTtreeWidgetItem的每个子级都获得一个带有setItemWidget()
的QLabel,并且PIXMap在另一个线程中生成。当我双击QLabel时,我想打印出公式
当我想在qrunbale生成完成后将每个QPixmap设置为每个相应的QLabel时,就会出现问题。第一次扩建支行时,情况如下:
请注意每个QTreeWidgetItem的高度是如何正确的(有6个公式,悬停在每个项目上,您可以看到有6个项目,这里我悬停在第五个项目上),双击每个项目会打印出正确的公式(第一个项目的v=s/t,最后一个项目的v2-v02as,即使它没有图像). 但是这里的Qpixmap/Qlabel与QTreeWidgetItems不对齐。再次折叠和展开同一项目将产生:
突然,由于某种原因,每个QPixmap都对齐了。(另外,我的鼠标在两张图片中的位置相同,悬停在相同的QTreeItemWidget上,双击可打印出相同的公式)
代码如下:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import matplotlib
import matplotlib.pyplot as mpl
from matplotlib.backends.backend_agg import FigureCanvasAgg
from sympy.printing import latex
from sympy.parsing import parse_expr
from sympy import Eq
matplotlib.rcParams["mathtext.fontset"] = "cm"
data = [
{
"velocity": ["V", "Velocity of object"]
},
{
"Fysik": {
"Kinematics": {
"v = s/t": {},
"a = v/t": {},
"v = v0+a*t": {},
"s = v0*t+(a*t**2)/2": {},
"s = (v+v0)/2*t": {},
"v**2-v0**2=2*a*s": {},
}
}
}
]
def mathTex_to_QPixmap(mathTex, fs, fig):
"""
Create QPixMap from LaTeX
https://stackoverflow.com/questions/32035251/displaying-latex-in-pyqt-pyside-qtablewidget
:param mathTex: str
LaTeX string
:param fs: int
Font size
:param fig: matplotlib.figure.Figure
Matplotlib Figure
:return: QPixmap
QPixMap contaning LaTeX image
"""
fig.clf()
fig.patch.set_facecolor("none")
fig.set_canvas(FigureCanvasAgg(fig))
renderer = fig.canvas.get_renderer()
ax = fig.add_axes([0, 0, 1, 1])
ax.axis("off")
ax.patch.set_facecolor("none")
t = ax.text(0, 0, mathTex, ha="left", va="bottom", fontsize=fs)
fwidth, fheight = fig.get_size_inches()
fig_bbox = fig.get_window_extent(renderer)
text_bbox = t.get_window_extent(renderer)
tight_fwidth = text_bbox.width * fwidth / fig_bbox.width
tight_fheight = text_bbox.height * fheight / fig_bbox.height
fig.set_size_inches(tight_fwidth, tight_fheight)
buf, size = fig.canvas.print_to_buffer()
qimage = QImage.rgbSwapped(QImage(buf, size[0], size[1], QImage.Format_ARGB32))
qpixmap = QPixmap(qimage)
return qpixmap
class LaTeXSignals(QObject):
finished = pyqtSignal()
current = pyqtSignal(int)
output = pyqtSignal(list)
class LaTeXWorker(QRunnable):
def __init__(self, formula_list):
super(LaTeXWorker, self).__init__()
self.formula_list = formula_list
self.fig = mpl.figure()
self.signals = LaTeXSignals()
@pyqtSlot()
def run(self) -> None:
"""
Create QPixMap from formulas provided
by self.formula_list
:return: list
List of QPixMap
"""
out = []
for i, formula in enumerate(self.formula_list):
expr = formula.split("=")
left = parse_expr(expr[0], evaluate=False)
right = parse_expr(expr[1], evaluate=False)
latex_pixmap = mathTex_to_QPixmap(
f"${latex(Eq(left, right))}$",
15,
fig=self.fig,
)
out.append(latex_pixmap)
self.signals.current.emit(i)
self.signals.output.emit(out)
self.signals.finished.emit()
class Testing(QMainWindow):
def __init__(self):
super().__init__()
self.info = data[0]
self.formulas = data[1]
self.threadpool = QThreadPool()
self.threadpool.setMaxThreadCount(1)
self.init_ui()
self.add_formulas()
self.init_bindings()
def init_ui(self):
"""
Create UI
"""
self.FormulaTree = QTreeWidget()
self.setCentralWidget(self.FormulaTree)
def add_formulas(self):
"""
Initialize the Tree
"""
for branch in self.formulas:
parent = QTreeWidgetItem(self.FormulaTree)
parent.setText(0, branch)
for sub_branch in self.formulas[branch]:
child = QTreeWidgetItem(parent)
child.setText(0, sub_branch)
for formula in self.formulas[branch][sub_branch]:
formula_child = QTreeWidgetItem(child)
formula_label = QLabel()
formula_label.setObjectName(f"{formula}")
self.FormulaTree.setItemWidget(formula_child, 0, formula_label)
def init_bindings(self):
self.FormulaTree.itemDoubleClicked.connect(self.formula_tree_selected)
self.FormulaTree.itemExpanded.connect(self.expanded_sub)
self.FormulaTree.itemCollapsed.connect(self.collapsed_sub)
def expanded_sub(self, item):
# Collapse everything else and only expand whatever the user clicked on
root = self.FormulaTree.invisibleRootItem()
for i in range(root.childCount()):
branch = root.child(i)
for j in range(branch.childCount()):
sub_branch = branch.child(j)
if sub_branch != item:
self.FormulaTree.collapseItem(sub_branch)
# Start worker
if item.parent():
formulas = [
self.FormulaTree.itemWidget(item.child(i), 0).objectName()
for i in range(item.childCount())
]
title = item.text(0)
total = len(formulas)
worker = LaTeXWorker(formulas)
worker.signals.current.connect(lambda current: self.update_current(current, total, title, item))
worker.signals.output.connect(lambda output: self.set_pixmap(output, item))
worker.signals.finished.connect(lambda: item.setText(0, title))
self.threadpool.start(worker)
def update_current(self, curr, total, title, item):
"""
Updates sub-branch name
"""
item.setText(0, f"{title} - Generating LaTeX [{curr}/{total}] {int((curr/total)*100)}%")
def set_pixmap(self, output, item):
for i in range(item.childCount()):
pixmap = output[i]
qlabel = self.FormulaTree.itemWidget(item.child(i), 0)
item.child(i).setSizeHint(
0, QSize(QSizePolicy.Expanding, pixmap.height())
)
qlabel.setPixmap(pixmap)
QPixmapCache.clear()
def collapsed_sub(self, item):
"""
In order to save memory, LaTeX QPixmaps are generated when shown
and cleared once the user clicks on another sub-branch.
:param item: QTreeWidgetItem
The item the user clicked at
:return: None
"""
if item.parent():
for i in range(item.childCount()):
qlabel = self.FormulaTree.itemWidget(item.child(i), 0)
qlabel.clear()
QPixmapCache.clear()
def formula_tree_selected(self):
"""
Prints formula of selected item
"""""
selected = self.FormulaTree.selectedItems()
if selected:
widget = selected[0]
qlabel = self.FormulaTree.itemWidget(widget, 0)
print(qlabel.objectName())
app = QApplication(sys.argv)
_app = Testing()
_app.setFixedSize(QSize(500, 500))
_app.show()
sys.exit(app.exec_())
因为它在第二次尝试时起作用,所以我尝试先设置大小提示,然后设置Pixmap, 导致以下变化:
def set_pixmap(self, output, item):
for i in range(item.childCount()):
pixmap = output[i]
item.child(i).setSizeHint(
0, QSize(QSizePolicy.Expanding, pixmap.height())
)
for i in range(item.childCount()):
pixmap = output[i]
qlabel = self.FormulaTree.itemWidget(item.child(i), 0)
qlabel.setPixmap(pixmap)
QPixmapCache.clear()
但是QPixmaps仍然没有对齐
如何使Qpixmap/Qlabel与QTreeWidgetItems正确对齐
musicamante的评论回答了我的问题。以下是我为使其工作所做的:
相关问题 更多 >
编程相关推荐