在不更改现有图纸颜色的情况下更改新图纸的颜色
Posted
技术标签:
【中文标题】在不更改现有图纸颜色的情况下更改新图纸的颜色【英文标题】:Color change for new drawings without changing the color of existing drawings 【发布时间】:2020-01-05 18:15:38 【问题描述】:下面给出的代码源自 SO 上的another question。它显示一个 QMainWindow
和 4 个 QGraphicsView
以在其中使用鼠标进行绘制,一个 QPushButton
用于清除 4 个 QGraphicsView
,以及一个 QPushButton
以获取用于绘制的新随机颜色。
目标:我想在不改变现有图纸颜色的情况下改变未来图纸的颜色。
尝试:更改QPen
对象的颜色会立即更改已绘制图形的颜色。因此,我使用新颜色的新 QPen
对象创建了新的 GraphicsPathItem
对象以避免这种情况。
问题:更改颜色后,QGraphicsView
中现有绘图的颜色会在您再次在其中绘制内容时发生变化。
如何解决这个问题?
main.py
>import sys
from random import choice
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPathItem
from PyQt5.QtGui import QPainterPath, QPen, QColor
from PyQt5.QtCore import Qt
from PyQt5.uic import loadUi
# Based on code from https://***.com/a/44248794/7481773
class MainWindow(QMainWindow):
COLORS = ("black", "red", "green", "blue", "yellow")
def __init__(self):
super().__init__()
loadUi("mainwindow.ui", self)
self.color = "black"
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.color)
self._views.append(graphics_view)
layout.addWidget(graphics_view)
self.clear_button.clicked.connect(self.clear_views)
self.color_button.clicked.connect(self.update_color)
def _get_new_random_color(self):
new_colors = list(self.COLORS)
new_colors.remove(self.color)
return choice(new_colors)
def clear_views(self):
for view in self._views:
view.clear_view()
def update_color(self):
new_color = self._get_new_random_color()
self.color = new_color
for view in self._views:
view.new_item(new_color)
class GraphicsView(QGraphicsView):
def __init__(self, color):
super().__init__()
self.start = None
self.end = None
self.item = None
self.setScene(QGraphicsScene())
self.path = QPainterPath()
self.new_item(color)
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):
try:
self.path.clear()
except AttributeError:
self.path = QPainterPath()
self.item.setPath(self.path)
def new_item(self, color):
self.item = GraphicsPathItem(color)
self.scene().addItem(self.item)
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, color):
super().__init__()
self.pen = QPen()
self.pen.setColor(QColor(color))
self.pen.setWidth(5)
self.setPen(self.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="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="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="1" column="0">
<widget class="QPushButton" name="clear_button">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="color_button">
<property name="text">
<string>New random color</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>
【问题讨论】:
每个帖子一个问题,如果您有其他问题,则必须创建另一个问题,因为这是 SO 的规则。 【参考方案1】:每次创建新项目时,您仍然使用相同的 QPainterPath,因此您看到的不是应用在现有“绘图”上的新颜色,而是仍然使用其中先前路径的新 QGraphicsPathItem 项目。
您可以通过在每次创建新项目时创建新路径来轻松解决您的问题:
def new_item(self, color):
self.item = GraphicsPathItem(color)
self.scene().addItem(self.item)
self.path = QPainterPath()
【讨论】:
以上是关于在不更改现有图纸颜色的情况下更改新图纸的颜色的主要内容,如果未能解决你的问题,请参考以下文章
在不更改边框颜色的情况下更改 GridView 单元格中的文本颜色