1

I tried to typeset a table like figure using TikZ matrix library and wanted to add stripes to it. However I also wanted to style the last column and row in another color. Regardless of order and combinations of .append style .prefix style and normal .style I have not been able to overwrite the stripe color from every odd row.

Here is a minimal working example:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}
\begin{tikzpicture}
\matrix [
  matrix of nodes,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={draw, anchor=center, minimum size=.75cm},
  every odd row/.style={nodes={fill=yellow!10}},
  column 6/.style={column sep=5pt},
  column 7/.style={nodes={fill=green!10, font=\bfseries}},
  row 5/.style={row sep=5pt},
  row 6/.style={nodes={fill=green!10, font=\bfseries}}
] {
  1 & 1 & 1 & 0 & 1 & 0 & 0 \\
  0 & 0 & 1 & 0 & 1 & 1 & 1 \\
  0 & 1 & 0 & 1 & 1 & 0 & 1 \\
  0 & 1 & 1 & 0 & 0 & 0 & 0 \\
  1 & 0 & 1 & 1 & 0 & 1 & 0 \\
  0 & 1 & 0 & 0 & 1 & 0 & \\
};
\end{tikzpicture}
\end{document}

And an image of what it currently looks like:
image showing the stripes overwriting the background color of the last column

1
  • With regards to github.com/pgf-tikz/pgf/issues/867, I added a style that changes the order when invoked. Please use with care if you use it. Perhaps a feature request to implement something along these lines will be successful.
    – user194703
    Commented May 28, 2020 at 20:57

1 Answer 1

0

The "overwriting" is a consequence of the following excerpt of tikz.code.tex:

\def\tikz@common@matrix@code{%
  \let\tikz@options=\pgfutil@empty%
  \let\tikz@mode=\pgfutil@empty%
  \tikzset{every cell/.try={\the\pgfmatrixcurrentrow}{\the\pgfmatrixcurrentcolumn}}%
  \tikzset{column \the\pgfmatrixcurrentcolumn/.try}%
  \ifodd\pgfmatrixcurrentcolumn%
    \tikzset{every odd column/.try}%
  \else%
    \tikzset{every even column/.try}%
  \fi%
  \tikzset{row \the\pgfmatrixcurrentrow/.try}%
  \ifodd\pgfmatrixcurrentrow%
    \tikzset{every odd row/.try}%
  \else%
    \tikzset{every even row/.try}%
  \fi%
  \tikzset{row \the\pgfmatrixcurrentrow\space column \the\pgfmatrixcurrentcolumn/.try}%
  \tikz@options%
}%

As you can see, it goes through the column and row options in a certain order. In particular, it looks at the rows after the columns. So, as you say, the styles for the column will in general be overwritten by the styles for rows.

However, this problem is far from being unsolvable. Rather, I find it in most situations most convenient to directly work with the the counts \pgfmatrixcurrentcolumn and \pgfmatrixcurrentrow. This allows one to implement whatever rule you like. In your case, your goal can be achieved with some code that computes an integer labeling the cases,

\pgfmathtruncatemacro{\itest}{ifthenelse(%
    \pgfmatrixcurrentcolumn==7||\pgfmatrixcurrentrow==6,0,%
     ifthenelse(isodd(\pgfmatrixcurrentrow),1,2))}

and then using \ifcase,

\ifcase\itest
\tikzset{fill=green!10, font=\bfseries}%
\or
\tikzset{fill=yellow!10}%
\or
\fi

This method is very powerful as you can implement more general conditions like a modulo condition, or more general functions of the row and column indices.

Here is the full code.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{matrix}
\tikzset{cond/.code={%
\pgfmathtruncatemacro{\itest}{ifthenelse(%
    \pgfmatrixcurrentcolumn==7||\pgfmatrixcurrentrow==6,0,%
     ifthenelse(isodd(\pgfmatrixcurrentrow),1,2))}
%\typeout{\the\pgfmatrixcurrentcolumn,\pgfmatrixcurrentrow->\itest}  
\ifcase\itest
\tikzset{fill=green!10, font=\bfseries}%
\or
\tikzset{fill=yellow!10}%
\or
\fi
}}
\begin{document}
\begin{tikzpicture}
\matrix [
  matrix of nodes,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={draw, anchor=center, minimum size=.75cm,cond},
  column 6/.style={column sep=5pt},
  row 5/.style={row sep=5pt},
] {
  1 & 1 & 1 & 0 & 1 & 0 & 0 \\
  0 & 0 & 1 & 0 & 1 & 1 & 1 \\
  0 & 1 & 0 & 1 & 1 & 0 & 1 \\
  0 & 1 & 1 & 0 & 0 & 0 & 0 \\
  1 & 0 & 1 & 1 & 0 & 1 & 0 \\
  0 & 1 & 0 & 0 & 1 & 0 & \\
};
\end{tikzpicture}
\end{document}

enter image description here

ADDENDUM: With regards to this issue, you could also install some reordering of the styles.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{matrix}
\makeatletter
\tikzset{reorder matrix styles/.style={execute at begin matrix={
\def\tikz@common@matrix@code{%
  \let\tikz@options=\pgfutil@empty%
  \let\tikz@mode=\pgfutil@empty%
  \tikzset{every cell/.try={\the\pgfmatrixcurrentrow}{\the\pgfmatrixcurrentcolumn}}%
  \ifodd\pgfmatrixcurrentcolumn%
    \tikzset{every odd column/.try}%
  \else%
    \tikzset{every even column/.try}%
  \fi%
  \ifodd\pgfmatrixcurrentrow%
    \tikzset{every odd row/.try}%
  \else%
    \tikzset{every even row/.try}%
  \fi%
  \tikzset{column \the\pgfmatrixcurrentcolumn/.try}%
  \tikzset{row \the\pgfmatrixcurrentrow/.try}%
  \tikzset{row \the\pgfmatrixcurrentrow\space column \the\pgfmatrixcurrentcolumn/.try}%
  \tikz@options%
}%
}}}
\makeatother
\begin{document}
\begin{tikzpicture}[reorder matrix styles]
\matrix [
  matrix of nodes,
  row sep=-\pgflinewidth,
  column sep=-\pgflinewidth,
  nodes={draw, anchor=center, minimum size=.75cm},
  every odd row/.style={nodes={fill=yellow!10}},
  column 6/.style={column sep=5pt},
  column 7/.style={nodes={fill=green!10, font=\bfseries}},
  row 5/.style={row sep=5pt},
  row 6/.style={nodes={fill=green!10, font=\bfseries}}
] {
  1 & 1 & 1 & 0 & 1 & 0 & 0 \\
  0 & 0 & 1 & 0 & 1 & 1 & 1 \\
  0 & 1 & 0 & 1 & 1 & 0 & 1 \\
  0 & 1 & 1 & 0 & 0 & 0 & 0 \\
  1 & 0 & 1 & 1 & 0 & 1 & 0 \\
  0 & 1 & 0 & 0 & 1 & 0 & \\
};
\end{tikzpicture}
\end{document}

This produces the same output as above. Note, however, that this is a bit of a hack, and one can think of scenarios in which this crashes.

12
  • I've implemented something to configure the order: github.com/hmenke/pgf/commit/… Commented May 28, 2020 at 22:48
  • 1
    @HenriMenke I prefer the first method of the answer. It allows one to implement mod 3 conditions, say, to play with beamer overlays (see here), automatically label matrix entries, and much much more. I personally would find it much more useful if one added a wrapper for those to the matrix library. (There are many more additions to the matrix library possible, such as an alignment. One can use eqparbox but I feel this could be part of the library.)
    – user194703
    Commented May 28, 2020 at 23:00
  • 1
    @HenriMenke The main headache I have with the reordering is that you stack styles. In the case at hand, this is fine, you overwrite fill=yellow!10 by fill=green!10. However, if you had something like fill=yellow!10,text width=3em and then a style for column 7 like fill=green!10 you'd keep the text width. This may or may not be what the user wants, but with just reordering it is IMHO much harder to get what you like in general. That's why I do like \ifcase, which does not stack styles.
    – user194703
    Commented May 28, 2020 at 23:05
  • In the new key matrix/inner style order you can also install your own styles and even leave out existing ones, which will then not be considered at all. Commented May 28, 2020 at 23:52
  • @HenriMenke Yes, these styles are certainly nice. However, I think one could add a lot of value to the matrix library by just adding a bit more information to the manual. (I'll be happy to make a concrete proposal.) And even more value by adding some very simple styles, which could e.g. allow the user to add grid lines, and/or left- and right-align the cells.
    – user194703
    Commented May 29, 2020 at 2:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .