python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank=’sink’ ; rank=’source’ ; rank=’same’ ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank=’true’) #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank=’sink’) # 設置子圖為sink ; s.node(‘Logo’, ‘Company Logo’)

加入好友
加入社群
python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

Graphviz是一個強大的圖形可視化工具,
而其中rank屬性是控制節點垂直佈局的關鍵參數之一。
本文將深入介紹rank='sink'的使用方法和實際應用場景。

什麼是rank=’sink’?

在Graphviz中,rank屬性用於指定子圖在垂直方向的位置層級。
rank='sink'特別表示將節點或子圖放置在圖的最底部,
不管其他節點的位置如何。

常見的rank值包括:
rank='source' – 放置在最頂部

rank='sink' – 放置在最底部

rank='same' – 與其他同級節點保持在同一水平線

rank='min' – 優先放在頂部

rank='max' – 優先放在底部

rank=’sink’ 的正確使用方法

要使用rank='sink',應該在子圖中設置此屬性,
而不是直接在節點上設置。
以下是正確的實現方式:

from graphviz import Digraph

g = Digraph()

# 主圖中的節點
g.node('A', 'Node A')
g.node('B', 'Node B')
g.node('C', 'Node C')
g.edges([("A", "B"), ("B", "C")])

# 正確在子圖中使用rank='sink'
with g.subgraph() as s:
    s.attr(rank='sink')  # 設置子圖為sink
    s.node('Logo', 'Company Logo')  
    # Logo節點會被放在最底部
    #子圖只有一個節點(node)

g.render('correct_sink', format='png', view=True)

輸出結果:

python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

 注意:在上面的例子中,
我們創建了一個子圖,設置其rank='sink'
然後在這個子圖中添加了Logo節點。
這確保Logo節點被放在圖的最底部。

常見錯誤:直接在節點上設置rank

以下代碼展示了一個常見錯誤:嘗試直接在節點上設置rank屬性:

from graphviz import Digraph

g = Digraph()

# 主圖中的節點
g.node('A', 'Node A')
g.node('B', 'Node B')
g.node('C', 'Node C')
g.edges([("A", "B"), ("B", "C")])

# 錯誤直接在節點上設置rank
g.node('Logo', 'Company Logo', rank='sink')  # 這不會按預期工作

g.render('incorrect_sink', 
format='png', view=True)

輸出結果:

python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

這種方法作用不如預期,
因為在Python的Graphviz接口中,
rank不是節點屬性,而是子圖屬性
不論有無 rank=’sink’ 圖形都是這樣排列。

多個層級的進階使用

我們可以使用多個子圖來創建多個具有不同rank值的節點組:

from graphviz import Digraph

g = Digraph()

# 設置一些常規節點
g.node('A', 'Process Start')
g.node('B', 'Process Middle')
g.node('C', 'Process End')
g.edges([("A", "B"), ("B", "C")])

# 創建頂部標題子圖
with g.subgraph() as s:
    s.attr(rank='source')  # 放在最頂部
    s.node('Title', 'PROCESS FLOW CHART')

# 創建底部註腳子圖
with g.subgraph() as s:
    s.attr(rank='sink')  # 放在最底部
    s.node('Footer', 'Copyright © 2025')
    s.node('Logo', 'Company Logo')

# 連接標題和註腳不影響rank
g.edge('Title', 'A', style='invis')  # 不可見邊僅用於佈局
g.edge('C', 'Footer', style='invis')  # 不可見邊僅用於佈局

g.render('multi_level_ranks', format='png', view=True)

輸出結果:

python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

rank=’sink’ 的實際應用場景

  1. 添加頁腳或標識:將公司標識、版權信息或文檔頁腳放在圖表底部。
  2. 流程終點標記:在流程圖中標記最終狀態或終點。
  3. 圖例位置控制:確保圖例始終出現在圖表的底部。
  4. 分層架構圖:在系統架構圖中,明確表示底層組件。

小結:rank=’sink’ 的關鍵要點

  1. 使用方式:必須在子圖中使用,而不是直接在節點上設置。
  2. 作用:將節點或一組節點放置在圖的最底部。
  3. 搭配使用:可與其他rank值如’source’、’same’等結合使用,創建層次分明的圖表。
  4. 實用場景:適用於添加頁腳、圖例或終點標記等需要固定在底部的元素。

透過正確使用rank='sink'及其他rank值,
您可以精確控制Graphviz圖的垂直布局,
創建出層次分明、結構清晰的可視化圖表。

推薦hahow線上學習python: https://igrape.net/30afN

部分code:

# 添加流程底部的輔助節點
g.node('BottomAnchor', '', shape='point', 
style='invis', width='0', height='0')

# 使用rank=sink確保輔助節點在最底部
with g.subgraph() as s:
    s.attr(rank='sink')
    s.node('BottomAnchor')

# 添加從Repair6到ICT的大弧線連接
# 使用隱形輔助邊引導弧線路徑
g.edge('Repair6', 'BottomAnchor', 
style='invis', constraint='true')
g.edge('ICT', 'BottomAnchor', 
style='invis', constraint='true')

# 添加從Repair6到ICT的大弧線使用特殊設置
g.edge('Repair6', 'ICT', label="OK", 
constraint='false', tailport='s', headport='s') 
#, minlen='4' #這個參數無影響

也可沉在最底部,
作為隱形的子圖(僅有一個node)
Repair6 (最右方最底下的Repair, label為空字串)
Repair 6 & ICT 都與 BottomAnchor子圖
使用隱形的線連接起來 (constraint=“true”)
Repair 6 的南邊 -> ICT 的南邊 再連接 (constraint=“false”),
可以讓Repair6 -> ICT 使用弧狀的線連接

python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

推薦hahow線上學習python: https://igrape.net/30afN

rank=’sink’ 不可與
g.attr(newrank=’true’)
#子圖同高度
一起使用
code:

from graphviz import Digraph

# 创建图表并设置newrank=true
g = Digraph('Manufacturing_test_flow', 
filename='manufacturing_test_flow.gv', 
format='png', engine='dot')
g.attr(rankdir='TB')  # 从上到下的布局
g.attr(newrank='true')  # 启用newrank

# 左侧流程
g.node('L1', 'Left Top', shape='box')
g.node('L2', 'Left Middle', shape='box')
g.node('L3', 'Left Bottom', shape='box')
g.edge('L1', 'L2')
g.edge('L2', 'L3')

# 右侧流程
g.node('R1', 'Right Top', shape='box')
g.node('R2', 'Right Middle', shape='box')
g.node('R3', 'Right Bottom', shape='box')
g.edge('R1', 'R2')
g.edge('R2', 'R3')

# # 确保上层节点在同一水平线上
# with g.subgraph() as s:
#     s.attr(rank='same')
#     s.node('L1')
#     s.node('R1')

# # 确保中间节点在同一水平线上
# with g.subgraph() as s:
#     s.attr(rank='same')
#     s.node('L2')
#     s.node('R2')

# # 确保底层节点在同一水平线上
# with g.subgraph() as s:
#     s.attr(rank='same')
#     s.node('L3')
#     s.node('R3')

# 添加sink节点到最底部
with g.subgraph() as s:
    s.attr(rank='sink')
    s.node('LeftSink', 'Left Sink Node', 
    shape='box', style='filled', 
    fillcolor='lightblue')
    s.node('RightSink', 'Right Sink Node', 
    shape='box', style='filled', 
    fillcolor='lightblue')

# # 连接到sink节点
# g.edge('L3', 'LeftSink')
# g.edge('R3', 'RightSink')

# 渲染图形
g.render(view=True)

輸出結果:

python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

LeftSink 與 RightSink
未因為rank=’sink’的設定
而沉在最底下

註解掉這一行程式碼
# g.attr(newrank=’true’)  # 启用newrank
rank=’sink’ 的設定
就如預期般地作用

python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

推薦hahow線上學習python: https://igrape.net/30afN

加入好友
加入社群
python Graphviz中控制子圖(子圖可以僅含一個node)垂直位置教學: rank='sink' ; rank='source' ; rank='same' ; 為子圖的屬性,在node中設定無效 ; 不可與g.attr(newrank='true') #子圖同高度 一起使用; with g.subgraph() as s: s.attr(rank='sink') # 設置子圖為sink ; s.node('Logo', 'Company Logo') - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *