如何仅更改 tikz-qtree 中一个级别的级别距离?

如何仅更改 tikz-qtree 中一个级别的级别距离?

我正在尝试绘制一棵树来解决博弈论问题。问题是标签p1 = 0.5十字标签

我想调整第一级的级别距离,但是\tikzset{level distance=2cm]命令会改变所有距离。

也试过了\tikzstyle{level 1}=[level distance=2cm],但是没有用。我该怎么办?

我是 TikZ 的新手(仅 2 天),因此很乐意接受任何其他评论。

\documentclass{article}

\usepackage{tikz}
\usepackage{tikz-qtree}

\begin{document}
 \tikzset{edge from parent/.style=
 {draw, edge from parent path={(\tikzparentnode) -- (\tikzchildnode)}}}

\begin{tikzpicture}[grow=down] % game tree
\tikzstyle{mydot} = [circle, minimum width=2pt,fill, inner sep=0pt] % decision node style
\tikzstyle{mystart} = [circle, minimum width=3pt, fill, inner sep=0pt] % starting node style
% \tikzset{level distance=2cm} % attempt to adjust level distance 
\Tree 
    [.\node[mystart, label=above: {N}] {}; 
        \edge node[left] {$p_1=0.5$}; [.\node[mydot, label=above left:I] {}; 
            \edge node[left] {$a$}; \node[mydot, label=below: {$5,1$}] {};  
            \edge node[right] {$b$}; [.\node[mydot, label=above right:II] {};  
                \edge node[left] {$m$}; \node[mydot, label=below: {$1,2$}] {}; 
                \edge node[right] {$n$}; \node[mydot, label=below: {$2,3$}] {}; ]   ]
        \edge node[right] {$p_2=0.5$}; [.\node[mydot, label=above right:II] {};  
            \edge node[left] {$c$}; [.\node[mydot] (a) {};  
                \edge node[left] {$z$}; \node[mydot, label=below: {$1,0$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$2,2$}] {}; ] 
            \edge node[right] {$d$}; [.\node[mydot] (b) {}; 
                \edge node[left] {$z$}; \node[mydot, label=below: {$3,1$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$0,0$}] {}; ]   ]   ]
\draw[dashed] (a)--node[label=above:I] {}(b);
\end{tikzpicture}
\end{document}

答案1

更新

虽然这是公认的答案,但tikz-qtree在 2012 年进行了更新以允许这样做。


原始答案:

据我所知,没有一种方法可以使用 来指定特定级别的级别距离tikz-qtree。当然,您可以使用常规tikz方法,但通常输入效率更高。解​​决您的问题最简单的方法是稍微移动标签。您可以通过定位它们和tikz-qtree来做到这一点。[above left][above right]

我还对您的代码进行了一些简化,这样您可以减少输入内容:您可以创建every tree node自己的mydot样式,然后只需覆盖起始节点的样式即可。这意味着您不需要mydot向树中的每个节点添加命令。我还删除了[grow down]上的规范tikzpicture,因为这是 的默认增长方向tikz-qtree

\documentclass{article}

\usepackage{tikz}
\usepackage{tikz-qtree}

\begin{document}
\begin{tikzpicture}
\tikzstyle{mydot} = 
[circle, minimum width=2pt,fill, inner sep=0pt] % decision node style
\tikzstyle{mystart} = 
[circle, minimum width=3pt, fill, inner sep=0pt] % starting node style

\tikzset{edge from parent/.style=
{draw, 
 edge from parent path={(\tikzparentnode) -- (\tikzchildnode)}},
 every tree node/.style={mydot}} 
 % make every tree node a decision node; then you only have to override the start node

\Tree 
    [.\node[mystart, label=above: {N}] {};  
        \edge node[above left] {$p_1=0.5$}; [.\node[ label=above left:I] {}; 
            \edge node[left] {$a$}; \node[label=below: {$5,1$}] {};  
            \edge node[right] {$b$}; [.\node[ label=above right:II] {};  
                \edge node[left] {$m$}; \node[ label=below: {$1,2$}] {}; 
                \edge node[right] {$n$}; \node[ label=below: {$2,3$}] {}; ]   ]
        \edge node[above right] {$p_2=0.5$}; [.\node[ label=above right:II] {};  
            \edge node[left] {$c$}; [.\node[mydot] (a) {};  
                \edge node[left] {$z$}; \node[ label=below: {$1,0$}] {}; 
                \edge node[right] {$t$}; \node[ label=below: {$2,2$}] {}; ] 
            \edge node[right] {$d$}; [.\node[] (b) {}; 
                \edge node[left] {$z$}; \node[ label=below: {$3,1$}] {}; 
                \edge node[right] {$t$}; \node[ label=below: {$0,0$}] {}; ]   ]   ]
\draw[dashed] (a)--node[label=above:I] {}(b);
\end{tikzpicture}
\end{document}

代码输出

答案2

本答复中建议的修改现已纳入tikz-qtree软件包(版本 1.2 或更高)。有关如何使用最新版本实现此目的的详细信息,请参阅文档。

(此事发生于2012年4月。)


查看代码tikz-qtree然后它出现* 它完全重新实现了植树程序。因此,不能保证树的标准 TikZ 键能正常工作。这就是为什么level 2/.style={something}不起作用的原因tikz-qtree

虽然有可能将样式和键组合在一起,以便每个节点都知道它处于哪个级别,但这似乎是对主代码的一个非常有用的补充,而且肯定更简单通过对此进行小幅修改即可实现。首先是树生成系统。树是通过递归生成的,代码目前不跟踪递归级别。幸运的是,这很容易纠正:我们需要一个新的计数,我们在树的顶部将其设置为 0,并在我们向下移动时递增。我们的增量是本地的,以确保每当我们返回到某个级别(在处理子级的子级之后)时,我们的索引都在正确的位置。

--- pgftree.tex.orig    2010-12-31 00:50:24.000000000 +0100
+++ pgftree.tex 2012-04-19 10:34:57.286252337 +0200
@@ -82,11 +82,14 @@
 \newdimen\pgftree@savechildy
 \newcount\pgftree@childi
 \newcount\pgftree@savechildi
+\newcount\pgftree@level

 %%% \pgftree{subtree}

 \def\pgftree#1{%
 \def\nodename{r}%
+\pgftree@level=0\relax
+\pgfkeys{/pgf/qtree/every level/.try,/pgf/qtree/level \the\pgftree@level/.try}%
 #1%
 \pgfplacesubpicture
 }
@@ -108,6 +111,8 @@
 \pgftree@savechildx=\pgftree@childx
 \pgftree@savechildy=\pgftree@childy
 \pgftree@savechildi=\pgftree@childi
+\advance\pgftree@level by 1\relax
+\pgfkeys{/pgf/qtree/every level/.try,/pgf/qtree/level \the\pgftree@level/.try}%
 % Build subpicture with all the children and their subtrees
 {\pgftree@childx=0pt%
 \pgftree@childy=0pt%

现在我们可以跟踪树的级别了。树最终处于第 1 级。

现在我们需要使用该信息根据级别执行按键。为此,我们需要在相关阶段插入一些按键处理。有几个地方可以做到这一点:直接在代码中pgftree或在tikz-qtree代码中。我不确定哪个看起来更自然,代码有意义的两个地方有不同的效果(一个持续只是对于级别,另一个也会对树的所有后续部分产生影响),所以我为两者添加了代码。为了与 PGF 和 TikZ 的分离保持一致,部分中的键pgftree为 形式/pgf/qtree/level n,部分中的tikz-qtree键为 形式。我还通过添加一个在中附加了样式的键/tikz/level n,提供了对较低级别 TikZ 级别的访问。/pgf/qtree/every leveltikz-qtree/tikz,level \the\pgftree@level\space onwards

继承因素意味着,为了获得所需的风格,任何一个做:

\tikzset{level 1/.style={level distance=2cm}}

或者这样做:

\tikzset{level 1 onwards/.style={level distance=2cm}}
\tikzset{level 2 onwards/.style={level distance=1cm}}

该部分的补丁pgftree已包含在上面。该tikz-qtree部分内容如下:

--- tikz-qtree.tex.orig 2011-10-10 23:53:59.000000000 +0200
+++ tikz-qtree.tex  2012-04-19 10:39:02.516300095 +0200
@@ -75,9 +75,9 @@
 }
 \def\@@@@@@subtree{%
 \@ifequal{\the\root@node}{\pgfutil@empty}%
-\edef\act{\noexpand\@result={\noexpand\pgfsubtree{\noexpand\path coordinate (\noexpand\nodename);}{\the\child@list}}}%
+\edef\act{\noexpand\@result={\noexpand\pgfsubtree{\noexpand\tikzset{level \noexpand\the\pgftree@level/.try}\noexpand\path coordinate (\noexpand\nodename);}{\the\child@list}}}%
 \else
-\edef\act{\noexpand\@result={\noexpand\pgfsubtree{\the\root@node}{\the\child@list}}}%
+\edef\act{\noexpand\@result={\noexpand\pgfsubtree{\noexpand\tikzset{level \noexpand\the\pgftree@level/.try}\the\root@node}{\the\child@list}}}%
 \fi
 \act
 \@return}
@@ -117,7 +117,7 @@
 \def\@interior.{\@result{\node[alias=\nodename][every tree node,every internal node]}\@label}

 \def\@leaf{\@call\@label\@@leaf}
-\def\@@leaf{\edef\act{\noexpand\@result{\noexpand\pgfsubtree{\noexpand\node[alias=\noexpand\nodename][every tree node,every leaf node]\the\@result}{}}}\act\@return}
+\def\@@leaf{\edef\act{\noexpand\@result{\noexpand\pgfsubtree{\noexpand\tikzset{level \noexpand\the\pgftree@level/.try}\noexpand\node[alias=\noexpand\nodename][every tree node,every leaf node]\the\@result}{}}}\act\@return}

 \def\@edge\edge #1;{%
 \@result{\edge@adapter{#1}}%
@@ -179,3 +179,4 @@
 % predefined roof style
 \tikzset{roof/.style={edge from parent path=\roof@edge{\tikzparentnode}{\tikzchildnode}}}

+\pgfkeys{/pgf/qtree/every level/.append style={/tikz,level \the\pgftree@level\space onwards/.try}}

我很可能错过了一些应该设置键的地方!所以请谨慎使用。

这是包含这些新密钥的代码:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/39103/86}
\usepackage{tikz}
\usepackage{tikz-qtree}

\begin{document}
 \tikzset{edge from parent/.style=
 {draw, edge from parent path={(\tikzparentnode) -- (\tikzchildnode)}}}
\tikzset{got called/.code={\message{got called}}}

\begin{tikzpicture}[grow=down]% game tree
\tikzset{mydot/.style={circle, minimum width=2pt,fill, inner sep=0pt}} % decision node style
\tikzset{mystart/.style={circle, minimum width=3pt, fill, inner sep=0pt}} % starting node style
\Tree 
    [.\node[mystart, label=above: {N}] {}; 
        \edge node[left] {$p_1=0.5$}; [.\node[mydot, label=above left:I] {}; 
            \edge node[left] {$a$}; \node[mydot, label=below: {$5,1$}] {};  
            \edge node[right] {$b$}; [.\node[mydot, label=above right:II] {};  
                \edge node[left] {$m$}; \node[mydot, label=below: {$1,2$}] {}; 
                \edge node[right] {$n$}; \node[mydot, label=below: {$2,3$}] {}; ]   ]
        \edge node[right] {$p_2=0.5$}; [.\node[mydot, label=above right:II] {};  
            \edge node[left] {$c$}; [.\node[mydot] (a) {};  
                \edge node[left] {$z$}; \node[mydot, label=below: {$1,0$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$2,2$}] {}; ] 
            \edge node[right] {$d$}; [.\node[mydot] (b) {}; 
                \edge node[left] {$z$}; \node[mydot, label=below: {$3,1$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$0,0$}] {}; ]   ]   ]
\draw[dashed] (a)--node[label=above:I] {}(b);
\end{tikzpicture}
\begin{tikzpicture}[grow=down]% game tree
\tikzset{mydot/.style={circle, minimum width=2pt,fill, inner sep=0pt}} % decision node style
\tikzset{mystart/.style={circle, minimum width=3pt, fill, inner sep=0pt}} % starting node style
\tikzset{level 1/.style={level distance=2cm}}
\Tree 
    [.\node[mystart, label=above: {N}] {}; 
        \edge node[left] {$p_1=0.5$}; [.\node[mydot, label=above left:I] {}; 
            \edge node[left] {$a$}; \node[mydot, label=below: {$5,1$}] {};  
            \edge node[right] {$b$}; [.\node[mydot, label=above right:II] {};  
                \edge node[left] {$m$}; \node[mydot, label=below: {$1,2$}] {}; 
                \edge node[right] {$n$}; \node[mydot, label=below: {$2,3$}] {}; ]   ]
        \edge node[right] {$p_2=0.5$}; [.\node[mydot, label=above right:II] {};  
            \edge node[left] {$c$}; [.\node[mydot] (a) {};  
                \edge node[left] {$z$}; \node[mydot, label=below: {$1,0$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$2,2$}] {}; ] 
            \edge node[right] {$d$}; [.\node[mydot] (b) {}; 
                \edge node[left] {$z$}; \node[mydot, label=below: {$3,1$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$0,0$}] {}; ]   ]   ]
\draw[dashed] (a)--node[label=above:I] {}(b);
\end{tikzpicture}

\begin{tikzpicture}[grow=down]% game tree
\tikzset{mydot/.style={circle, minimum width=2pt,fill, inner sep=0pt}} % decision node style
\tikzset{mystart/.style={circle, minimum width=3pt, fill, inner sep=0pt}} % starting node style
\tikzset{level distance=2cm}
\tikzset{level 2 onwards/.style={level distance=1cm}}
\Tree 
    [.\node[mystart, label=above: {N}] {}; 
        \edge node[left] {$p_1=0.5$}; [.\node[mydot, label=above left:I] {}; 
            \edge node[left] {$a$}; \node[mydot, label=below: {$5,1$}] {};  
            \edge node[right] {$b$}; [.\node[mydot, label=above right:II] {};  
                \edge node[left] {$m$}; \node[mydot, label=below: {$1,2$}] {}; 
                \edge node[right] {$n$}; \node[mydot, label=below: {$2,3$}] {}; ]   ]
        \edge node[right] {$p_2=0.5$}; [.\node[mydot, label=above right:II] {};  
            \edge node[left] {$c$}; [.\node[mydot] (a) {};  
                \edge node[left] {$z$}; \node[mydot, label=below: {$1,0$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$2,2$}] {}; ] 
            \edge node[right] {$d$}; [.\node[mydot] (b) {}; 
                \edge node[left] {$z$}; \node[mydot, label=below: {$3,1$}] {}; 
                \edge node[right] {$t$}; \node[mydot, label=below: {$0,0$}] {}; ]   ]   ]
\draw[dashed] (a)--node[label=above:I] {}(b);
\end{tikzpicture}
\end{document}

以下是示例输出:

tikz-qtree 具有级别变化样式

我想补充一点,Ryan Reich 的出色trace-pgfkeys软件包对于完成上述任务绝对必不可少。特别是,它让我很容易看到标准level n键没有得到处理,这给了我提示,让我更深入地研究代码,看看到底发生了什么。参见我如何调试 pgfkeys?了解有关此最优秀套餐的更多信息。

* 我没有仔细研究过代码,所以我的推论可能是错误的。但是,它们与我的实验结果一致,所以我准备接受它们作为工作假设。

答案3

随着istgame包,您可以使用\xtdistance{<lev-dist>}{<sib-dist>}它来改变级别距离和兄弟距离。

请注意,使用 tikz-qtree 包与任何其他方法在 tikz 中绘制树可能会产生意想不到的结果。因此,除非您知道自己在做什么,否则请使用only tikz-qtreedo not use tikz-qtree使用 TikZ 绘制树。

在此处输入图片描述

\documentclass{standalone}

\usepackage{istgame}

\begin{document}    
\begin{istgame}[font=\footnotesize]
\xtdistance{15mm}{32mm}
\istroot(0){N}
  \istb{p_1=0.5}[l]
  \istb{p_2=0.5}[r]
  \endist
\xtdistance{10mm}{16mm}
\istroot(1)(0-1)<135>{I}
  \istb{a}[l]{5,1}[b]
  \istb{b}[r]
  \endist
\istroot(2)(0-2)<45>{II}
  \istb{c}[l]
  \istb{d}[r]
  \endist
\xtdistance{10mm}{8mm}
\istroot(3)(1-2)<45>{II}
  \istb{m}[l]{1,2}
  \istb{n}[r]{2,3}
  \endist
\istroot(3a)(2-1)
  \istb{z}[l]{1,0}
  \istb{t}[r]{2,2}
  \endist
\istroot(3b)(2-2)
  \istb{z}[l]{3,1}
  \istb{t}[r]{0,0}
  \endist
\xtInfoset(3a)(3b){I}
\end{istgame}

\end{document}

相关内容