This commit is contained in:
codeboss 2024-07-31 07:57:17 +08:00
parent b3fc5f325a
commit f86b7bf460
3 changed files with 153 additions and 32 deletions

View File

@ -5,10 +5,9 @@
</component>
<component name="ChangeListManager">
<list default="true" id="f609c0f2-cd0d-4eea-87f1-8caf02d3f04f" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/graph/directed_acyclic_graph/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/graph/dagpresent/DAGGraph.py" beforeDir="false" afterPath="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGLayout.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/graph/dagpresent/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGPresent.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGLayout.py" beforeDir="false" afterPath="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGLayout.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGPresent.py" beforeDir="false" afterPath="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGPresent.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -36,29 +35,29 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Python.CompareViews.executor": "Run",
"Python.CompareWindow.executor": "Run",
"Python.DAGGraph (1).executor": "Run",
"Python.DAGGraph.executor": "Run",
"Python.DAGLayout (1).executor": "Run",
"Python.DAGLayout.executor": "Run",
"Python.DAGPresent.executor": "Run",
"Python.MergeView.executor": "Run",
"Python.MileStone.executor": "Run",
"Python.NovelManage.executor": "Debug",
"Python.ReferView.executor": "Run",
"Python.StoryMap.executor": "Run",
"Python.ast_load.executor": "Debug",
"Python.entry.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master",
"last_opened_file_path": "D:/Projects/Python/StoryCheckTools",
"settings.editor.selected.configurable": "reference.settings.ide.settings.new.ui"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;Python.CompareViews.executor&quot;: &quot;Run&quot;,
&quot;Python.CompareWindow.executor&quot;: &quot;Run&quot;,
&quot;Python.DAGGraph (1).executor&quot;: &quot;Run&quot;,
&quot;Python.DAGGraph.executor&quot;: &quot;Run&quot;,
&quot;Python.DAGLayout (1).executor&quot;: &quot;Run&quot;,
&quot;Python.DAGLayout.executor&quot;: &quot;Run&quot;,
&quot;Python.DAGPresent.executor&quot;: &quot;Run&quot;,
&quot;Python.MergeView.executor&quot;: &quot;Run&quot;,
&quot;Python.MileStone.executor&quot;: &quot;Run&quot;,
&quot;Python.NovelManage.executor&quot;: &quot;Debug&quot;,
&quot;Python.ReferView.executor&quot;: &quot;Run&quot;,
&quot;Python.StoryMap.executor&quot;: &quot;Run&quot;,
&quot;Python.ast_load.executor&quot;: &quot;Debug&quot;,
&quot;Python.entry.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master&quot;,
&quot;last_opened_file_path&quot;: &quot;D:/Projects/Python/StoryCheckTools&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;reference.settings.ide.settings.new.ui&quot;
}
}]]></component>
}</component>
<component name="RunManager" selected="Python.DAGPresent">
<configuration name="CompareViews" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />

View File

@ -65,6 +65,7 @@ class DAGGraph:
def __init__(self):
self.graph_inst: Dict[str, DAGLayerHelper] = {}
self.nodes_with_layout: List[DAGOrderHelper] = []
self.max_layer_count = 0
pass
def rebuild_from_edges(self, arrow_list: List[Arrow]) -> None:
@ -269,10 +270,9 @@ class DAGGraph:
self.__graph_recovery(sort_seqs)
# 数据图节点分层
max_length = 0
for item in sort_seqs:
if item.input_count == 0:
max_length = max(max_length, self.__node_layering(item))
self.max_layer_count = max(self.max_layer_count, self.__node_layering(item))
pass
pass

View File

@ -1,14 +1,25 @@
from graph.directed_acyclic_graph.DAGLayout import DAGGraph
from graph.directed_acyclic_graph.DAGLayout import DAGGraph, DAGOrderHelper
from graph.DataType import Arrow, Point
from typing import List
from PyQt5.QtWidgets import QWidget, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
from PyQt5.QtCore import QRectF, Qt
from PyQt5.QtGui import QFont, QBrush
from PyQt5.QtCore import QRectF, Qt, QPointF
from PyQt5.QtGui import QFont, QBrush, QPen, QPainter
import sys
from enum import Enum
from abc import abstractmethod
class StoryFragmentNode(QGraphicsItem):
class GraphNode:
@abstractmethod
def boundingRect(self) -> QRectF:
raise NotImplementedError("boundingRect")
@abstractmethod
def pos(self)->QPointF:
raise NotImplementedError("pos")
class StoryFragmentNode(QGraphicsItem, GraphNode):
"""
故事情节名称节点
"""
@ -35,6 +46,8 @@ class StoryFragmentNode(QGraphicsItem):
painter.drawText(text_rect, self.fragment_name)
painter.restore()
pass
# 添加自定义功能函数
def attach_data(self, data_inst: object):
@ -44,6 +57,72 @@ class StoryFragmentNode(QGraphicsItem):
def get_data(self) -> object:
return self.data_bind
pass
class PenetrateNode(QGraphicsItem, GraphNode):
"""
贯穿连线节点
"""
def __init__(self, width:float, parent):
QGraphicsItem.__init__(self, parent)
self.width_store = width
pass
def resize(self, width: float):
self.width_store = width
self.update()
pass
def boundingRect(self):
return QRectF(0, 0, self.width_store, 8)
def paint(self, painter, option, widget = ...):
outline = self.boundingRect()
painter.save()
painter.fillRect(QRectF(0, 2, outline.width(), 4), Qt.black)
painter.restore()
pass
class CurveTransition(QGraphicsItem):
def __init__(self, start: GraphNode, end: GraphNode, parent):
QGraphicsItem.__init__(self, parent)
self.start_node = start
self.end_node = end
self.outline = QRectF()
pass
def layout_refresh(self):
self.setPos(self.start_node.boundingRect().topRight())
self.outline = QRectF(0, 0,
self.end_node.pos().x() - self.start_node.pos().x() - self.start_node.boundingRect().width(),
self.end_node.pos().y() + self.end_node.boundingRect().height() - self.start_node.pos().y())
pass
def boundingRect(self):
return self.outline
pass
def paint(self, painter, option, widget = ...):
outline = self.outline
painter.save()
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
start_rect = self.start_node.boundingRect()
end_rect = self.end_node.boundingRect()
start_pos = QPointF(0, start_rect.height()/2)
end_pos = QPointF(outline.width(), outline.height() - end_rect.height()/2)
npen = QPen(Qt.black)
npen.setWidthF(4)
painter.setPen(npen)
painter.drawLine(start_pos, end_pos)
painter.restore()
pass
class Direction(Enum):
RankLR = 0,
@ -54,13 +133,24 @@ class DAGActiveView(QGraphicsView):
def __init__(self, orie: Direction, parent):
QGraphicsView.__init__(self, parent)
self.transition_with = 200
self.orientation = orie
self.scene_bind = QGraphicsScene(self)
self.setScene(self.scene_bind)
font_global = QFont()
font_global.setPixelSize(20)
self.scene_bind.addItem(StoryFragmentNode("实例节点:示例情节", font_global, None))
one = StoryFragmentNode("实例节点:示例情节", font_global, None)
self.scene_bind.addItem(one)
two = PenetrateNode(200, None)
two.setPos(QPointF(500, 400))
self.scene_bind.addItem(two)
connectx = CurveTransition(one, two, None)
self.scene_bind.addItem(connectx)
connectx.layout_refresh()
pass
@ -70,6 +160,38 @@ class DAGActiveView(QGraphicsView):
tools.graph_layout()
total_nodes = tools.nodes_with_layout
for layer_idx in range(0, tools.max_layer_count):
current_level_nodes: List[DAGOrderHelper] = list(filter(lambda n:n.layer_number == layer_idx, total_nodes))
current_level_nodes.sort(key=lambda n:n.sort_number)
# 构建当前层节点
ypos_acc = 0
all_nodes = []
for node in current_level_nodes:
if node.is_fake_node():
node = PenetrateNode(20, None)
ypos_acc += node.boundingRect().height()
all_nodes.append(node)
self.scene_bind.addItem(node)
else:
node = StoryFragmentNode(node.layer_bind.bind_point().point_name, self.font(), None)
ypos_acc += node.boundingRect().height()
all_nodes.append(node)
self.scene_bind.addItem(node)
pass
pass
width_max = 0
for n in all_nodes:
width_max = max(width_max, n.boundingRect().width())
pass
for n in all_nodes:
if n is PenetrateNode:
n.resize(width_max)
pass
pass
pass
pass