How to change the level distance in tikz-qtree for one level only?

The modifications suggested in this answer have now been subsumed into the tikz-qtree package (version 1.2 or higher). See the documentation for details on how to accomplish this with the latest version.

(This happened in April 2012.)


Looking through the code for tikz-qtree then it appears* that it completely reimplements the tree-planting routines. Therefore, the standard TikZ keys for trees are not guaranteed to work. This is why level 2/.style={something} doesn't work for tikz-qtree.

Whilst it might be possible to hack something together with styles and keys so that each node knows what level it is at, this seems like it would be quite a useful addition to the main code and it is certainly simpler to do by small modifications to that. The first is to the tree-generation system. The trees are generated by a recursion and the code does not currently track the level of recursion. Fortunately, that's simple to correct: we need a new count which we set to 0 at the top of the tree and increment as we go down. Our increments are local to ensure that whenever we return to a level (after processing a child's sublevels), our index is at the right place.

--- 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%

That now allows us to track the level of our tree. The root of the tree ends up at level 1.

Now we need to use that information to execute keys according to the level. To do this, we need to insert some key processing at the relevant stages. There are a couple of places where we could do this: directly in the pgftree code or in the tikz-qtree code. I'm not sure which seems more natural, and the two places where the code makes sense have different effects (one lasts just for the level, the other also has an effect on all subsequent parts of the tree), so I've added code for both. To be consistent with the separation of PGF and TikZ, the keys in the pgftree part are of the form /pgf/qtree/level n and in the tikz-qtree are of the form /tikz/level n. I've also provided a TikZ-level access to the lower-level one by adding a /pgf/qtree/every level key which in tikz-qtree has appended to it the style /tikz,level \the\pgftree@level\space onwards.

The inheritance factor means that to get the desired style, one either does:

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

or one does:

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

The patch for the pgftree part is included above. The tikz-qtree part follows:

--- 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}}

It is entirely possible that I've missed some places where keys should be set! So use with caution.

Here's your code with these new keys included:

\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}

Here's the sample output:

tikz-qtree with level changing styles

I would like to add that Ryan Reich's fantastic trace-pgfkeys package was absolutely essential in doing the above. In particular, it made it easy to see that the standard level n keys were not getting processed, which gave me the hint to look deeper into the code to see what exactly was going on. See How do I debug pgfkeys? for more on this most excellent package.

* I've not gone through the code extensively so my deductions could be false. However, they agree with the results of my experiments so I'm prepared to accept them as a working hypothesis.


UPDATE

Although this is the accepted answer, tikz-qtree was updated in 2012 to allow this.

  • See Loop Space's answer.

Original answer:

There isn't a way that I know of to specify the level distance for particular levels using tikz-qtree. Of course you could use the regular tikz methods, but tikz-qtree is generally much more efficient in its input. The simplest solution to your problem is to simply move the labels slightly. You can do this by positioning them [above left] and [above right].

I've also made some simplification to your code which will give you less to type: you can make every tree node have your mydot style, and then just override the style for the start node. This means you don't need to add mydot to each of the node commands in the tree. I also removed the [grow down] specification on the tikzpicture, since that is the default growth direction for 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}

output of code


With the istgame package, you can use \xtdistance{<lev-dist>}{<sib-dist>} to change level distances and sibling distances.

Please note that using the tikz-qtree package together with any other method to draw trees in tikz, may give you unexpected results. So use only tikz-qtree or do not use tikz-qtree to draw trees with TikZ, unless you know what you are doing.

enter image description here

\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}