|
| 1 | +% !TEX encoding = UTF8 |
| 2 | +% !TEX spellcheck = ru_RU |
| 3 | +% !TEX root = ../seminars.tex |
| 4 | + |
| 5 | +%%=============================================== |
| 6 | +\chapter{Графические пользовательские интерфейсы} |
| 7 | +%%=============================================== |
| 8 | + |
| 9 | +%%==================================== |
| 10 | +\section{Окно с кнопкой \texttt{Quit}} |
| 11 | +%%==================================== |
| 12 | +Выполним упражнение~1 из~\textbookref{главы~16} учебника. Для~этого пронаследуем \code{My\_window} от~класса \code{Simple\_window} из~библиотеки \code{Graph\_lib}. Затем добавим по~аналогии с~кнопкой \code{Next} кнопку \code{Quit}, как показано на~рисунке~\ref{fig:mywindow}. |
| 13 | + |
| 14 | +\begin{figure}[ht] |
| 15 | + {\centering |
| 16 | + \includegraphics[width=0.6\textwidth]{images/my_window.png} |
| 17 | + |
| 18 | + } |
| 19 | + \caption{Простое окно \code{My\_window} с кнопкой \code{Quit}} |
| 20 | + \label{fig:mywindow} |
| 21 | +\end{figure} |
| 22 | + |
| 23 | +Из~документации к~библиотеке \name{FLTK} известно, что если все окна становятся скрытыми, то цикл обработки событий прекращает работу. То есть для~реализации функции \code{quit()} можно воспользоваться методом \code{hide()}. |
| 24 | + |
| 25 | +\cppfile[firstline=11, lastline=30]{projects/ch16/chessboard/board.h} |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +%%======================= |
| 30 | +\section{Шахматная доска} |
| 31 | +%%======================= |
| 32 | +Покажем, как можно создать клеточное поле и взаимодействовать с~ним на~примере упражнения~2 из~\textbookref{главы~16}. Эти идеи можно использовать для~создания практически любой игры с~клеточным полем: шашки, шахматы, сапёр, морской бой и другие. |
| 33 | + |
| 34 | +\begin{figure}[ht] |
| 35 | + {\centering |
| 36 | + \includegraphics[width=0.5\textwidth]{images/chessboard.png} |
| 37 | + |
| 38 | + } |
| 39 | + \caption{Окно с шахматной доской \(4\times 4\)} |
| 40 | + \label{fig:chessboard} |
| 41 | +\end{figure} |
| 42 | + |
| 43 | +Размеры клеток и, соответственно, окна зафиксируем. Впоследствии, такое поведение можно изменить. Клетки представим квадратными кнопками и будем хранить их в~\code{Vector\_ref}. Метки строк и столбцов доски можно нарисовать при~помощи объектов \code{Marks}. Окно, согласно заданию, пронаследуем от~\code{My\_window} из~предыдущего упражнения. |
| 44 | + |
| 45 | +\cppfile[firstline=32, lastline=60]{projects/ch16/chessboard/board.h} |
| 46 | + |
| 47 | +Учитывая последующую доработку, код удобнее распределить между~несколькими файлами, как это предлагается в~таблице~\ref{tab:chessboard}. |
| 48 | +\begin{table}[ht] |
| 49 | + {\centering\begin{tabular}{ll} |
| 50 | + \toprule |
| 51 | + \code{board.h} & класс \code{Chessboard} для~шахматной доски, а также \code{My\_window} \\ |
| 52 | + \code{board.cpp} & \\[0.5em] |
| 53 | + |
| 54 | + \code{cell.h} & класс \code{Cell} для~шахматной клетки \\ |
| 55 | + \code{cell.cpp} & \\[0.5em] |
| 56 | + |
| 57 | + \code{main.cpp} & \\ |
| 58 | + \bottomrule |
| 59 | + \end{tabular} |
| 60 | + |
| 61 | + } |
| 62 | + \medskip |
| 63 | + \caption{Распределение кода <<шахматной доски>> между файлами} |
| 64 | + \label{tab:chessboard} |
| 65 | +\end{table} |
| 66 | + |
| 67 | +Конструктор задаёт размеры окна, создаёт клетки, располагая их в~соответствующих позициях, и рисует метки строк и столбцов доски. Зафиксировать размеры окна, чтобы пользователь не~смог его растягивать или сжимать, позволяет функция \code{size\_range()} "--- метод окна \name{FLTK}. |
| 68 | + |
| 69 | +\cppfile[firstline=35, lastline=66]{projects/ch16/chessboard/board.cpp} |
| 70 | + |
| 71 | +Цвет клетки (или тип) вычисляется на~основе номеров строки и столбца, определяющих её положение на~доске. Клетка в~левом нижнем углу имеет чёрный цвет. Обратим внимание, что клетки добавлялись в~линейный массив по~порядку в~соответствии с~направлением снизу вверх и слева направо, как принято в~шахматах. |
| 72 | + |
| 73 | +\cppfile[firstline=7, lastline=13]{projects/ch16/chessboard/board.cpp} |
| 74 | + |
| 75 | +Метки \code{Marks} допускают всего лишь один символ, поэтому мы используем ограничение \code{N\_max} для~максимального размера доски. Если потребуется вывести двузначные номера клеток, придётся разработать новый класс или добавить метки при~помощи неименованных объектов \code{Text}. А пока используем простую реализацию и пару вспомогательных функций: |
| 76 | + |
| 77 | +\cppfile[firstline=15, lastline=33]{projects/ch16/chessboard/board.cpp} |
| 78 | + |
| 79 | +\noindent Таким образом, получается вид, как на~рисунке~\ref{fig:chessboard}. |
| 80 | + |
| 81 | +В~функцию-обработчик нажатия на~кнопку-клетку добавим простую логику самой шахматной доски. Мы можем выделить любую клетку; переместить выделение, выбрав другую клетку; или снять выделение, нажав на~выделенную клетку повторно: |
| 82 | + |
| 83 | +\cppfile[firstline=68, lastline=90]{projects/ch16/chessboard/board.cpp} |
| 84 | + |
| 85 | +\noindent\textbf{NB!} Если в~отображении виджета что-то изменилось, то, скорее всего, потребуется перерисовать его вручную. Для~этого используйте \code{Fl::redraw()}. |
| 86 | + |
| 87 | +Теперь посмотрим реализацию клетки шахматной доски: |
| 88 | + |
| 89 | +\cppfile[firstline=8, lastline=32]{projects/ch16/chessboard/cell.h} |
| 90 | + |
| 91 | +Реализация методов проста и не~требует дополнительных пояснений, кроме того, что \code{pw} "--- это защищённый член класса \code{Graph\_lib::Widget}, связанный с~реальным графическим виджетом из~\name{FLTK}. |
| 92 | +\enlargethispage{0.5\baselineskip} |
| 93 | + |
| 94 | +\cppfile[firstline=5, lastline=32]{projects/ch16/chessboard/cell.cpp} |
| 95 | + |
| 96 | +Теперь настало время собрать и запустить программу целиком. Для~этого добавьте необходимые заголовки и функцию \code{main()}, просто создающую окно \code{Checkerboard} и запускающую цикл обработки событий: |
| 97 | + |
| 98 | +\cppfile[firstline=17, lastline=18]{projects/ch16/chessboard/main.cpp} |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | +\clearpage |
| 103 | +%%=============================== |
| 104 | +\section{Добавление фигур. Шашки} |
| 105 | +%%=============================== |
| 106 | + |
| 107 | +\begin{figure}[ht] |
| 108 | + {\centering |
| 109 | + \includegraphics[width=0.5\textwidth]{images/checkers.png} |
| 110 | + |
| 111 | + } |
| 112 | + \caption{Шахматная доска \(4\times 4\) с~шашками} |
| 113 | + \label{fig:checkers} |
| 114 | +\end{figure} |
| 115 | + |
| 116 | +\todo{Описание будет добавлено позже.} |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | +%%================ |
| 121 | +\WhatToReadSection |
| 122 | +%%================ |
| 123 | +\textcite{Stroustrup:2016:ru}: \textbf{глава~17} |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | +%%=============== |
| 128 | +\ExercisesSection |
| 129 | +%%=============== |
| 130 | +\begin{exercise} |
| 131 | +\item Выполните упражнения из~\textbookref{главы~16} учебника. |
| 132 | + |
| 133 | +\end{exercise} |
0 commit comments