![将 TikZ 图形垂直对齐到多列中的邻居](https://linux22.com/image/259198/%E5%B0%86%20TikZ%20%E5%9B%BE%E5%BD%A2%E5%9E%82%E7%9B%B4%E5%AF%B9%E9%BD%90%E5%88%B0%E5%A4%9A%E5%88%97%E4%B8%AD%E2%80%8B%E2%80%8B%E7%9A%84%E9%82%BB%E5%B1%85.png)
为了在 Prolog 中记录块世界问题,我想展示示例代码(使用 listing 包)以及我使用 TikZ 制作的真实世界等效代码。为此,我使用了多列包和 2 列。
不幸的是,这两个元素的两个框架不是从同一高度开始的。我希望这两个元素的顶部边框从同一垂直点开始。
以下是示例代码:
\documentclass[11pt]{article}
\usepackage{tikz}
\usepackage{multicol}
\usepackage{listings}
\lstset{ %
language=Prolog, % the language of the code
basicstyle=\scriptsize\ttfamily, % the size of the fonts that are used for the code
numbers=left, % where to put the line-numbers
numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers
stepnumber=1, % the step between two line-numbers. If it's 1, each line will be numbered
numbersep=5pt, % how far the line-numbers are from the code
backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
showspaces=false, % show spaces adding particular underscores
showstringspaces=false, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
frame=single, % adds a frame around the code
rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text
tabsize=4, % sets default tabsize to 4 spaces
captionpos=b, % sets the caption-position to bottom
breaklines=true, % sets automatic line breaking
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
title=\lstname, % show the filename of files included with \lstinputlisting;
% also try caption instead of title
keywordstyle=\color{blue}, % keyword style
commentstyle=\color{dkgreen}, % comment style
stringstyle=\color{mauve}, % string literal style
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
}
\begin{document}
\tikzstyle{block} = [rectangle, draw, minimum height=1cm, minimum width=1cm]
\tikzstyle{table} = [rectangle, draw, minimum width=5cm, minimum height=0.5cm, fill=gray!50]
\tikzstyle{b1} = [fill=orange!50]
\tikzstyle{b2} = [fill=green!50]
\tikzstyle{b3} = [fill=cyan!50]
\tikzstyle{b4} = [fill=red!50]
This is an example paragraph.
\begin{multicols}{2}
\begin{lstlisting}[language=Prolog]
[
block(block1),
block(block2),
block(block3),
block(block4),
on(table,block2),
on(table,block3),
on(block2,block1),
on(table,block4),
clear(block1),
clear(block3),
clear(block4),
handempty
]
\end{lstlisting}
\begin{tikzpicture}
\draw(-2,-2) rectangle (5,4);
\node[block, b3] at (1.5,0) {3};
\node[block, b2] at (0,0) {2};
\node[block, b1] at (0,1) {1};
\node[block, b4] at (3,0) {4};
\node[table] at (1.5,-0.75) {Table};
\end{tikzpicture}
\end{multicols}
Another paragraph can follow here.
\end{document}
这是结果,显示了顶部边框不在同一垂直水平上的问题:
答案1
如果不使用 multicol,而是将列表放入 tikz 节点中,则可以得到以下结果:
代码
这段代码相当脏,因为它包含很多硬编码的长度。为了完全自动化这些测量,需要精确地知道列表节点的高度。这可以通过以下方法实现:这个问题,但由于某种原因,列表改变了节点的排版方式,导致测量的高度过大。因此,在我找到更好的方法之前,我将在这里留下一个肮脏但有效的代码。
\documentclass[11pt]{article}
\usepackage{tikz}
% \usepackage{multicol} % no longer necessary
\usepackage{listings}
\usepackage{lipsum}
\lstset{ %
language=Prolog, % the language of the code
basicstyle=\scriptsize\ttfamily, % the size of the fonts that are used for the code
numbers=left, % where to put the line-numbers
numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers
stepnumber=1, % the step between two line-numbers. If it's 1, each line will be numbered
numbersep=5pt, % how far the line-numbers are from the code
backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
showspaces=false, % show spaces adding particular underscores
showstringspaces=false, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
frame=single, % adds a frame around the code
rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text
tabsize=4, % sets default tabsize to 4 spaces
captionpos=b, % sets the caption-position to bottom
breaklines=true, % sets automatic line breaking
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
title=\lstname, % show the filename of files included with \lstinputlisting;
% also try caption instead of title
keywordstyle=\color{blue}, % keyword style
commentstyle=\color{dkgreen}, % comment style
stringstyle=\color{mauve}, % string literal style
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
}
\begin{document}
\tikzstyle{block} = [rectangle, draw, minimum height=1cm, minimum width=1cm]
\tikzstyle{table} = [rectangle, draw, minimum width=5cm, minimum height=0.5cm, fill=gray!50]
\tikzstyle{b1} = [fill=orange!50]
\tikzstyle{b2} = [fill=green!50]
\tikzstyle{b3} = [fill=cyan!50]
\tikzstyle{b4} = [fill=red!50]
\lipsum[1]
%\begin{multicols}{2}
\begin{tikzpicture}
\node at (-5,0) {
\begin{lstlisting}[language=Prolog,linewidth=5cm]
[
block(block1),
block(block2),
block(block3),
block(block4),
on(table,block2),
on(table,block3),
on(block2,block1),
on(table,block4),
clear(block1),
clear(block3),
clear(block4),
handempty
]
\end{lstlisting}
};
\draw(-1.5,-2.05) rectangle (4.5,2.8);
\node[block, b3] at (1.5,0) {3};
\node[block, b2] at (0,0) {2};
\node[block, b1] at (0,1) {1};
\node[block, b4] at (3,0) {4};
\node[table] at (1.5,-0.75) {Table};
\end{tikzpicture}
%\end{multicols}
\lipsum[2]
\end{document}
编辑(根据 OP 的评论)
下面的代码在某种程度上完成了对齐所需的高度计算。
\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{multicol}
\usepackage{listings}
\usepackage{lipsum}
\lstset{ %
language=Prolog, % the language of the code
basicstyle=\scriptsize\ttfamily, % the size of the fonts that are used for the code
numbers=left, % where to put the line-numbers
numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers
stepnumber=1, % the step between two line-numbers. If it's 1, each line will be numbered
numbersep=5pt, % how far the line-numbers are from the code
% backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
showspaces=false, % show spaces adding particular underscores
showstringspaces=false, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
% frame=single, % adds a frame around the code
% rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text
tabsize=4, % sets default tabsize to 4 spaces
captionpos=b, %
breaklines=true, % sets automatic line breaking
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
% title=\lstname, % show the filename of files included with \lstinputlisting;
% also try caption instead of title
keywordstyle=\color{blue}, % keyword style
commentstyle=\color{dkgreen}, % comment style
stringstyle=\color{mauve}, % string literal style
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
}
\makeatletter
\newcommand\getheightofnode[2]{%
\pgfextracty{#1}{\pgfpointanchor{#2}{north}}%
\pgfextracty{\pgf@xa}{\pgfpointanchor{#2}{south}}% \pgf@xa is a length defined by PGF for temporary storage. No need to create a new temporary length.
\addtolength{#1}{-\pgf@xa}%
}
\makeatother
\newlength{\myheight}
\begin{document}
\tikzstyle{block} = [rectangle, draw, minimum height=1cm, minimum width=1cm]
\tikzstyle{table} = [rectangle, draw, minimum width=5cm, minimum height=0.5cm, fill=gray!50]
\tikzstyle{b1} = [fill=orange!50]
\tikzstyle{b2} = [fill=green!50]
\tikzstyle{b3} = [fill=cyan!50]
\tikzstyle{b4} = [fill=red!50]
\lipsum[1]
\begin{tikzpicture}
\node[anchor=south west,inner xsep=15pt,inner ysep=5pt,draw] (listing) at (-7,0) {%
\begin{lstlisting}[language=Prolog,aboveskip=0,belowskip=0,abovecaptionskip=0pt,belowcaptionskip=0pt]
[
block(block1),
block(block2),
block(block3),
block(block4),
on(table,block2),
on(table,block3),
on(block2,block1),
on(table,block4),
clear(block1),
clear(block3),
clear(block4),
handempty
]
\end{lstlisting}};
\getheightofnode{\myheight}{listing}
\begin{scope}[shift={($ - 0.5*(0,\myheight) + (0,2.5)$)}]
% The second term's y coordinate is 2.5 = height of the boxes + table
\draw (-1.5,0) rectangle ($(4.5,0) + (0,\myheight) $);
\begin{scope}[shift={($0.5*(0,\myheight) - (0,0.25)$)}] % Why do I need this 0.25?
\node[block, b3] at (1.5,0) {3};
\node[block, b2] at (0,0) {2};
\node[block, b1] at (0,1) {1};
\node[block, b4] at (3,0) {4};
\node[table] at (1.5,-0.75) {Table};
\end{scope}
\end{scope}
\end{tikzpicture}
\lipsum[2]
\end{document}
我从 listings 包中注释掉一些选项,让 tikz 进行框架等操作。结果在高度方面是正确的,但是我仍然不完全满意,因为这仍然需要用户输入框的高度(但我不打算将其自动化),并且有 0.2 这个“神奇”值是块的垂直对齐所必需的。我想我的计算在某些地方是错误的。
将这个 0.2 魔法值替换为 0.4,它不再对齐,但在我看来它更加平衡:
如果右侧图片较高,则采用 (半脏) 解决方案
对齐可以从那里进行或多或少的调整。但在这种情况下语法有点不同
\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{multicol}
\usepackage{listings}
\usepackage{lipsum}
\lstset{ %
language=Prolog, % the language of the code
basicstyle=\scriptsize\ttfamily, % the size of the fonts that are used for the code
numbers=left, % where to put the line-numbers
numberstyle=\tiny\color{gray}, % the style that is used for the line-numbers
stepnumber=1, % the step between two line-numbers. If it's 1, each line will be numbered
numbersep=5pt, % how far the line-numbers are from the code
% backgroundcolor=\color{white}, % choose the background color. You must add \usepackage{color}
showspaces=false, % show spaces adding particular underscores
showstringspaces=false, % underline spaces within strings
showtabs=false, % show tabs within strings adding particular underscores
% frame=single, % adds a frame around the code
% rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text
tabsize=4, % sets default tabsize to 4 spaces
captionpos=b, %
breaklines=true, % sets automatic line breaking
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
% title=\lstname, % show the filename of files included with \lstinputlisting;
% also try caption instead of title
keywordstyle=\color{blue}, % keyword style
commentstyle=\color{dkgreen}, % comment style
stringstyle=\color{mauve}, % string literal style
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
}
\makeatletter
\newcommand\getheightofnode[2]{%
\pgfextracty{#1}{\pgfpointanchor{#2}{north}}%
\pgfextracty{\pgf@xa}{\pgfpointanchor{#2}{south}}% \pgf@xa is a length defined by PGF for temporary storage. No need to create a new temporary length.
\addtolength{#1}{-\pgf@xa}%
}
\makeatother
\newlength{\myheight}
\begin{document}
\tikzstyle{block} = [rectangle, draw, minimum height=1cm, minimum width=1cm]
\tikzstyle{table} = [rectangle, draw, minimum width=5cm, minimum height=0.5cm, fill=gray!50]
\tikzstyle{b1} = [fill=orange!50]
\tikzstyle{b2} = [fill=green!50]
\tikzstyle{b3} = [fill=cyan!50]
\tikzstyle{b4} = [fill=red!50]
\begin{tikzpicture}
\node[anchor=south west,inner xsep=15pt,inner ysep=5pt] (listing) at (-7,0) {%
\begin{lstlisting}[language=Prolog,aboveskip=0,belowskip=0,abovecaptionskip=0pt,belowcaptionskip=0pt]
[
block(block1),
block(block2),
block(block3),
block(block4),
on(table,block2),
on(table,block3),
on(block2,block1),
on(table,block4),
clear(block1),
clear(block3),
clear(block4),
handempty
]
\end{lstlisting}};
\def\myheight{7}
\begin{scope}[shift={($ - 0.5*(0,\myheight) + (0,2.5)$)}]
% The second term is 2.5 (height of the boxes + table)
\draw (-1.5,0) rectangle ($(4.5,0) + (0,\myheight) $);
\begin{scope}[shift={($(0,1.5)$)}] % Why do I need this 0.25?
\node[block, b3] at (1.5,0) {3};
\node[block, b2] at (0,0) {2};
\node[block, b1] at (0,1) {1};
\node[block, b4] at (3,0) {4};
\node[block, b2] at (0,2) {5};
\node[block, b3] at (0,3) {6};
\node[block, b4] at (0,4) {7};
\node[table] at (1.5,-0.75) {Table};
\end{scope}
\end{scope}
\draw ($(listing) - 0.5*(5,\myheight)$) rectangle ($(listing) + 0.5*(5,\myheight)$);
\end{tikzpicture}
\end{document}