构建ActiveView构件

This commit is contained in:
codeboss 2024-07-30 23:52:02 +08:00
parent c78f66f5e4
commit b3fc5f325a
8 changed files with 129 additions and 69 deletions

View File

@ -5,13 +5,10 @@
</component>
<component name="ChangeListManager">
<list default="true" id="f609c0f2-cd0d-4eea-87f1-8caf02d3f04f" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/frame/ContentView.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/graph/DataType.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/graph/__init__.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/graph/dagpresent/DAGGraph.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/graph/dagpresent/__init__.py" afterDir="false" />
<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$/frame/MergeView.py" beforeDir="false" afterPath="$PROJECT_DIR$/frame/MergeView.py" 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" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -43,7 +40,11 @@
"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",
@ -54,10 +55,11 @@
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master",
"last_opened_file_path": "D:/Projects/Python/StoryCheckTools"
"last_opened_file_path": "D:/Projects/Python/StoryCheckTools",
"settings.editor.selected.configurable": "reference.settings.ide.settings.new.ui"
}
}]]></component>
<component name="RunManager" selected="Python.DAGGraph">
<component name="RunManager" selected="Python.DAGPresent">
<configuration name="CompareViews" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
@ -80,7 +82,7 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="DAGGraph" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<configuration name="DAGLayout" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
@ -89,11 +91,11 @@
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/graph/dagpresent" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/graph/directed_acyclic_graph" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/graph/dagpresent/DAGGraph.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGLayout.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
@ -102,7 +104,7 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="MileStone" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<configuration name="DAGPresent" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
@ -111,12 +113,12 @@
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/manage" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/graph/directed_acyclic_graph" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/manage/MileStone.py" />
<option name="PARAMETERS" value="milestone:new" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/graph/directed_acyclic_graph/DAGPresent.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
@ -146,49 +148,25 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="entry" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="StoryTools" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/entry.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<list>
<item itemvalue="Python.DAGGraph" />
<item itemvalue="Python.DAGLayout" />
<item itemvalue="Python.DAGPresent" />
<item itemvalue="Python.CompareViews" />
<item itemvalue="Python.NovelManage" />
<item itemvalue="Python.entry" />
<item itemvalue="Python.MileStone" />
</list>
<recent_temporary>
<list>
<item itemvalue="Python.DAGGraph" />
<item itemvalue="Python.DAGPresent" />
<item itemvalue="Python.DAGLayout" />
<item itemvalue="Python.CompareViews" />
<item itemvalue="Python.NovelManage" />
<item itemvalue="Python.MileStone" />
<item itemvalue="Python.entry" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-python-sdk-5b207ade9991-746f403e7f0c-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-241.17890.14" />
<option value="bundled-python-sdk-50da183f06c8-d3b881c8e49f-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-233.13135.95" />
</set>
</attachedChunks>
</component>

View File

@ -1,11 +1,5 @@
from graph.DataType import Point, Arrow
from typing import List, Dict, Tuple
from enum import Enum
class Direction(Enum):
RankLR = 0,
RankTB = 1,
class DAGLayerHelper:
@ -46,6 +40,7 @@ class DAGOrderHelper:
def __init__(self, level:int = 0, relate:DAGLayerHelper|None = None, bind: DAGLayerHelper|None = None):
self.layer_bind = bind
self.relate_bind = relate
self.layer_number = level
self.sort_number:float = 0
self.__prev_layer_nodes: List['DAGOrderHelper'] = []
@ -67,8 +62,7 @@ class DAGOrderHelper:
class DAGGraph:
def __init__(self, orie: Direction):
self.orientation = orie
def __init__(self):
self.graph_inst: Dict[str, DAGLayerHelper] = {}
self.nodes_with_layout: List[DAGOrderHelper] = []
pass
@ -99,37 +93,39 @@ class DAGGraph:
pass
pass
def __spawns_peak(self, refset: List[DAGLayerHelper]) -> Tuple[DAGLayerHelper, List[DAGLayerHelper]] | None:
def __spawns_peak(self, ref_set: List[DAGLayerHelper]) -> Tuple[DAGLayerHelper, List[DAGLayerHelper]] | None:
"""
拓扑排序迭代处理
:param refset:
:param ref_set:
:return:
"""
for inst in refset:
for inst in ref_set:
if inst.input_count == 0:
for it_nxt in inst.next_nodes():
refset.append(it_nxt)
it_nxt.input_count -= 1
if it_nxt not in ref_set:
ref_set.append(it_nxt)
pass
pass
refset.remove(inst)
if inst.bind_point().point_name in self.graph_inst:
self.graph_inst.pop(inst.bind_point().point_name)
return inst, refset
ref_set.remove(inst)
self.graph_inst.pop(inst.bind_point().point_name)
return inst, ref_set
for inst in self.graph_inst.values():
if inst.input_count == 0:
if inst in refset:
refset.remove(inst)
if inst in ref_set:
ref_set.remove(inst)
for it_nxt in inst.next_nodes():
refset.append(it_nxt)
it_nxt.input_count -= 1
if it_nxt not in ref_set:
ref_set.append(it_nxt)
pass
pass
self.graph_inst.pop(inst.bind_point().point_name)
return inst, refset
return inst, ref_set
pass
if len(self.graph_inst) > 0:
@ -254,7 +250,6 @@ class DAGGraph:
self.__graph_layer_nodes_sort(layer_index + 1, nodes)
pass
def graph_layout(self):
sort_seqs = []
@ -299,17 +294,22 @@ class DAGGraph:
if __name__ == "__main__":
graph = DAGGraph(Direction.RankLR)
graph = DAGGraph()
arrows = [
Arrow(Point('a'), Point('b')),
Arrow(Point('a'), Point('c')),
Arrow(Point('c'), Point('d')),
Arrow(Point('a'), Point('d')),
Arrow(Point('c'), Point('e')),
Arrow(Point('c'), Point('f')),
]
graph.rebuild_from_edges(arrows)
graph.graph_layout()
points = graph.visible_nodes()
points = graph.nodes_with_layout
for p in points:
print(f"{p.layer_bind.bind_point().point_name},level{p.layer_number},sort{p.sort_number}")
if not p.is_fake_node():
print(f"{p.layer_bind.bind_point().point_name},level{p.layer_number},sort{p.sort_number}")
else:
print(f"'{p.relate_bind.bind_point().point_name}',level{p.layer_number},sort{p.sort_number}")

View File

@ -0,0 +1,82 @@
from graph.directed_acyclic_graph.DAGLayout import DAGGraph
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
import sys
from enum import Enum
class StoryFragmentNode(QGraphicsItem):
"""
故事情节名称节点
"""
def __init__(self, name:str, font: QFont, parent):
QGraphicsItem.__init__(self, parent)
self.fragment_name = name
self.font_bind = font
self.data_bind: object = None
pass
def boundingRect(self) -> QRectF:
size = self.font_bind.pixelSize()
return QRectF(0, 0, size * len(self.fragment_name) + 10, size + 10)
def paint(self, painter, option, widget = ...):
outline = self.boundingRect()
text_rect = QRectF(outline.x()+5, outline.y()+5, outline.width()-10, outline.height() - 10)
painter.save()
painter.fillRect(outline, QBrush(Qt.gray))
painter.drawRect(outline)
painter.setFont(self.font_bind)
painter.drawText(text_rect, self.fragment_name)
painter.restore()
# 添加自定义功能函数
def attach_data(self, data_inst: object):
self.data_bind = data_inst
pass
def get_data(self) -> object:
return self.data_bind
class Direction(Enum):
RankLR = 0,
RankTB = 1,
class DAGActiveView(QGraphicsView):
def __init__(self, orie: Direction, parent):
QGraphicsView.__init__(self, parent)
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))
pass
def update_with_edges(self, arrows: List[Arrow]) -> None:
tools = DAGGraph()
tools.rebuild_from_edges(arrows)
tools.graph_layout()
total_nodes = tools.nodes_with_layout
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
view = DAGActiveView(Direction.RankLR, None)
view.show()
app.exec()