к оглавлению   к 4GL - визуальному программированию

Графика в VB .NET

Отображение графических объектов в Microsoft Windows производится посредством интерфейса графических устройств (graphics device interface, GDI). Он представлйет собой аппаратно-независимую модель вывода графики, которая обрабатывает вызовы графических функций из Windows-приложений и передает их соответствующему драйверу устройства. Последний выполняет специфические для устройства операции, которые и осуществляют вывод. Работая как буфер между приложениями и устройствами вывода, GDI представляется приложению как нечто независящее от самого устройства, но учитывающее формат устройства при выводе.

Разработчики приложений используют функциональные средства GDI для отображения и отрисовки элементов управления, фигур и текста, а также для создания и применения перьев, кистей и шрифтов. Объект Graphics из WFC вместе с другими объектами WFC — Pen, Font и Brush — инкапсулирует эти средства в качестве объектов Java. В среде WFC графический вывод производится через объект Graphics. После создания или получения объекта Graphics Вы связываете с ним другие графические объекты — шрифты, перья и кисти — и, используя присущие им методы рисования, строите изображение на дисплее. Например, для изображения произвольных линий используется метод set-Pen объекта Graphics для установки пера, которое применяется объектом для рисования, а затем используется метод drawLine этого же объекта для проведения линий. Подобные связи объектов можно менять сколь угодно часто.

Создание объекта Graphics

WFC предоставляет несколько способов создания объекта Graphics. Явное создание объекта. Объект Graphics создается явно путем вызова метода createGraphics для любого объекта, который расширяет класс Control.

Неявное создание объекта. Объекты Bitmap и Metafile поддерживают неявное создание объекта Graphics при помощи метода getGraphics.

Явное создание объекта Graphics

Все классы, расширяющие класс Control, поддерживают метод createGraphics, который можно использовать для создания экземпляра объекта Graphics. Следующий фрагмент кода демонстрирует, как вызвать этот метод изнутри класса, производного от Form:

Graphics g = this.createGraphics();

Второй подход для явного создания объекта Graphics предполагает использование описателя контекста устройства Win32 (HDC). Вообще говоря, единственным случаем создания объекта Graphics этим способом является вызов метода Win32, который возвращает HDC. Если Вам просто нужны графические возможности, которые не поддерживаются явно в объекте Graphics, примените метод объекта getHandle для получения описателя контекста устройства Win32 и затем передайте этот описатель в соответствующий метод Win32. Если Вы создаете объект Graphics на основе ранее существовавшего описателя, то объект Graphics не становится владельцем описателя, и после использования объекта Вы ответственны за освобождение описателя с помощью соответствующей функции Win32. Если Ви применяете метод getHandle объекта Graphics для получения базисного описателя объекта, то объект остается владельцем этого описателя, и Вы не должны пытаться освободить его.

Дополнительная информация об описателях Win32 и объекте Graphics приведена далее в этой главе в разделе «Выполнение операций с описателями».

Неявное создание объекта Graphics

Объекты Bitmap и Metafile поддерживают неявное создание объекта Graphics при помощи их метода getGraphics. В следующем фрагменте кода метод getGraphics объекта Bitmap используется для создания объекта Graphics, который применяют для отрисовки растрового изображения:

Bitmap bmp = new Bitmap(«

c:\\MyImage. bmp»);

Graphics gr = bmp. getGraphics();

При первым вызове getGraphics объект создает новый экземпляр объекта Graphics и возвращает его. Последующие вызовы getGraphics для того же объекта приводят к возврату объекта, созданного при первом вызове.

Кроме того, когда методы рисования вызываются посредством объекта Graphics, созданного методом getGraphics какого-то объекта, они применяются к объекту, посредством которого они были созданы. Например, XY-координаты (0,0), заданные ранее в обращении к drawText, измеряются относительно объекта «растр», а не относительно элемента управления, на котором находитется» растр.

Получение объекта Graphics

Внутри события отрисовки (paint event) формы или элемента управления можно получить и использовать экземпляр объекта Graphics. Обработчик этого события получает в качестве параметра объект Paint-Event, который имеет открытый член graphics, являющийся экземпляр объекта Graphics. Его вызывают следующим образом:

protected void onPaint(PaintEvent е)

{

е.graphics.drawString(«Hello, World», new Point(10, 10));

}

Подробности о создании объекта Graphics вне события отрисовки см. в предыдущих разделах «Явное создание объекта Graphics» и «Неявное создание объекта Graphics».

Область видимости объекта Graphics

Объект Graphics имеет область видимости метода (method scope). Это означает, что при возврате из метода, в котором использовался объект Graphics, автоматически вызывается метод dispose этого объекта, освобождая все ресурсы, выделенные объекту. После вызова dispose попытки использования объекта сгенерируют исключительную ситуацию времени выполнения.

Если Вы объявили экземпляр объекта Graphics на уровне класса, то необходимо использовать метод createGraphics объекта Form для инициализации такого объекта в каждом методе, который его использует:

Public class Forml extends Form{

Graphics g = new Graphics();

Private void Form1_resize(0bject sender, Event e){

// Инициализировать экземпляр объекта,

g = this.createGraphics();

// dispose вызывается автоматически...

}

private void Form1_click(0bject sender, Event e){

// Инициализировать экземпляр объекта, g = this.createGraphics();

// Метод dispose вызывается автоматически...

}

}

Хотя метод dispose вызывается автоматически, лучше вызывать его явно в конце процедур, использующих объект Graphics. Это особенно важно на платформе Windows, потому что имеется системное ограничение на количество выделяемых контекстов устройств.

Управление ограничивающим прямоугольником

Область окна, в которой можно производить отрисовку, называется клиентской областью (client area) окна. Внутри этой области ограничивающий прямоугольник (bounding rectangle) определяет невидимую прямоугольную область, где объект Graphics производит отрисовку и которая может включать в себя всю клиентскую область окна. Когда окно теряет и затем снова получает фокус ввода, часть ограничивающего прямоугольника, ранее покрытая другим объектом, не перерисовывает автоматически элементы, которые были на ней. Чтобы гарантировать правильность отображения, нужно управлять перерисовкой формы или элемента управления. Обработчик события отрисовки является тем самым местом в коде класса Form, где обычно и размещается такое управление. Внутри обработчика восстанавливается правильное состояние ограничивающего прямоугольника. В следующем примере на уровне класса создается объект Bitmap, а затем он использует обработчик события отрисовки для изменения вида объекта Bitmap. Каждый раз, когда клиентская область формы становится недействительной, Windows вызывает этот обработчик и изображение на форме перерисовывается:

Bitmap bmp = new Bitmap(«c:\\MyImage.bmp»);

protected void onPaint(PaintEvent e){

e.graphics.drawlmage(bmp, new Point(0, 0)); }

Когда форма отображается в первый раз, а также при каждом получении фокуса, обработчик события отрисовки вызывается автоматически. Однако если форма поддерживает изменение размеров, то смена размеров формы не вызывает автоматически перерисовку. Напротив, нужно добавить в класс, производный от Form, обработчик события изменения размеров и из этого обработчика вызывать метод invalidate объекта. Обращение к этому методу запускает обработчик события отрисовки формы:

protected void onResize(Event e)

{

this. invalidate();

}

Выполнение операций с описателями

Описатель (handle) — это уникальный номер, по которому некий элемент операционной системы идентифицируется в компьютере. Например, каждое окно на рабочем столе имеет уникальный описатель, позволяющий компьютеру отличить его от других окон. Каждые контекст устройства, перо, кисть и шрифт также имеют уникальный описатель. Чтобы сохранить оптимальную совместимость с Win32 API, объекты Graphics, Pen, Brush и Font поддерживают операции с описателями. Например, если Вы используете \Ут32-функцию CreatePen для создания пера, эта функция вернет описатель. Затем Вы вправе передать этот описатель в конструктор объекта Реп, и объект будет создан на основе характеристик пера Win32.

Даже если Вы не создаете объект Pen, Brush или Font на основе имеющегося описателя, Вы можете получить описатель, на котором основан любой из этих объектов. Каждый из этих объектов поддерживает методы copyHandle и getHandle; продублировав или получив описатель объекта при их помощи, Вы вправе передать описатель в любую функцию Win32, которая примет его в качестве параметра.

Далее следует несколько важных правил, которые надо иметь в виду при выполнении действий с описателями и объектами Graphics. • Если создается объект на основе описателя, полученного при помощи метода Win32, то объект не владеет этим описателем. Например, если используется метод GetDC из Win32 для получения описателя контекста устройства (HDC) для формы, то затем следует создать объект Graphics на основе этого HDC, чтобы владеть описателем. Это означает, что, когда вызывается метод dispose объекта Graphics, описатель не освобождается. Вместо этого придется использовать соответствующую процедуру Win32 для уничтожения описателя. Ниже проиллюстрировано, как управлять описателем. В этом примере используется функция GetDC из Win32 для получения описателя из контекста устройства для формы, затем на основе этого описателя создается объект Graphics. После применения объекта Graphics для отрисовки линии на форме вызывается метод dispose объекта Graphics для уничтожения объекта Graphics и вызывается процедура ReleaseDC из Win32 для освобождения описателя контекста устройства, выделенного вызовом GetDC:

// импорт пакета the com.ms.wfc.Win32.Windows, import com.ns.wfс.Win32.Windows;

int hDC = Windows.GetDC(this.getHandle());

Graphics g = new Grapnics(hDC);

g.drawLine(new Point(0.0), new Point(100, 0));

g.dispose();

Windows.ReleaseDC(hDC);

Заметьте, здесь говорится об описателе контекста устройства, но используемые принципы применимы и к перьям, кистям, шрифтам и растрам.

Системы координат объекта Graphics

Множество методов объекта Graphics зависит от числовых координат. Последние задаются в объекте Rectangle, определяющем область выполнения операции, или в объекте Point, который указывает координаты х (горизонтальную) и у (вертикальную) места выполнения операции. Система координат (coordinate system) определяет, как координаты, заданные на объекте, отображаются на дисплей или на устройство. Предположим, к примеру, что Вы вызвали метод drawString объекта Graphics для вывода текста в координатах 100, 100:

Graphics g = this.createGraphics();

g.drawString(«Hello, WFC»

, new Point(100, 100));

Объект Point здесь определяет координаты х и у места, где будет выведена строка. Однако действительный результат операции зависит от системы координат, с которой связан объект Graphics. Системы координат, с которыми может быть связан объект Graphics, определены в классе CoordinateSystem. По умолчанию системой координат для объекта Graphics является CoordinateSystem.TEXT, что означает, что при увеличении значений х и у в объекте Point текст (или изображение или элемент управления) смещается горизонтально вправо и вертикально вниз.

Чтобы привязать систему координат к объекту Graphics, используйте метод setCoordinateSystem:

Graphics gr = this.createGraphics();

gr.setCoordinateSystem(CoordinateSysten.ANISOTROPIC);

В таблице перечислены системы координат, которые можно связывать с объектом Graphics, и описаны направления вывода при увеличении значений по осям х и у в объекте Point.

Система координат

Направление х

Направление у

CoordinateSystem.TEXT

Вправо

Вниз

CoordinateSystem.LOMETRIC

Вправо

Вверх

CoordinateSystem.HIMETRIC

Вправо

Вверх

CoordinateSystem.LOENGLISH

Вправо

Вверх

CoordinateSystem.HIENGLISH

Вправо

Вверх

CoordinateSystem.TWIPS

Вправо

Вверх

CoordinateSystem.ISOTRdPIC

Определяется пользователем

Определяется пользователем

CoordinateSystem.ANISOTROPIC

Определяется пользователем

Определяется пользователем

 

Установка начала координат

Начало координат (coordinate origin) определяет место, от которого отсчитываются координаты.

Например, если создается объект Graphics посредством основной формы приложения, системой координат объекта является CoordinateSystem.TEXT и графические координаты отсчитываются от верхнего левого угла формы.

Однако, если Вы работаете с системой координат, задаваемой пользователем, — CoordinateSystem.ISOTROPIC или CoordinateSystem.ANISOTROPIC, — то Вы вправе самостоятельно установить начало координат (и для страницы, и для устройства), используя метод setCoor-dinateOrigin метода Graphics. Предположим, к примеру, что Вы включили следующий код в обработчик события отрисовки:

private void Form1_paint(0bject source, PaintEvent e)

{

// Задать систему координат.

e.graphics.setCoordinate

System(CoordinateSystem.ANISOTROPIC);

e.graphics.setCoordinateOrigin(new Point(20, 20), new Point(20,20));

e.graphics.setCoordinateScale(new Point(1,1), new Point(1,1));

e.graphics.drawLine(new Point(O.O), new Point(100,100));

}

Этот код задает систему координат CoordinateSystem.ANISOTROPIC и затем - точку отсчета 20,20 для страницы и для устройства.Вызов drawLine, указанный далее и коде, отсчитывается от этой точки. Следовательно, линия закончится в точке с координатами 100,100 от точки отсчета (20,20).

Отображение логических координат на координаты устройства

Windows предоставляет встроенную поддержку для отображения страничных координат на устройство, например принтер или дисплей. Для большинства систем координат, определенных в Windows, система сама выполняет преобразование. Например, если ассоциировать объект Graphics с системой координат CoordinateSystem.HIMETRIC, то каждая логическая единица на объекте будет преобразована в одну тысячную дюйма на устройстве.

Однако, когда используются задаваемые пользователем системы координат ANISOTROPIC и ISOTROPIC, нужно использовать метод setCoordinateSeale, чтобы сообщить системе, как выполнять преобразование,
например:

Graphics g = this.createGraphics();

g.setCoordinateSystem(CoordinateSystem.ANISOTROPIC);

g.setCoordinateSca!e(new Point(1,1), new Point(2,2));

Вызов setCoordinateScale здесь указывает системе на необходимость преобразования логической горизонтальной и вертикальной единицы в две горизонтальные и вертикальные единицы устройства.

Вывод текста

Метод drawString объекта Graphics поддерживает вывод текста на тот элемент управления, к которому относится объект. Этот метод пишет текст в заданную позицию, как показано в следующем примере: Graphics g = this.createGraphicsO; g.drawString(«Hello, World», new Point(0, 0));

Визуальный результат вызова зависит от нескольких факторов, включая текущий цвет текста объекта Graphics, цвет фона, характеристики шрифта и системы координат.

Информацию о том, как установить цвет текста, см. в следующем разделе «Установка цвета текста». Подробнее о связывании шрифтов с объектом Graphics см. в разделе «Использование объекта Font» далее в этой главе. Сведения о системах координат приведены выше в этой главе в разделе «Системы координат объекта Graphics».

Установка цвета текста

Чтобы установить цвет текста и цист фона для текста, вызовите методы setBackColor и setTextColor объекта Graphics перед вызовом drawString:

// Установить белый цвет текста и черный фон.

g.setTextColor(new Color(0, 0, 0));

g.setBackColor(new Color(255, 255, 255));

// Вывести текст...

Метод setBackColor влияет только на фон за текстом. Чтобы задать фон или цвет заполнения других объектов, например многоугольников и линий, используйте соответственно методы setBrush и setPen.

Использование объекта Font

Шрифт (font) — это набор знаков определенного рисунка. Основными элементами шрифта являются гарнитура (typeface), стиль и кегль (размер).

В WFC шрифты Windows инкапсулированы в объекте Font, который можно использовать в комбинации с другими шрифтовыми объектами для определения шрифтов (число их не ограничено), используемых для вывода в объекте Graphics. В таблице перечислены шрифтовые классы, поддерживаемые WFC.

Класс

Описание

FontDescriptor Предоставляет информацию о шрифте, на котором основан объект Font.
FontFamily Определяет группу констант, представляющих семейства шрифтов, к которым может принадлежать шрифт.
FontMetrics Определяет физические характеристики шрифта, отображенного в объект Graphics.
FontPitch Определяет разрядку шрифта.
FontSize Определяет группу констант, представляющих единицы, в которых может быть задан размер шрифта.
FontType Определяет группу констант, представляющих устройства, на которых будет использоваться шрифт.
FontWeight Определяет константы, представляющие различные веса, которые могут быть связаны со шрифтом.

 

Создание объекта Font

Создание объекта Font бывает простым или сложным в зависимости от степени детализации определения шрифта. Следующий фрагмент кода иллюстрирует один из простых подходов к созданию объекта Font: Font font = new Font(«Times New Roman», 26);

Здесь используется конструктор объекта Font, которому требуется только два вида информации: имя шрифта и его размер. При создании

объекта Font можно также задан, семейство шрифта, его тип, вес, ориентацию, а также будет ли он полужирным, курсивным, подчеркнутым или зачеркнутым. Однако изменить атрибуты после создания объекта Font нельзя.

Установка шрифта для объекта Graphics

Объект Graphics поддерживает метод setFont, который связывает шрифт с объектом. После связывания объекта Font с объектом Graphics весь текст, выводимый внутри ограничивающего прямоугольника объекта Graphics, рисуется этим шрифтом.

Следующий код иллюстрирует установку белого фона, черного текста и шрифта Times New Roman размером 26 пунктов для объекта Graphics. Текст выводится в заданную позицию экрана:

Graphics g = this.createGraphics();

g.setFont(new Font(«Times New Roman», 26));

g.setBackColor(new Color(255, 255, 255));

g.setTextColor(new Color(0, 0, 0));

g.drawString(«Hello, World», 0, 0);

Перечисление шрифтов

В некоторых случаях приложения перебирают все доступные шрифты, получая по каждому детальную информацию, чтобы выбрать наиболее подходящий для конкретной операции.

Объект FontDescriptor в WFC — описание шрифта, включающее его имя, высоту, ориентацию и т. д. Для получения детального описания всех доступных в системе шрифтов используйте метод getFontDesc-riptors объекта Graphics. Он возвращает массив объектов FontDescriptor, каждый элемент которого описывает шрифт.

Ниже показано, как использовать метод getFontDescriptors. В этом примере извлекается список имеющихся шрифтов, а затем вставляется единый список имен шрифтов в окно списка: Graphics g = this.createGraphics();

// Создать массив.

FontDescriptor rgFonts[] = g.getFontDescriptors();

for(int i = 0; i < rgFonts.length; i++){

if(listBox1.findString(rgFonts[i].fullName == -1){

listBoxl.addltem(rgFonts[i].fullName); } }

Использование перьев

Перо (реп) — это графическое средство, которое приложения Microsoft Windows используют для отрисовки линий и кривых. Приложения, предназначенные для рисования, позволят Вам использовать перья для проведения «от руки» прямых и кривых линий. В САПР-приложениях перья служат для изображения видимых и скрытых линий, линий сечений, осей симметрии и т. п. В текстовых редакторах и настольных издательствах перья применяются для вывода границ и линеек. В электронных таблицах — для обозначения трендов на графиках и для вывода линейчатых и круговых диаграмм.

Каждое перо имеет три атрибута: стиль, ширину и цвет. Тогда как на ширину и цвет не накладывается никаких ограничений, стиль пера должен поддерживаться операционной системой.

Объект Реп из WFC

Возможности перьев из Win32 инкапсулированы в объектах Реп и Pen-Style из WFC. Следующий фрагмент кода демонстрирует создание объекта Реn:

Реn р = new Pen(PenStyle.DASH);

Константа, передаваемая в конструктор объекта Реп, — это стиль пера (pen style). Семь встроенных в Windows стилей пера представлены константами, определенными в классе PenStyle. Последний — это класс перечисления (enumeration class), что означает, что в нем определен метод (valid), который указывает, является ли заданное значение членом класса PenStyle. В таблице перечислены константы из класса PenStyle.

Константа

Описание

PenStyle.DASH Тире
PenStyle.DOT Точки
PenStyle.DASHDOT Точка и тире
PenStyle.DASHDOTDOT Две точки и тире
PenStyle.INSIDEFRAME Перо рисует линию внутри замкнутых фигур, полученных функциями вывода объекта Graphics, в которых указан ограничивающий прямоугольник (например, drawRect, drawPie и drawChord)
PenStyle.NULL Пустое перо
PenStyle.SOLID Сплошное перо

Кроме того, объект Реп включает группу открытых переменных-членов, которые можно использовать, чтобы задать тип создаваемого пера. Каждая из этих переменных сама является объектом Реп и позволяет

Вам имитировать различные собственные черты пользовательского интерфейса Windows.

Например, в классе Реп определена переменная компонент WINDOWF-RAME. Линии, рисуемые пером типа WINDOWFRAME, выглядят аналогично рамке активного окна:

Pen pen = Pen.WINDOWFRAME;

В таблице перечислены объекты Реn, определенные как открытые переменные-члены класса Реn.

Объект

Описание

Реп.АСТР/ЕСАРТIONТЕХТ

Создает перо с цветом текста заголовка активного окна.

Pen.CONTROLTEXT

Перо с цветом текста элемента управления

Pen.GRAYTEXT

Перо с цветом заблокированного текста

Pen.HIGHLIGHTTEXT

Перо с цветом выделения текста

Pen.INACTIVECAPTIONTEXT

Перо с цветом текста заголовка неактивного окна

Pen.INFOTEXT

Перо с цветом текста подсказки

Pen.MENUTEXT

Перо с цветом текста меню

Pen.NULL

Пустое перо (не действует)

Pen.WINDOWFRAME

Перо с цветом рамки активного окна

Pen.WINDOWTEXT

Перо с цветом текста активного окна

Обратите внимание, что, когда используется перо на основе системной константы, например цвета текста активного окна, изменение системных настроек приводит к изменению пера.

Установка пера для объекта Graphics

Объект Реп сам по себе не содержит возможностей окраски или отри-совки. Он только описывает подмножество возможностей GDI. Прежде чем использовать перо для рисования, его нужно связать с объектом Graphics, используя метод setPen:

Graphics g = this.createGraphics();

g.setPen(new Pen(PenStyle.DASH));

После связывании объекта Pen с объектом Graphics все линии внутри ограничивающего прямоугольника объекта Graphics рисуются с использованием этого пера. Метод setPen можно вызывать любое число раз для одного объекта Graphics.

В следующем примере показано, как объект Реп используется объектом Graphics для рисования линий. В этом примере стили пера, определенные в объекте Реп, хранятся в целочисленном массиве. Внутри обработчика события отрисовки класса находится цикл итерации по этому массиву, в котором рисуется одна линия с использованием каждого стиля:

public class Form"! extends Form {

int [] rgStyles = { PenStyle.DASH, PenStyle.DASHDOT, PenStyle.DASHDOTDOT, PenStyle.DOT, PenStyle.INSIDEFRAME, PenStyle.SOLID };

protected void onPaint(PaintEvent e) {

Rectangle rc = this.getClientRect();

re. у += 10;

for(int i = 0; i < rgStyles.length; i++){

e.graphics.setPen(new Pen(Color.BLACK, i));

e.graphics.drawLine(new Point(0, rc.y),

new Point(re.width, rc.y));

rc.y += 10; } }

// Остальное описание класса Forml...

Использование кистей

Кисть (brush) — это графическое средство, которое приложения Win32 используют для заполнения внутренних областей многоугольников, эллипсов и произвольных фигур (paths). Приложения, предназначенные для рисования, используют кисти для заполнения фигур; текстовые редакторы — для заполнения линеек; САПР-приложения — для заполнения внутреннего вида сечений; электронные таблицы — для заполнения круговых и линейчатых диаграмм.

Есть два типа кистей: логические и физические. Логическая — это та, которая определяется в коде как идеальная комбинация цветов и/или узоров и которую приложение должно использовать для рисования. Физическую кисть драйвер устройства создает на основе определения логической кисти.

Начало координат кисти

Когда приложение вызывает функцию отрисовки для заполнения фигуры, Windows помещает кисть в начало операции отрисовки и отображает пиксел в растре кисти на начало координат клиентской области окна. (Начало координат окна (window origin) — это верхний левый угол клиентской' области.) Координаты пиксела, отображаемого Windows, называются, началом координат кисти (brush origin). По умолчанию начало координат кисти помещается в верхнем левом углу растра кисти с координатами (0,0). Затем Windows копирует кисть вдоль клиентской, области, формируя узор, который по высоте совпадает с растром. Копирование — строка за строкой — продолжается, пока не заполнится вся клиентская область. Однако узор кисти видим только внутри границ заданной фигуры. (Здесь термин растр используется в его наиболее буквальном смысле — как массив битов, а не относится исключительно к битам, хранимым в файле изображения.) В некоторых случаях начало координат кисти по умолчанию не должно использоваться. Например, приложению требуется отрисовать одной кистью фон его родительского и дочернего окон и смешать фон дочернего окна с фоном родительского окна.

Типы логических кистей

Логические кисти бывают трех разновидностей: сплошная, растровая и шаблонная.

Сплошная (solid) кисть состоит из цвета или узора, определенного для некоторого элемента пользовательского интерфейса Windows (например, можно заполнить фигуру цветом, которым в Windows отображаются запрещенные кнопки).

Шаблонная (hatched) кисть состоит из комбинации цвета и одного из шести узоров, определенных в Win32.

Растровая (pattern) кисть состоит из растра, который используется как основа для узора, заполняющего фигуру. Если область заполнения больше, чем растр, то растр размножается горизонтально и вертикально. На основе растровых кистей Вы можете создавать произвольные кисти, отображающие любой созданный Вами узор.

Объект Brush из WFC

Возможности кистей Win32 инкапсулированы в объектах Brush и BrushStyle из WFC, последние совместно используются для создания сплошных, растровых и шаблонных кистей.

Объект Brush определяет группу открытых конечных (public final) переменных-членов, каждая из которых является объектом Brush, представляющим сплошную кисть. Класс BrushStyle представляет штрихующие кисти в виде группы целочисленных констант, каждая из которых отвечает определенному стилю кисти.

В таблице перечислены константы объекта Brush, представляющие сплошные кисти.

Константа

Описание

Brush . ACTI VEBORDER

Объект Brush цвета рамки активного окна

Brush.ACTIVECAPTION

Объект Brush цвета заголовка активного окна

Brush.APPWORKSPACE

Объект Brush цвета рабочего пространства окна приложения

Brush. CONTROL

Объект Brush цвета элементов управления

Brush.CONTROLDARK

Объект Brush цвета тени трехмерного элемента

Brush.CONTROLDARKDARK

Объект Brush цвета самой темной части трехмерного элемента

Brush.CONTROLLIGHT

Объект Brush цвета подсвеченной части трехмерного элемента

Brush.CONTROLLIGHTLIGHT

Объект Brush цвета самой светлой части трехмерного элемента

Brush.DESKTOP

Объект Brush текущего цвета рабочего стола

Brush.HALFTONE

Объект Brush цвета стандартной полутоновой кисти

Brush.HIGHLIGHT

Объект Brush цвета фона подсвеченных элементов

Brush.HOLLOW

Пустая кисть, не действует

Brush.HOTTRACK

Объект Brush цвета для индикации активного отслеживания »

Brush.INACTIVEBORDER

Объект Brush цвета рамки неактивного окна

Brush.INACTIVECAPTION

Объект Brush цвета заголовка неактивного окна

Brush.INFO

Объект Brush цвета фона информационной подсказки

Brush.MENU

Объект Brush цвета фона меню

Brush.NULL

Пустая кисть

Brush.SCROLLBAR Brush.WINDOW

Объект Brush цвета фона полосы прокрутки Объект Brush цвета фона окна

Ниже перечислены константы объекта BrushStyle, представляющие штрихующие кисти.

Константа

Описание

BrushStyle. BACKWARDDIAGONAL

Представляет обратную диагональную кисть. Параллельные линии идут из левого нижнего угла в правый верхний.

BrushStyle.DIAGONALCROSS

Представляет кисть с перекрестной штриховкой.

BrushStyle.FORWARDDIAGONAL


Представляет прямую диагональную кисть. Параллельные линии идут из правого нижнего угла в левый верхний.

BrushStyle.HOLLOW

Представляет пустую кисть.

BrushStyle.HORIZONTAL


Представляет узор из равномерно распределенных горизонтальных линий.

BrushStyle.PATTERN

Представляет растровую кисть.

BrushStyle. SOLID

Представляет сплошную кисть.

BrushStyle.YERTICAL

Представляет узор из равномерно распределенных вертикальных линий.

 

Создание объекта Brush

Объект Brush создается в зависимости от типа необходимой кисти. Так как сплошные кисти являются объектами Brush, то они создаются следующим образом:

Brush br = Brush.BLACK;

Шаблонная кисть представляется объектом Brush как целая константа и создается так:

Brush br = new Brush(Color.BLACK, BrushStyle.FORWARDDIAGONAL);

В следующем фрагменте кода демонстрируется способ создания кисти на основе растра:

Brush bmpBrush = new Brush(new Bitmap(«с:\\myBitmap. bmp»));

В этом примере предполагается, что растр находится в файле на диске. Однако Вы также можете использовать метод createBitmap объекта Bitmap для создания растра во время выполнения — затем он будет положен в основу узора кисти.

Установка кисти для объекта Graphics

Подобно объектам Реп и Font, у объекта Brush нет возможностей окраски или отрисовки. Он отражает подмножество возможностей GDI. Прежде чем использовать кисть для заполнения поверхностей, ее надо связать с объектом Graphics посредством метода setBrush:

protected void onPaint(PaintEvent e) {

// Создать прямо-диагональную кисть и связать ее с объектом.

Brush br = new Brush(Color.BLACK, BrushStyle.FORWARDDIAGONAL);

e.graphics.setBrush(br);

}

После привязки объекта Brush к объекту Graphics все многоугольники, рисуемые с использованием этого экземпляра объекта Graphics, будут заполнены с помощью этой кисти. Метод setBrush можно вызывать сколь угодно часто для привязки к объекту Graphics новых кистей.

Пример объекта Brush

Произвольная кисть может быть основана на растре, который загружен из файла или создан в памяти. В примере CustomBrush демонстрируется, как создать и использовать такие кисти.

Приложение CustomBrush состоит из двух панелей и двух кнопок. Первая панель (panelGrid) состоит из 64 квадратов. Когда пользователь щелкает один из них, в приложении регистрируется щелчок, квадрат закрашивается черным и выполняются битовые операции над одним из членов массива коротких целых. Модифицируемое целое зависит от квадрата, который щелкнули.

Когда пользователь щелкает кнопку Test, в приложении CustomBrush создается растр на основе массива коротких целых, затем — кисть на основе этого растра, и эта кисть используется для рисования на панели (panelRect), которая появляется над кнопкой Test.

При запуске приложения CustomBrush выполняются следующие действия.

public class Form1 extends Form {

// Прямоугольники, на которые разделена панель.

Rectangle [] rgRects = new Rectangle[64];

// Состояния прямоугольников.

boolean [] rgStates = new boolean[64];

int [] bBrushBits = new int[8];

public Form1()

{

// Установка начального значения false для массива состояний.

for(int i = 0; i < rgStates.length; i++){ rgStates[i] = false;

}

// Инициализация формы.

initForm();

// Разделить панель на 64 прямоугольника и заполнить форму.

rgRects = getRects(panelGrid.getClientRect(), 8, 8);

this.invalidate();

}

/.*

* В этом методе заданная прямоугольная область разделяется на заданное

* число прямоугольников (вдоль и поперек), и возвращается массив,

* содержащий прямоугольники. */

private Rectangle [] getRects(Rectangle rcClient, int nAcross, int nDown){

int deltaX, deltaY;

int x, y, right, bottom;

int i;

Rectangle rgRects[] = new Rectangle[nAcross * nDown];

// Сохранить правый и нижний прямоугольники.

right = rcClient.getRight(); bottom = rcCllent, get Bottom();

// Определить высоту и ширину каждого прямоугольника.

deltaX = (right - rcClient.x) / nAcross;

deltaY = (bottom - rcClient.y) / nDown;

// Инициализировать массив прямоугольных ячеек.

for(y = rcClient.y, i = 0; у < bottom; у += deltaY){

for(x = rcClient.x;

x < (right - nAcross) && i < (nAcross * nDown);

x += deltaX, i++){

rgRects[i] = new Rectangle(x, y, deltaX, deltaY);

} }

return rgRects;

}

Когда вызывается обработчик события отрисовки на панели с сеткой, для рисования сетки используются размеры, хранимые в массиве объектов Rectangle (rgRects), и состояния, хранимые в Булевом массиве (rgStates) уровня класса. Если Булево значение, соответствующее заданному прямоугольнику, равно true, то внутренняя область прямоугольника окрашивается в черный цвет. В противном случае она окрашивается при помощи пустой кисти. Это позволяет пользователю определить внешний вид кисти, которая будет создана на основе раскладки прямоугольников на панели:

private void panelGrid_paint(Object source, PaintEyent e) {

e.graphics.setPen(new Pen(Color.BLACK, PenStyle.SOLID, 1));

// Нарисовать сетку, отражающую текущее состояние квадратов.

for(int i = 0; i < rgRects.length; i++){

if(rgStates[i] == true){

// Если квадрат ранее щелкнули, заполнить его.

e.graphics.setBrush(new Brush(Color.BLACK)); }else{

e.graphics.setBrush(Brush.NULL); }

e.g raphics.d rawRect(rgRects[i]); }

}

При каждом щелчке пользователя одного из прямоугольников панели i сеткой генерируется событие щелчка. Внутри обработчика события оп ределяется, какой прямоугольник щелкнули, соответствующее Булевс значение в массиве устанавливается в true и вызывается panelGrid.inva lidate, чтобы вызвать перерисовку. Кроме того, выполняется битова; операция над соответствующим членом массива битов, хранящимися i переменной bBrushBits уровня класса:

private void panelGrid_mouseDown(Object source, MouseEvent e) {

Graphics gr = this.createGraphics();

gr.setBrush(new Brush(Color.BLACK));

Integer nBit = new Integer(O); // Определить ячейку, которую щелкнули.

for(int i = 0; i < 64; i++){

Rectangle rc = new Rectangle(rgRects[i].x,

rgRects[i].y, rgRects[i].height, rgRects[i].width);

if(rc.contains(new Point(e.x, e.y))){

// Установить соответствующую Булеву переменную состояния.

rgStates[i] = true;

// Выполнить побитовую операцию NOT над соответствующим

// целым в массиве коротких целых, на котором основан растр.

if(i % 8 == 0)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x80; if(i HI 8 == 1)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x40; if(i % 8 == 2)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x20; if(i X 8 == 3)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x10; if(i X 8 == 4)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x08; if(i % 8 == 5)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x04; if(i X 8 == 6)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x02; if(i % 8 == 7)

bBrushBits[i/8] = bBrushBits[i/8] ^ 0x01;

break;

} }

// Перерисовать сетку. panelGrid. invalidate();

}

Наконец, когда пользователь щелкает кнопку Test, обработчик события такого щелчка заставляет перерисовать панель panelRect, появляющейся над кнопкой Test благодаря вызову panelRect.invalidate:

private void btnTest_click(Object source, Event e)

{

panelRect.invalidate();

}

Внутри обработчика события отрисовки панели panelRect приложение создает растр на основе массива коротких целых (bBrushBits) и кисть на основе этого растра и далее этой кистью раскрашивает панель panelRect, появляющаяся над кнопкой Test:

private void panelRect_paint(Object source, PaintEvent e)

{

short [] rgShorts = new short[8];

for(int i = 0; i < bBrushBits.length; i++){

rgShorts[i] = (short) bBrushBits[i]; }

e.graphics.setBrush(new Brush(new Bitmap(8,8,1,1,rgShorts)));

e. graphics. fill(panelRect. getClientRect());

}

Вывод растровых изображений

Растр (bitmap) — это поверхность для рисования. Ее используют для вывода перьев, кистей или изображений, включая растры и метафайлы Windows, а также файлы форматов .gif и .jpg.

Объект Bitmap поддерживает создание и загрузку растров. Его можно применять для загрузки растровых изображений из файлов, потоков данных или ресурсов или для создания таких изображений в памяти. Кроме того, объект Bitmap поддерживает определение прозрачных цветов внутри растра.

После создания объекта Bitmap для вывода его на дисплей используется метод drawlmage объекта Graphics.

В следующем фрагменте кода создается новый объект Bitmap, а затем для создания объекта Graphics, рисующего изображение, используется метод createGraphics класса Form:

Bitmap bmp = new Bitmap(«c:\\MyImage.bmp»);

Graphics g = this.createGraphics();

g.drawlmage(bmp, new Point(10, 10));

Сжатие и растяжение изображений

Все объекты-изображения, поддерживаемые WFC (Metafile, Icon, Bitmap и Cursor), имеют методы drawStretchTo и drawTo. Любой вывод изображений посредством объекта Graphics выполняется с помощью этих методов. Когда вызывается метод drawlmage объекта Graphics, последний определяет, какой из методов — drawStretchTo или drawTo -надо вызывать для переданного объекта.

Метод drawStretchTo расширяет или сжимает изображение, чтобы оно уместилось в заданную прямоугольную область. Метод drawTo также выводит изображение в заданную область, но обрезает его, если оно слишком велико. Кроме того, оба метода поддерживают вывод разделов изображения в заданный раздел ограничивающего прямоугольника объекта Graphics.

Методы drawStretchTo или drawTo нельзя вызывать напрямую: в классах изображений в WFC они всегда объявляются защищенными (protected). Чтобы определить, какой из этих методов будет вызван, исполь-

зуется версия метода drawlmage, имеющая Булев параметр scale. Вот один из таких методов, определенный в объекте Graphics: public final void drawlmage(lmage i, Rectangle r, Boolean scale) Если параметр scale равен true, то изображение будет растянуто или сжато до размеров отсекающего прямоугольника; в противном случае изображение будет обрезано.

Прозрачная визуализация изображений

Объект Bitmap поддерживает прозрачную визуализацию одного или нескольких цветов изображения.

Если нужно сделать прозрачным один цвет, используются методы set-TransparentColor и setTransparent. Метод setTransparentColor получает в качестве параметра объект Color, определяющий цвет, который будет прозрачным. Метод setTransparent принимает Булево значение, которое определяет, должен ли выводится заданный прозрачный цвет или нет. Например, в следующем фрагменте кода черный цвет определен как прозрачный. Когда для отрисовки изображения вызывается метод draw-Image объекта Graphics, черные пикселы не выводятся:

protected void onPaint(PaintEvent e) {

Bitmap bmp = new Bitmap(«c:\\MyImage.bmp»);

Bmp.setTransparentColor(Color.BLACK); Bmp.setTransparent(false);

e.graphics.drawlmage(bmp, new Point(0,0));

}

Прозрачность достигается и путем создания объекта Bitmap на основе двух битовых масок — одной цветной и одной монохромной. В цветной маске каждая часть растра, которая выводится прозрачной, должна быть черного цвета. В монохромной маске каждая часть, которая выводится прозрачной, должна быть белого цвета.

Растровые операции

Растровая операция предполагает логическое действие над отображением базисного элемента GDI — пера, кисти, растра или фигуры -с целью получения визуального эффекта. Растровые операции, выполняемые с использованием объекта Graphics, определены в объекте Graphics. Просмотрев методы, поддерживаемые объектом Graphics, Вы увидете, что для каждой базовой операции — проведения линии или вывода изображения — есть метод, получающий RasterOp в качестве параметра.

В своих простейших воплощениях методы отрисовки объекта Graphics поддерживают только запись или копирование пикселов в некоторую область дисплея, заменяя текущее изображение. Добавьте в это уравнение растровые операции, и такая замена усложнится. Предположим, что надо нарисовать черный прямоугольник в области экрана, занятой в данный момент изображением, но желательно логически скомбинировать черные пикселы с соответствующими им пикселами на целевом изображении и вывести результаты на дисплей. Растровые операции делают такую комбинацию возможной.. Вариантов логики, поддерживаемых объектом RasterOps, слишком много, чтобы рассмотреть их все в этом документе. В следующих операторах демонстрируется типовой синтаксис вызова с использованием объекта RasterOps — устанавливается фоновый цвет формы и затем рисуется линия одетом, являющимся инверсией фонового цвета:

protected void onPaint(PaintEvent e)

{

this.setBackColor(new Color(255, 255, 255);

e.graphics.drawLine(new Point(10, 10), new Point(100, 10),

RasterOp.TARGET. invert());

}

Вывод кривых

Объект Graphics поддерживает вывод линий, прямоугольников, сегментов, дуг, секторов и сплайнов Безье.

Линии

Линия — это набор подсвеченных пикселов на дисплее, идентифицируемый двумя точками: начальной и конечной. В Windows пиксел, находящийся в начальной точке, всегда включается в линию, а пиксел, расположенный в конечной точке, всегда исключается (такие линии иногда называются inclusive-exclusive).

Приложение может нарисовать одну линию, вызвав метод drawLine объекта Graphics. Этот метод получает два параметра типа Point, которые задают начало и конец линии:

protected void onPaint(PaintEvent e){

Rectangle rcClient = this.getClientRect();

// Нарисовать линии, которые делят экран на четыре одинаковых квадрата.

e.graphics.drawLine(new Point(rcClient.x, rcClient.height / 2),

new Point(rcClient.width, rcClient.height / 2));

e.graphics.drawl_ine(new Point(rcClient.width / 2, rcClient.y),

new Point(rcClient.width / 2, rcClient,height)); }

Прямоугольники

Приложения, написанные для Microsoft Windows, используют прямоугольники, чтобы задать прямоугольные области на экране или в окне. Прямоугольники описывают клиентскую область окна, области на экране, которые нужно перерисовать, и области для вывода форматированного текста. Приложения могут также применять прямоугольники для заполнения, ограничения или инвертирования части клиентской области с использованием данной кисти и для получения координат окна или его клиентской области.

Размеры прямоугольных областей описываются объектом Rectangle из WFC. Этот объект содержит целые х, у, height и width, которые определяют его местонахождение и размеры на экране. Кроме того, для получения положения правой и нижней сторон можно использовать методы getRight и getBottom.

Подробности см. в разделах «Операции с прямоугольниками» и «Пример прямоугольника» далее в этой главе.

Операции с прямоугольниками

Объект Rectangle предоставляет ряд методов для работы с прямоугольниками. Метод equals определяет, идентичны ли два объекта Rectangle, т. е. одинаковы ли их координаты.

Метод inflateRect увеличивает или уменьшает ширину, высоту прямоугольника или оба параметра вместе. Его средствами можно изменить размеры с обеих сторон прямоугольника, а также снизу и сверху. Замещаемый метод contains позволяет определить, находится ли область, описываемая одним прямоугольником, внутри другого, и узнать, находится ли заданная точка внутри прямоугольника. Методы intersects и intersectsWith определяют, пересекаются ли два объекта Rectangle.

Пример прямоугольника

Пример в этом разделе показывает, как разделить части клиентской области приложения на подобласти и как работать внутри этих областей. При запуске приложение делит клиентскую область основной формы на прямоугольные подобласти в количестве 16 на 16 и в каждой из них отображает оттенок заданного цвета. Чтобы изменить число прямоугольников, отображаемых по высоте и ширине дисплея, выберите команду меню Dimensions для вывода диалогового окна, в котором можно задать число прямоугольников.

Метод деления экрана на объекты Rectangle приведен в следующем примере. У этого метода getRects есть три параметра: прямоугольник, определяющий разделяемую область, и два целых числа, которые задают число ячеек, рисуемых по высоте и ширине. Метод возвращает массив прямоугольников с соответствующими координатами:

private Rectangle[] getRects(Rectangle rcClient, int nDown, int nAcross){

int deltaX, deltaY; // Ширина и высота каждой ячейки, int x, у;

int i;

Rectangle rgRects[] = new Rectangle[nDown * nAcross];

// Определить ширину и высоту каждого прямоугольника.

deltaX = (rcClient.getRight() - rcClient.x) / nAcross;

deltaY = (rcClient.getBottom() - rcClient.y) / nDown;

// Создать и инициализировать массив прямоугольников.

for(y = rcClient.у, i = 0; у < rcClient.getBottom();

у += deltaY){ for(x = rcClient.x; x < (rcClient.getRight() - nAcross) && i < (nAcross * nDown); x += deltaX, i++){

rgRects[i] = new Rectangle(x, y, deltaX, deltaY); } }

// Возвратить инициализированный массив.

return rgRects; }

При запуске приложения его конструктор класса Form инициализирует значением 16 две целых переменных уровня класса — nAcross и nDown, а также вызывает описанный выше метод getRects:

public Form1(){

initForm(); nAcross = 16; nDown = 16;

// Инициализировать массив уровня класса.

rgRects = getRects(this.getClientRect(), nAcross, nDown);

}

После выполнения конструктора класса автоматически вызывается обработчик события отрисовки этого класса. Этот обработчик события проходит по массиву rgRects уровня класса, использует метод setBrush объекта Graphics для установки нового цвета и затем вызывает метод drawRcct для отрисовки каждого прямоугольника из массива:

protected void onPaint(PaintEvent e){

for(int i = 0; i < rgRects.length; i++){

e.graphics.setBrush(new Brush(new Color(0,0,i)));

e.graphics.drawRect(rgRects[i]); } }

Наконец, обработчик события resize класса Form заново инициализирует массив и вызывает перерисовку клиентской области формы:

protected void onflesize(Event e){

Rectangle rcClient = this.getClientRect();

rgRects = getRects(rcClient, nDown, nAcross); this. invalidate(); }

Сегменты

Сегмент (chord) — это область, ограниченная частью эллипса и линией, называемой секущей (secant). Сегмент рисуется с использованием текущего пера и заполняется с использованием текущей кисти. Часть эллипса по другую сторону секущей удаляется.

Чтобы нарисовать сегмент, используйте метод drawChord объекта Graphics, который имеет следующий синтаксис: drawChord( Rectangle p1, Point p2, Point p3)

Параметр Rectangle метода drawChord обозначает область, в которой будет нарисован эллипс. Два параметра Point обозначают точки, в которых секущая пересекает эллипс.

В следующем примере метод drawChord вызывается дважды. При первом вызове сегмент рисуется в нижнем левом углу дисплея, а при втором — в правом верхнем. Перед каждым вызовом drawChord с объектом Graphics связываются разные кисти, чтобы сегменты, вместе образующие круг, были нарисованы соответственно черным и белым цветом:

protected void onPaint(PaintEvent e){

Rectangle rcClient = this.getClientRect();

// Связать с объектом черную кисть и нарисовать сегмент.

e.graphics.setBrush(new Brush(new Color(0,0,0)));

e.graphics.drawChord(rcClient, new Point(rcClient.x, rcClient.y), new Point(rcClient.getRight(), rcClient.getBottom());

// Связать с объектом белую кисть и нарисовать сегмент.

e.graphics.setBrush(new Brush(new Color(255,255, 255)));

e.graphics.drawChord(rcClient, new Point(rcClient.getRight(), rcClient.getBottomO), new Point(rcClient.x, rcClient.y)); }

Дуги

Приложение может нарисовать эллипс или часть эллипса путем вызова метода drawArc. Этот метод рисует кривую внутри периметра невидимого прямоугольника, называемого ограничивающим прямоугольником. Размер эллипса задается двумя невидимыми радиусами — от центра прямоугольника к его сторонам.

При вызове метода drawArc приложение задает координаты ограничивающего прямоугольника и радиусы.

В следующем примере рисуется дуга, которая заполняет клиентскую область формы, а затем используется метод drawLine объекта Graphics для проведения линии от верха дуги к ее радиусу и затем от радиуса к правой части эллипса:

protected void onPaint(PaintEvent e){

Rectangle rcClient = this.getClientRect();

e.graphics.drawArc(rcClient, new Point(rcClient.width /2, rcClient.y),

new Point(rcClient.width, rcClient.height / 2));

e.graphics.drawLine(new Point(rcClient.width / 2, rcClient.y),

new Point(rcClient.width / 2, rcClient.height / 2));

e.graphics.drawLine(new Point(rcClient.width, rcClient.height / 2),

new Point(rcClient.width / 2, rcClient.height / 2)); }

Угловая мера дуги

Угловая дуга (arc angle) подобна обычной. Основное различие в том, что при рисовании дуги с использованием drawArc задаются значения х и у радиусов дуги. При отрисовке угловой дуги используется метод drawArcAngle и задается угол; метод сам определяет координаты начала и конца.

Метод drawArcAngle имеет следующий синтаксис:

public final void drawArcAngle(Point center, int radius, float startAngle, float endAngle)

Параметр типа Point задает место на экране, от которого отсчитывается радиус, определяемый параметром radius. Параметр start Angle задает угол в градусах, с которого начинается дуга, а параметр endAngle определяет, какой угол в градусах составляет рисуемая дуга. В следующем примере показано, как использовать этот метод. Здесь рисуется угловая дуга, startAngle который равен 30°, a endAngle равен 300°:

protected void onPaint(PaintEvent e){

Rectangle rcClient = this.getClientRect();

int x = rcClient.width / 2;

int у = rcClient.height / 2;

int radius = 100;

float startAngle = 30;

float endAngle = 300;

e.graphics.drawAngleArc(new Point(x.y), radius, startAngle, endAngle); }

Безье-сплайны

Безье-сплайны (Bezier spline) определяются четырьмя точками — двумя концевыми и двумя контрольными. Вместе эти точки определяют кривую. Две концевые точки определяют начало и конец кривой. Контрольные точки служат для «оттягивания» кривой от отрезка прямой, образованной начальной и конечной точками.

Для рисования Безье-сплайнов используйте метод drawBezier. Этот метод получает в качестве параметра массив объектов Point. Первые четыре элемента массива задают начальную точку, две контрольных и конечную точку.

Для рисования нескольких сплайнов подключают три элемента массива следующего сплайна к последней точке предыдущего. Конечная точка первого сплайна служит начальной точкой следующего, а три элемента массива определяют его контрольные точки и конечную точку. В следующем коде метод drawBezier используется для вывода кривой при каждом изменении размера окна:

protected void onPaint(PaintEvent e) {

Point [] pt = new Point[4];

Rectangle re = this.getClientRect();

int right = rc.getRight();

int bottom = rc.getBottom();

pt[0] = new Point(right / 4, bottom / 2);

pt[1] = new Point(right / 2, bottom / 4);

pt[2] = new Point(right / 2, 3 * bottom / 4);

pt[3] = new Point(3 * right / 4, bottom / 2);

e.graphics.drawBezier(pt); }

protected void onResi2e(Event e)

{

this.invalidate();

}

к оглавлению   к 4GL - визуальному программированию

Знаете ли Вы, что такое мысленный эксперимент, gedanken experiment?
Это несуществующая практика, потусторонний опыт, воображение того, чего нет на самом деле. Мысленные эксперименты подобны снам наяву. Они рождают чудовищ. В отличие от физического эксперимента, который является опытной проверкой гипотез, "мысленный эксперимент" фокуснически подменяет экспериментальную проверку желаемыми, не проверенными на практике выводами, манипулируя логикообразными построениями, реально нарушающими саму логику путем использования недоказанных посылок в качестве доказанных, то есть путем подмены. Таким образом, основной задачей заявителей "мысленных экспериментов" является обман слушателя или читателя путем замены настоящего физического эксперимента его "куклой" - фиктивными рассуждениями под честное слово без самой физической проверки.
Заполнение физики воображаемыми, "мысленными экспериментами" привело к возникновению абсурдной сюрреалистической, спутанно-запутанной картины мира. Настоящий исследователь должен отличать такие "фантики" от настоящих ценностей.

Релятивисты и позитивисты утверждают, что "мысленный эксперимент" весьма полезный интрумент для проверки теорий (также возникающих в нашем уме) на непротиворечивость. В этом они обманывают людей, так как любая проверка может осуществляться только независимым от объекта проверки источником. Сам заявитель гипотезы не может быть проверкой своего же заявления, так как причина самого этого заявления есть отсутствие видимых для заявителя противоречий в заявлении.

Это мы видим на примере СТО и ОТО, превратившихся в своеобразный вид религии, управляющей наукой и общественным мнением. Никакое количество фактов, противоречащих им, не может преодолеть формулу Эйнштейна: "Если факт не соответствует теории - измените факт" (В другом варианте " - Факт не соответствует теории? - Тем хуже для факта").

Максимально, на что может претендовать "мысленный эксперимент" - это только на внутреннюю непротиворечивость гипотезы в рамках собственной, часто отнюдь не истинной логики заявителя. Соответсвие практике это не проверяет. Настоящая проверка может состояться только в действительном физическом эксперименте.

Эксперимент на то и эксперимент, что он есть не изощрение мысли, а проверка мысли. Непротиворечивая внутри себя мысль не может сама себя проверить. Это доказано Куртом Гёделем.

Понятие "мысленный эксперимент" придумано специально спекулянтами - релятивистами для шулерской подмены реальной проверки мысли на практике (эксперимента) своим "честным словом". Подробнее читайте в FAQ по эфирной физике.

НОВОСТИ ФОРУМА

Форум Рыцари теории эфира


Рыцари теории эфира
 10.11.2021 - 12:37: ПЕРСОНАЛИИ - Personalias -> WHO IS WHO - КТО ЕСТЬ КТО - Карим_Хайдаров.
10.11.2021 - 12:36: СОВЕСТЬ - Conscience -> РАСЧЕЛОВЕЧИВАНИЕ ЧЕЛОВЕКА. КОМУ ЭТО НАДО? - Карим_Хайдаров.
10.11.2021 - 12:36: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от д.м.н. Александра Алексеевича Редько - Карим_Хайдаров.
10.11.2021 - 12:35: ЭКОЛОГИЯ - Ecology -> Биологическая безопасность населения - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> Проблема государственного терроризма - Карим_Хайдаров.
10.11.2021 - 12:34: ВОЙНА, ПОЛИТИКА И НАУКА - War, Politics and Science -> ПРАВОСУДИЯ.НЕТ - Карим_Хайдаров.
10.11.2021 - 12:34: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вадима Глогера, США - Карим_Хайдаров.
10.11.2021 - 09:18: НОВЫЕ ТЕХНОЛОГИИ - New Technologies -> Волновая генетика Петра Гаряева, 5G-контроль и управление - Карим_Хайдаров.
10.11.2021 - 09:18: ЭКОЛОГИЯ - Ecology -> ЭКОЛОГИЯ ДЛЯ ВСЕХ - Карим_Хайдаров.
10.11.2021 - 09:16: ЭКОЛОГИЯ - Ecology -> ПРОБЛЕМЫ МЕДИЦИНЫ - Карим_Хайдаров.
10.11.2021 - 09:15: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Екатерины Коваленко - Карим_Хайдаров.
10.11.2021 - 09:13: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ - Upbringing, Inlightening, Education -> Просвещение от Вильгельма Варкентина - Карим_Хайдаров.
Bourabai Research - Технологии XXI века Bourabai Research Institution