14

In the TikZ manual we have the example below that shows how to apply an style to an entry of the matrix. It is also easy to apply it for an entire row and an entire column. My question is how can we achieve the same for several entries? Is there a simple way to specify a style, say for example, rows 1 & 3 and columns 1 & 2?

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\begin{tikzpicture}[row 2 column 3/.style=red]
\matrix [matrix of nodes]
{
 8 & 1 & 6 \\
 3 & 5 & 7 \\
 4 & 9 & 2 \\
  };
 \end{tikzpicture}
 \end{document}
Sergio Parreiras
  • 1,786
  • 1
  • 15
  • 32

5 Answers5

22

You can use the /.list feature John Kormylo mentioned in his answer to repeat a style for different inputs.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\tikzset{myset/.style={row 2 column #1/.style={nodes={text=red}}}}
\begin{tikzpicture}[myset/.list={1,3,5}]
\matrix [matrix of nodes]
{
 8 & 1 & 6 & 8 & 1 & 6 \\
 3 & 5 & 7 & 3 & 5 & 7 \\
 4 & 9 & 2 & 4 & 9 & 2 \\
  };
\end{tikzpicture}
\end{document}

enter image description here

percusse
  • 157,807
  • list will be very useful for other projects, thanks! By any chance, besides the manual do you have any suggestions on references for TikZ programming? – Sergio Parreiras May 07 '14 at 08:32
  • 1
    @SergioParreiras Manual is very very good. I would say answer questions here :P It gives you a lot of practice and gives a chance to see others do their black magic. – percusse May 07 '14 at 08:33
9

More a long comment than a real answer... Based on percusse's answer, this style allows to specify both row and column.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\tikzset{myset/.style args = {(#1,#2)}{%
    row #1 column #2/.style={nodes={text=red}}}}
\begin{tikzpicture}[myset/.list={(2,1),(3,3),(1,5)}]
\matrix [matrix of nodes]
{
 8 & 1 & 6 & 8 & 1 & 6 \\
 3 & 5 & 7 & 3 & 5 & 7 \\
 4 & 9 & 2 & 4 & 9 & 2 \\
  };
\end{tikzpicture}
\end{document}

enter image description here

cjorssen
  • 10,032
  • 4
  • 36
  • 126
7

This can be done via \foreach indeed, but since the keys set with \pgfkeys are not global, their assignment are lost when the loop is exited. Unless you mess with \globaldef, as in the following example:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}

\newcommand{\rows}[2]{% #1 = rows, #2 = style
\foreach \r in {#1} {%
  \globaldefs=1\relax
  \tikzset{row \r/.style={#2}}
}%
}

\newcommand{\cols}[2]{% #1 = columns, #2 = style
\foreach \r in {#1} {%
  \globaldefs=1\relax
  \tikzset{column \r/.style={#2}}
}%
}

\begin{tikzpicture}
\cols{1,3}{blue}
\rows{1,3}{red}
\matrix [matrix of nodes]
{
 8 & 1 & 6 \\
 3 & 5 & 7 \\
 4 & 9 & 2 \\
  };
 \end{tikzpicture}
\end{document}

Result

JLDiaz
  • 55,732
2

Interestingly, you cannot do this using \foreach. I understand this is because \foreach is actually implemented using \pgfkeys using the /.list={...} feature, but I'm a bit fuzzy on the details.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}

\newcommand{\row}[2]{% #1 = row, #2 = style
\tikzset{row #1/.style={#2}}}

\newcommand{\col}[2]{% #1 = column, #2 = style
\tikzset{column #1/.style={#2}}}

\begin{document}
\begin{tikzpicture}
\row{1}{red}
\row{3}{red}
\col{1}{blue}
\col{3}{blue}
\matrix [matrix of nodes]
{
 8 & 1 & 6 \\
 3 & 5 & 7 \\
 4 & 9 & 2 \\
  };
 \end{tikzpicture}
 \end{document}
John Kormylo
  • 79,712
  • 3
  • 50
  • 120
2

I reopen this old questions because, from percusse's and cjorssen's answers, I managed to assign style to a block of cells only specifying its (top,left to bottom,right) coordinates. I share here my solution, hoping it will help someone else.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
\tikzset{myblocks/.style args = {(#1,#2 to #3,#4)}{
            blockrows/.style={
                block/.style={
                    row ##1 column ####1/.style={nodes={text=red}}
                },
                block/.list={#2,...,#4}
            },
            blockrows/.list={#1,...,#3}
        }
}
\begin{tikzpicture}[myblocks/.list={(1,1 to 2,2),(1,4 to 3,5)}]
\matrix [matrix of nodes]
{
 8 & 1 & 6 & 8 & 1 & 6 \\
 3 & 5 & 7 & 3 & 5 & 7 \\
 4 & 9 & 2 & 4 & 9 & 2 \\
  };
\end{tikzpicture}
\end{document}

enter image description here

JPG
  • 2,019