在不更改现有图纸颜色的情况下更改新图纸的颜色

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()

【讨论】:

以上是关于在不更改现有图纸颜色的情况下更改新图纸的颜色的主要内容,如果未能解决你的问题,请参考以下文章

CAD中怎样改变图纸中字体的大小和颜色???

CAD图纸中的文字颜色要怎么修改

如何在不更改整个文本视图颜色的情况下更改文本颜色

在不更改边框颜色的情况下更改 GridView 单元格中的文本颜色

PyQt 在不重置样式的情况下更改 QPushButton 背景颜色

VIM:如何在不使用非文本颜色元素的情况下更改 Showbreak Highlight 颜色