Помощь - Поиск - Пользователи - Календарь
Полная версия: Графический редактор в Delphi
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Страницы: 1, 2, 3
SeregaR1Val
Добрый день! Необходимо написать графический редактор следующего вида:
Окно разбито на 2 части, в левой вводятся параметры фигуры, в правой она отрисовывается. Например: для начала задан прямоугольник высотой 50 и шириной 100. Указываем высоту - 25, на ней ширина 50 и фигура должна преобразоваться, приняв форму песочных часов и далее в этом духе. Надеюсь нормально объяснил...

Программу еще не начал, код писать не прошу, необходима консультация в том, какие элементы выбрать для разработки, TPaintBox или TImage и т.д. и как лучше всё это отрисовывать, может кто может дать совет?
TarasBer
Что-то я пока не очень понял.
Если мы можем только менять ширину на конкретной высоте.
То есть фигура может иметь только такой вид?
Гость
Да, только такой, возможно надо будет сругленные углы добавить, но пока только такой вид! Может есть у кого какие соображения? Опыт подсказывает, что первое попавшееся решение потом приходится переделывать, хотелось бы узнать мнение знающих людей и приступить к работе!
TarasBer
То есть все инструкции определяются только двумя параметрами - высота и ширина?
Ну так и храни массив пар (высота, ширина)
Изначально массив состоит из 2 пар: (25, 100) и (-25, 100)
Каждая команда добавляет пару к массиву.
Потом отсортируй по высоте.
Потом просто выведи ломаную линию (стандартная функция, передай в неё массив пар (ширина пополам плюс середина экрана, высота)), отрази её (передай пары (середина экрана минус ширина пополам, высота)).
Потом нарисуй верхнюю и нижнюю грани (длину линии определи по ширине на максимальной и минимальной высоте).
RussoTuristo
Извините, придется заходить не под собой, мой профиль исчез куда-то))))
Навоял что-то, но работает оно совсем не так... Отрисовывается что-то непонятное, а из-за того, что изображение строю в буфере, отследить по шагам не удается... Может я что не так делаю? Подскажите, пожалуйста...
Код:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, Grids, ExtCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
PaintBox1: TPaintBox;
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
StringGrid1: TStringGrid;
BitBtn1: TBitBtn;
Label3: TLabel;
procedure FormActivate(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
img, buffer: TBitmap;
pol:array[1..100] of TPoint;
ar1,ar2: array[1..2,1..100] of real;
l,h:integer;

implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);
begin
StringGrid1.Cells[0,0]:='Ширина';
StringGrid1.Cells[1,0]:='Высота';
StringGrid1.Cells[0,1]:='70';
StringGrid1.Cells[1,1]:='200';
StringGrid1.Cells[0,2]:='120';
StringGrid1.Cells[1,2]:='300';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Img:=TBitmap.Create;
buffer:=TBitmap.Create;
img.Width:=PaintBox1.ClientWidth;
buffer.Width:=PaintBox1.ClientWidth;
img.Height:=PaintBox1.ClientHeight;
buffer.Height:=PaintBox1.ClientHeight;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
i:integer;
a1,a2:real;
begin
//ar1 и ar2-содержат точки аттриума(1-левая грань,2-правая)
img.Canvas.Pen.Color:=clBlack;
l:=StrtoInt(edit1.text);
h:=StrtoInt(edit2.text);
//Начальная фигура -прямоугольник(зададим углы)
ar1[1,1]:=10; ar1[2,1]:=10;
ar1[1,100]:=10; ar1[2,100]:=10+h;
ar2[1,1]:=10+l; ar2[2,1]:=10;
ar2[1,100]:=10+l; ar2[2,100]:=10+h;
//заполним массивы точками из таблицы
for i:=2 to 100 do
begin
if (StringGrid1.Cells[1, i]<>'') and (StringGrid1.Cells[2, i]<>'') then begin
a1:=StrToInt(StringGrid1.Cells[1, i]);
a2:=StrToInt(StringGrid1.Cells[2, i]);
ar1[1,i]:=10+Round((h-a1)/2);
ar1[2,i]:=10+a2;
ar2[1,i]:=10+Round((h-a1)/2)+a1;
ar2[2,i]:=10+a2;
end;
end;
//Тут надо отсортировать массивы ar1 и ar2 по высоте

//Печать того, что получилось
img.Canvas.MoveTo(10,10);
for i:=1 to 100 do begin
if (ar1[1, i]<>0) and (ar1[2, i]<>0) then begin
img.Canvas.LineTo(Round(ar1[1,i]),Round(ar1[2,i]));
end;
end;
img.Canvas.MoveTo(10,10+l);
for i:=1 to 100 do begin
if (ar2[1, i]<>0) and (ar2[2, i]<>0) then begin
img.Canvas.LineTo(Round(ar2[1,i]),Round(ar2[2,i]));
end;
end;

//Отрисовка верхней и нижней граней
img.Canvas.MoveTo(10,10);
img.Canvas.LineTo(10+l,10);
img.Canvas.MoveTo(10,10+l);
img.Canvas.LineTo(10+h,10+l);
//Перевод изображения из буфера
paintbox1.Canvas.CopyRect(bounds(0,0,img.Width,img.Height),
img.Canvas,bounds(0,0,img.Width,img.Height));
end;

end.


Массивы ar1 и ar2 из StringGrid по-моему он не заполняет... или потом не считывает....
TarasBer
> StringGrid1.Cells[0,0]:='Ширина';
> StringGrid1.Cells[1,0]:='Высота';
> StringGrid1.Cells[0,1]:='70';
> StringGrid1.Cells[1,1]:='200';
> StringGrid1.Cells[0,2]:='120';
> StringGrid1.Cells[1,2]:='300';

> 0 1



> img.Canvas.MoveTo(10,10);
> for i:=1 to 100 do begin
> if (ar1[1, i]<>0) and (ar1[2, i]<>0) then begin
> img.Canvas.LineTo(Round(ar1[1,i]),Round(ar1[2,i]));
> end;
> end;
> img.Canvas.MoveTo(10,10+l);
> for i:=1 to 100 do begin
> if (ar2[1, i]<>0) and (ar2[2, i]<>0) then begin
> img.Canvas.LineTo(Round(ar2[1,i]),Round(ar2[2,i]));
> end;
> end;

> 1 2

У тебя нумерация сбилась.
RussoTuristo
Что-то до меня не доходит... В строке 0 - заголовочная часть, её пропускаем, часть StringGrida заполнена, она начинается со строки 1 и считываем для отрисовки соответственно со строки 1... Не понимаю, где ошибся. Объясните, пожалуйста, еще немного...
TarasBer
Я тебе привёл 2 фрагмента.
В одном ты берёшь 1й индекс 0 и 1
В другом ты берёшь 1й индекс 1 и 2.

Кстати, 1й индекс - это точно номер столбца?
RussoTuristo
В одном ты берёшь 1й индекс 0 и 1
В другом ты берёшь 1й индекс 1 и 2.
Структуры-то разные по сути, StringGrid и массивы ar1. ar2, если ошибаюсь и здесь ошибка - извините заранее...

А насчет индекса навёл много сомнений, только с массивами я работал не так основательно, что-то сам вникнуть не могу, по моей какой-то логике и примеру из учебника вроде так, но буду благодарен, если вы меня разубедите ...
TarasBer
Ещё раз.
Вот тебе два куска твоего кода:

StringGrid1.Cells[0,0]:='Ширина';
StringGrid1.Cells[1,0]:='Высота';

a1:=StrToInt(StringGrid1.Cells[1, i]);
a2:=StrToInt(StringGrid1.Cells[2, i]);

Что, не настораживает?

Ещё раз:

StringGrid1.Cells[0,0]:='Ширина';
StringGrid1.Cells[1,0]:='Высота';

a1:=StrToInt(StringGrid1.Cells[1, i]);
a2:=StrToInt(StringGrid1.Cells[2, i]);

> Структуры-то разные по сути, StringGrid и массивы ar1. ar2

Нет, ты и там и там обращаешься к "массиву" StringGrid.Cells.
RussoTuristo
Спасибо, понял, что с индексами не так!
volvo
Цитата
придется заходить не под собой, мой профиль исчез куда-то))))
Ничего не исчезло. Посмотри первое сообщение. Если б профиль исчез, там было бы написано, что сообщение оставил Гость. Пароль забыл, что-ли?
RussoTuristo
Цитата(volvo @ 4.02.2011 12:36) *

Ничего не исчезло. Посмотри первое сообщение. Если б профиль исчез, там было бы написано, что сообщение оставил Гость. Пароль забыл, что-ли?

Есть подозрения, что меня взломали, пароль не пашет. Копировал имя из этого поста и просил отправить пароль на ящик, написано было, что такого имени нет на форуме, странно...

Чтоб много сообщений не оставлять, спрошу здесь:
Все заработало как надо, отрисовывается, но появился ламерский вопрос: как имитировать нажатие кнопки BitBtn? Раньше знал, сейчас даже в drkb найти не могу...
TarasBer
Просто пишешь BitBtn1Click(Sender);
RussoTuristo
Помогите, пожалуйста, еще с одной вещью: как правильно отсортировать двумерный массив по одному из индексов. Мне нужно расположить значения массивов ar1 и ar2 в порядке возрастания по высоте (2-й столбец). Но это оказывается непросто:
for i:=1 to 100 do
for j:=1 to 100 do
if ar1[2,i]<ar1[2,j] then begin
buf1:=ar1[1,i];
buf2:=ar1[2,i];
ar1[1,j]:=ar1[1,i];
ar1[2,j]:=ar1[2,i];
ar1[1,i]:=buf1;
ar1[2,i]:=buf2;
end;


Что-то пытаюсь придумать, но чушь какая-то выходит....
TarasBer
Надо так:

buf1:=ar1[1,j];
buf2:=ar1[2,j];
ar1[1,j]:=ar1[1,i];
ar1[2,j]:=ar1[2,i];
ar1[1,i]:=buf1;
ar1[2,i]:=buf2;


да что же у тебя так хреново с индексами-то...
RussoTuristo
Спасибо! Невнимательность моя... вроде могу сообразить принцип, а мелочи, даже очень значительные, пропускаю...

Можно узнать, а есть ли в Delphi возмоожность подогнать изображение под холст, то есть, например: на форме есть место под PaintBox размером 200 на 400 пикселей, а изображение может быть очень большим, можно ли как-нибудь "подогнать" его, чтобы оно оставшись своих размеров, отображалось в уменьшенном виде?
TarasBer
PaintBox1.Canvas.StretchDraw(какие-то параметры, не помню, дельфи сама подскажет)
RussoTuristo
StretchDraw не подойдет на сколько я понимаю....
Paintbox не имеет свойства Graphic...
Paintbox1.Canvas.StretchDraw(MyRect,Paintbox1.Graphic); выдает ошибку...
Может есть другие способы, или необходимо Painbox менять на что-то?

И еще вопросик... Изображение получается недолговечным... перетаскиваешь какое-нибудь окно или просто сворачиваешь и нету ничего.... как сделать чтобы изображение не стиралось?
volvo
У тебя какой-то "неправильный мёд" (С)

В PaintBox-е всегда был Canvas: TPaintBox.Canvas Property

А чтобы изображение было "долговечным", и его не надо было перерисовывать каждый раз по OnPaint, используй TImage, он "хранит" свое содержимое...
RussoTuristo
Извините за Canvas, действительно пропустил, но Paintbox1.Canvas.Graphic тоже не работает....

То есть чтобы оно "хранилось" вместо Paintbox необходимо использовать Image? Еще раз извините за глупый вопрос, просто не хочется из-за недопонимания переписывать всё...
volvo
TPaintBox так устроен, что не хранит изображение, которое в нем нарисовано. Ему просто негде его хранить. Это обычная канва. Чем-то напоминает "узоры на песке", их тоже видно, пока ветер не подует или пока дождь не пойдет. Пока твое окно не перекрыто другими окнами - все видно. Как только окно перекроется - все, что было тобой нарисовано в PaintBox-е сотрется. Чтобы восстановить изображение, тебе придется перерисовать его. Поэтому заполняют TPaintBox обычно в событии OnPaint, то есть, полностью перерисовывают содержимое каждый раз, когда приходит сообщение WM_PAINT.

TImage снимает с тебя заботу о перерисовке своего содержимого. Допустим, по нажатию TButton ты нарисовал линию, свернул программу на таскбар, развернул - линия ровно в том же месте, где и была. PaintBox в аналогичном случае будет пуст.
RussoTuristo
Спасибо за разъяснение, запомню и переделаю, в принципе не так много работы прибавится.
TarasBer
> Извините за Canvas, действительно пропустил, но Paintbox1.Canvas.Graphic тоже не работает....

Просто Canvas, блин, без .Graphic!
RussoTuristo
Вместо Paintbox взял Image, всё отрисовывается хорошо, не исчезает никуда, но StretchDraw упрямится - ошибок не выдает но и не сжимает ничего, когда изображение больше, чем Image, видна лишь часть изображения...

MyRect := Rect(0,0,250,450);
Image1.Canvas.StretchDraw(MyRect, Image1.Picture.Graphic);


Может я что-то опять напутал?

и еще вопросик:
Изображение не пропадает, но не делает это вообще:
Пишу в событии кнопки первой строкой Img.free и выдает ужасную ошибку: Invalide Pointer operation
TarasBer
А ты задай MyRect побольше (или поменьше) раз в 10, узнаешь, напутал, или нет. А лучше задавай MyRect в зависимости от максимального и минимального из вводимых значений.
RussoTuristo
Действительно, ошибок не выдает, но это не значит, что работает... думаю я не в том месте его указываю(хотя пробовал в разных) или аргументы не те, посмотрите, пожалуйста, может какие замечания будут по стилю или применению функций, новичок в этом деле, готов учиться на своих ошибках...
procedure TForm1.BitBtn1Click(Sender: TObject);
var
i,j:integer;
a1,a2,buf1,buf2:real;
MyRect:TRect;
begin
//ar1 и ar2-содержат точки фигуры(1-левая грань,2-правая)
img.Canvas.Pen.Color:=clBlack;
l:=StrtoInt(edit1.text);
h:=StrtoInt(edit2.text);
//Начальная фигура -прямоугольник(зададим углы)
ar1[1,1]:=10; ar1[2,1]:=10;
ar1[1,100]:=10; ar1[2,100]:=10+h;
ar2[1,1]:=10+l; ar2[2,1]:=10;
ar2[1,100]:=10+l; ar2[2,100]:=10+h;
//заполним массивы точками из таблицы
for i:=1 to 100 do
begin
if (StringGrid1.Cells[0, i]<>'') and (StringGrid1.Cells[1, i]<>'') then begin
a1:=StrToInt(StringGrid1.Cells[0, i]);
a2:=StrToInt(StringGrid1.Cells[1, i]);
ar1[1,i+1]:=10+Round((l-a1)/2);
ar1[2,i+1]:=10+a2;
ar2[1,i+1]:=10+Round((l-a1)/2)+a1;
ar2[2,i+1]:=10+a2;
end;
end;
//Сортируем массивы по высоте
for i:=1 to 100 do
for j:=1 to 100 do
if ar1[2,i]<ar1[2,j] then begin
buf1:=ar1[1,j];
buf2:=ar1[2,j];
ar1[1,j]:=ar1[1,i];
ar1[2,j]:=ar1[2,i];
ar1[1,i]:=buf1;
ar1[2,i]:=buf2;
end;
for i:=1 to 100 do
for j:=1 to 100 do
if ar2[2,i]<ar2[2,j] then begin
buf1:=ar2[1,j];
buf2:=ar2[2,j];
ar2[1,j]:=ar2[1,i];
ar2[2,j]:=ar2[2,i];
ar2[1,i]:=buf1;
ar2[2,i]:=buf2;
end;
//Печать того, что получилось
img.Canvas.MoveTo(10,10);
for i:=1 to 100 do begin
if (ar1[1, i]<>0) and (ar1[2, i]<>0) then begin
img.Canvas.LineTo(Round(ar1[1,i]),Round(ar1[2,i]));
end;
end;
img.Canvas.MoveTo(10+l,10);
for i:=1 to 100 do begin
if (ar2[1, i]<>0) and (ar2[2, i]<>0) then begin
img.Canvas.LineTo(Round(ar2[1,i]),Round(ar2[2,i]));
end;
end;
//Отрисовка верхней и нижней граней
img.Canvas.MoveTo(10,10);
img.Canvas.LineTo(10+l,10);
img.Canvas.MoveTo(10,10+h);
img.Canvas.LineTo(10+l,10+h);
//Перевод изображения из буфера
MyRect := Rect(0,0,Image1.ClientWidth,Image1.ClientHeight);
Image1.Canvas.StretchDraw(MyRect, Image1.Picture.Graphic);
Image1.Canvas.CopyRect(bounds(0,0,img.Width,img.Height),
img.Canvas,bounds(0,0,img.Width,img.Height));
end;


Без StretchDraw никак, а он не пашет...
TarasBer
Кто так сортировку пишет? У тебя она неправильно сортирует вообще.
Видимо, ты откуда-то переписал, причём очень небрежно и не глядя, что там происходит.

for i:=1 to 100 do
for j:=i+1 to 100 do

Дальше, а с чего StretchBlt будет работать, если у тебя и буфер, и область вывода, и прямоугольник, который ты выводишь - одного размера? Чему там и куда сжиматься?
И зачем ты копируешь из себя в себя?

> Image1.Canvas.StretchDraw(MyRect, Image1.Picture.Graphic);

Ты сам понимаешь, что ты написал?

Почему так нельзя?

MyRect := Rect(0,0,Image1.ClientWidth,Image1.ClientHeight);
Image1.Canvas.StretchDraw(MyRect, img);

Почему фигура у тебя выводится от 10, если должна рисоваться от середины буфера (от img.Width div 2)?

ar1[1,1]:=img.Width div 2; и так далее надо
RussoTuristo
Насчет изображения понял... Почему-то такие глобальные ошибки сам не замечаешь, путаясь в мелочах, я рисовал от кромки, а чтобы она не была вплотную, сделал отступ в 10 пикселей, переделаю, чтобы всё от середины плясало, поэтому в принципе и сжать-то невозможно было... Спасибо огромное, переделаю, напишу.

А по поводу цикла - это эксперимент был и он удался, если сделать как ты говоришь, то появляются какие-то левые 2 линии по бокам, даже не знаю откуда, но тоже попробую привести к человеческому виду. Еще раз спасибо, будем работать!
RussoTuristo
Помогите, пожалуйста, с удалением изображения, Img.Destroy напрочь отказывается работать, всё та же ошибка - Invalid Pointer Operation. По идее Create - Destroy, но что-то не так тут...
TarasBer
Create-Free, а не Create-Destroy.

Опять невнимательность!
RussoTuristo
Free тоже самое выдает, я пробовал....
TarasBer
Покажи, как ты этот Free вызываешь?
RussoTuristo
img.free; первым делом при нажатии кнопки...
Пробовал одновременно с этим буфер очищать, но тогда вообще ошибка сразу с нулями вылетает.
TarasBer
Ты создаёшь img при создании формы, а уничтожаешь при нажатии кнопки.
Где логика.
В OnDestroy деструкторы перенеси.
RussoTuristo
Форма-то заново не создается и не уничтожается, деструкторы походу оттуда не работают, поэтому и помещал их в кнопку, т.к. в момент нажатия они должны уничтожаться:

procedure TForm1.FormDestroy(Sender: TObject);
begin
buffer.Free;
img.Free;
end;

Без ошибок и без результатов.

и вопросик по поводу StretchDraw:

Моя логика, решил не строить от середины, почему-то не удобно:
Создаем в памяти изображение нужной ширины+50, и высоты+50: // 50 отведено на небольшие подписи
img.Width:=l+50;
buffer.Width:=l+50;
img.Height:=h+50;
buffer.Height:=h+50;

Рисуем на нём всё, что нужно
Создаем область необходимого размера(место, выделенное под фигуру на форме):
MyRect := Rect(0,0,250,450);

Вставляем в Image1 наше изображение, сжатое/растянутое до размеров этой области:
Image1.Canvas.StretchDraw(MyRect, Image1.Picture.Graphic);
Image1.Canvas.CopyRect(bounds(0,0,img.Width,img.Height),
img.Canvas,bounds(0,0,img.Width,img.Height));


По моей логике все нормально, но чувствую она далека от идеала.... Подскажите, пожалуйста, что делаю не так?
TarasBer
> Без ошибок и без результатов.

Какой результат тебе нужен?
Создаются они у тебя при создании формы, то есть 1 раз.
Значит, и удалять их надо 1 раз. То есть при уничтожении формы.

> Подскажите, пожалуйста, что делаю не так?

Ты всё делаешь не так.

> Image1.Canvas.StretchDraw(MyRect, Image1.Picture.Graphic);

Покажи мне в этой строчке слово img или buffer.

> Image1.Canvas.CopyRect(bounds(0,0,img.Width,img.Height),
img.Canvas,bounds(0,0,img.Width,img.Height));

Это что, это зачем? Зачем копировать ещё раз?
Ты сначала зачем-то вывел содержимое Image1 на себя со сжатием, а потом без сжатия туда же скопировал буфер.

Я же тебе сказал, как правильно выводить. А ты забил и сделал свою хрень неправильно.
У тебя полное непонимание того, что ты делаешь.
RussoTuristo
Цитата

Какой результат тебе нужен?

Чтобы при нажатии кнопки BitBtn1 старое изображение уничтожалось, а не при уничтожении формы

Цитата

Я же тебе сказал, как правильно выводить. А ты забил и сделал свою хрень неправильно.

> Image1.Canvas.StretchDraw(MyRect, Image1.Picture.Graphic);

Покажи мне в этой строчке слово img или buffer.

Stretchdraw ожидает в качестве параметра тип .Graphic, img.Canvas такого свойства не имеет, поэтому как туда вставить его я не знаю... в этом и проблема основная.

Вообще уже не знаю что делать, весь мозг сломал, помогите, пожалуйста, переделать.

TarasBer
> Чтобы при нажатии кнопки BitBtn1 старое изображение уничтожалось, а не при уничтожении формы

Хорошо. А создавать новое изображение тогда надо когда?

> Stretchdraw ожидает в качестве параметра тип .Graphic, img.Canvas такого свойства не имеет

Тебе нужен тип или свойство?
Я же тебе написал, как надо использовать StretchDraw! Ищи сам в этой теме.
RussoTuristo
Цитата

Image1.Canvas.StretchDraw(MyRect, Img);

Я так понимаю, речь идёт об этой строке, но изображение всё равно не сжимается, а часть его остается где-то за пределами....
Цитата

Хорошо. А создавать новое изображение тогда надо когда?

При нажатии кнопки первым делом удаляем старое, и строим новое. Делаю так, потому что форма не уничтожается в процессе работы.
TarasBer
> Я так понимаю, речь идёт об этой строке, но изображение всё равно не сжимается, а часть его остается где-то за пределами....

Да, об этой.
Она именно выводит то, что было в Img на форму. То, что там что-то за пределами - ну так что было в Img, то и вывелось. Можешь написать для контроля Img.SvaeToFile() и сравнить.

> При нажатии кнопки первым делом удаляем старое, и строим новое.

Что-то я не увидел, чтобы ты создавал новое при нажатии кнопки.
У тебя, видимо полное непонимание происходящего.

TBitmap.Create - это создание изображения для работы, если этого не сделать, то с ним ничего делать нельзя. Эта процедура соответствует доставанию нового листа бумаги из стола.
TBitmap.Free - это не стереть изображение ластиком с листа! Это выкинуть лист в мусорку, потому что тебе он больше не нужен. После Free делать с изображением ничего нельзя, поэтому его лучше пропиши в OnDestroy.

Всякие там рисования - это не создание нового листа, это рисование на текущем.
А для того, чтобы стереть изображение ластиком, делай так:


with Img.Canvas do begin
Brush.Style := bsSolid; // стиль заливки - заливать по полной
Brush.Color := clWhite; // цвет заливки - белый
Pen.Style := psClear; // линии не рисовать
Rectangle(0, 0, Width, Height); // нарисовать прямоугольник на всю область
end;


А потом, перед рисованием, не забудь обратно написать Pen.Style := psSolid; (а потом он линии рисовать не будет).
RussoTuristo
Вроде доработал все, изображение строится, сжимается/растягивается, но как-то иногда очень криво, что-то не прорисовывается, когда изображение большое - иногда целые линии не видны. Увеличил размер кисти, стало лучше, даже нормально, но это, наверное, не правильный способ.... Можно как-то по-другому это реализовать - улучшить качество?

И еще вопрос, добавил панель для расчетов, поместил Editы, туда ввожу значения, но при расчете вылетает ошибка: "EConverError with message "" is not a vali floating point value". Незаполненных Editов нету, странно...
Хотя типы должны совпадать:

Qn, Vlin,r:real;
tau:integer;

Procedure Init;
begin
Qn:=StrToFloat(Edit3.text);
Vlin:=StrToFloat(Edit4.Text);
tau:=StrToInt(Edit7.Text);
r:=Vlin*tau;
Edit8.text:=FloatToStr®;
end;
-TarasBer-
> о при расчете вылетает ошибка: "EConverError with message "" is not a vali floating point value".

Это не значит, что он не заполнен. Это значит, что его содержимое - не число. Кстати, в качестве разделителя нужна именно запятая (кажется).

> что-то не прорисовывается, когда изображение большое - иногда целые линии не видны

Функцию сжатия писал Микрософт. Видать, хреново написал. У меня тоже при сжатии вместо оттенков серого просто пропадают линии, даже если принудительно задать режим сжатия halftone .

> Можно как-то по-другому это реализовать - улучшить качество?

Да.
Изначально задать размер буфера, совпадающий с размером выводимого участко и при рисовании в буфер использовать только относительные координаты, никаких точных чисел.
То есть делать так:
w := Img.Width;
h := Img.Height;
...
LineTo(round(w * 0.1), round(h * 0.34));

(для первой координаты через w, для второй через h).
RussoTuristo
В поля text у Edit3, Edit4 и Edit7 введены значения 1380, 10 и 10 соответственно без запятых и без пробелов, поле для вывода - пустое.
Вообще когда добавил 2-ю панель она как не родная))) С первой панели из такого же Edita считывается, а эта панель вообще мёртвая почему-то.... Хотя они по сути идентичные.
-TarasBer-
> В поля text у Edit3, Edit4 и Edit7

Ты хоть сам помнишь, что они означают?
Возьми редактор свойств объектов и исправь им значение поля Name на нормальное.

Да, пустое поле тоже вызывает ошибку при попытке перевести в число.
Кстати, я в таких случаях делаю примерно так:


function ToFloat(E: TEdit): extended;
var
c: integer;
begin
val(E.Caption, Result, c);// пытаемся перевести чесло в строку
if c <> 0 then begin // если код ошибки не равен нулю
ShowMessage(E.Caption + " не число!!!");
E.SelectText(1, Length(E.Caption)); // как-то так, не помню, там вроде два свойства надо менять для выделения текста
end;
end;


RussoTuristo
http://delphi-manual.ru/edit.php А что с text не так? Я всегда так делал, да и в учебниках так написано.

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

Procedure Init;
begin
Edit3.text:='13800';
Edit4.text:='19';
Edit5.text:='0,015';
Edit6.text:='100';
Edit7.text:='10';
Qn:=StrToFloat(Edit3.text);
Vlin:=StrToFloat(Edit4.Text);
tau:=StrToInt(Edit7.Text);
r:=Vlin*tau;
Fn:=Pi*Vlin*Vlin*tau*tau;
Edit8.text:=FloatToStr®;
Edit9.text:=FloatToStr(Fn);
end;


Даже так не работает, когда вероятность попадания чего-то ненужного исключена.
volvo
Значит, где-то в обработчиках чего-то лишнего понавешал. На пустом проекте прекрасно отработала процедура Init. Прикрепляй свой проект целиком (только не надо EXE-шники и все временные файлы пихать, ладно? Скомпилировать я и сам могу, меня исходники интересуют)
RussoTuristo
Вот проект без ЕХЕшников:
Заранее спасибо.

volvo
OMG... blink.gif

А ничего, что Edit3 и Form1.Edit3 (и так далее) - это разные вещи? Убери напрочь этот свой "страшный Var" (у тебя ж сейчас все переменные, описанные там - NIL-ы, не инициализированные они), и сделай Init методом TForm1, тогда все будут всё видеть...

  TForm1 = class(TForm)
// тут ничего не меняй
private
{ Private declarations }
public
{ Public declarations }

procedure Init; // <--- Добавляешь прототип
end;

procedure TForm1.Init; // <--- Добавляешь Tform1.
begin
end;
RussoTuristo
Спасибо, уверен был, что там косяк, но не знал куда пихнуть метод Init в заголовочную часть....
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.