python - 在 Qt <= 5.12 中立即清除 `QGraphicsView`
问题描述
下面给出的代码来自另一个关于 SO 的问题。它显示 a QMainWindow
with 4QGraphicsView
以在其中使用鼠标进行绘制,并显示 aQPushButton
以清除 4 QGraphicsView
。
课堂上有一个clear()
方法QPainterPath
,但它是在 Qt 5.13中引入的,我正在使用 Qt 5.12。所以我编写了自己的方法来清除视图及其路径。
绘图工作正常,单击Clear
按钮不会导致错误,但视图只会在下次绘图时被清除,而不是立即清除。
立即清除视图的更好解决方案是什么?
主文件
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPathItem
from PyQt5.QtGui import QPainterPath, QPen
from PyQt5.QtCore import Qt
from PyQt5.uic import loadUi
# Based on code from https://stackoverflow.com/a/44248794/7481773
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
loadUi("mainwindow.ui", self)
self.layouts = (self.verticalLayout_top_left, self.verticalLayout_top_right,
self.verticalLayout_bottom_left, self.verticalLayout_bottom_right)
self._views = []
for layout in self.layouts:
graphics_view = GraphicsView()
self._views.append(graphics_view)
layout.addWidget(graphics_view)
self.clear_button.clicked.connect(self.clear_views)
def clear_views(self):
for view in self._views:
view.clear_view()
class GraphicsView(QGraphicsView):
def __init__(self):
super().__init__()
self.start = None
self.end = None
self.setScene(QGraphicsScene())
self.path = QPainterPath()
self.item = GraphicsPathItem()
self.scene().addItem(self.item)
self.contents_rect = self.contentsRect()
self.setSceneRect(0, 0, self.contents_rect.width(), self.contents_rect.height())
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
def clear_view(self):
# self.path.clear() # Qt 5.13
self.path = QPainterPath()
self.scene().update()
def mousePressEvent(self, event):
self.start = self.mapToScene(event.pos())
self.path.moveTo(self.start)
def mouseMoveEvent(self, event):
self.end = self.mapToScene(event.pos())
self.path.lineTo(self.end)
self.start = self.end
self.item.setPath(self.path)
class GraphicsPathItem(QGraphicsPathItem):
def __init__(self):
super().__init__()
pen = QPen()
pen.setColor(Qt.black)
pen.setWidth(5)
self.setPen(pen)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
app.exec_()
del main_window, app
if __name__ == "__main__":
main()
主窗口.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Paint and Clear</string>
</property>
<property name="locale">
<locale language="English" country="UnitedKingdom"/>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_top_left"/>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_top_right"/>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_bottom_left"/>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_bottom_right"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QPushButton" name="clear_button">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>24</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
解决方案
即使使用该clear()
方法并不意味着视图已被清除,但您必须在项目中设置路径。正题,等价的方法是新建一个QPainterPath
,另外不需要调用update()
场景的方法。使用clear()
或设置空QPainterPath
在 python 端是等效的,但在 C++ 端它会导致优化应用程序的相同内存被重用。
def clear_view(self):
self.path = QPainterPath()
self.item.setPath(self.path)
如果你想同时兼容这两个版本,你可以使用 try-except:
def clear_view(self):
try:
self.path.clear()
except AttributeError as e:
self.path = QPainterPath()
self.item.setPath(self.path)
推荐阅读
- javascript - 如何获取所有带有属性表单字符串的 HTML
- api - Jupyter Notebook 和 Gsheet 之间的连接 - 失败 - HttpError 403 错误
- python - yfinance - 隔离股票价格
- javascript - GO_TO_PAGE GOOGLE 表格到表单,如何设置转到页面变量
- javascript - Vue 通知数组
- python - 使用 re.search 搜索文件并将输出保存到新文件
- clickhouse - Clickhouse:runningAccumulate() 不像我预期的那样工作
- d3.js - threejs 在对象上或对象旁边呈现文本
- oracle - 无法在 oracle 的表中获得预期结果值(负记录行)
- memory - “写保护” PAT 内存类型的用例是什么?