Задача такова: Написать программу построения чертежей планиметрии "протягиванием" от выбранной точки с изображением ее промежуточного положения с возможностью обозначения точек и проведения стандартных линий в треугольнике. Как это сделать я впринципе знаю но есть 1 проблема это работа с указателем мыши.Для начала я попытался сделать так чтобы при нажатии на изображение рисовалась линия из текущего положения курсора в положение указателя мыши
procedure TForm1.Image1Click(Sender: TObject); var Mo: TMouse; MX, MY: integer; begin MX := Mo.CursorPos.X; MY := Mo.CursorPos.Y; image1.canvas.LineTo(mx,my); end;
получается чето не то линия проводится явно не к указателю мыши.Может это связано с масштабом Image1 (833x533)?подскажите.И еще какие свойства в Tmouse отвечают за нажатые кнопки мыши?
Это связано с тем, что Mouse.CursorPos хранит информацию в экранных координатах (глобальных), а тебе надо клиентские. Вот работающий код через OnClick:
procedure TForm1.Image1Click(Sender: TObject); var p: TPoint; begin p := Point(Mouse.CursorPos.X, Mouse.CursorPos.Y); // Берем координаты p := Image1.ScreenToClient(p); // преобразуем их в локальные Image1.Canvas.LineTo(p.X, p.Y); // отображаем end;
блин чето не получается сделать протягивание с изображением промежуточного положения.Алгоритм должен быть примерно таким: рисуем новую линию с координатами указателя мыши старую линию стираем и так до тех пор пока не нажмем кнопку.Я попробовал для начала так
procedure TForm1.Image1Click(Sender: TObject); var p: TPoint; begin while true do begin p := Point(Mouse.CursorPos.X, Mouse.CursorPos.Y); p := Image1.ScreenToClient(p); Image1.Canvas.lineto(p.X, p.Y); end; end;
думал что линия будет постоянно следовать за указателем но это никак не работает.
Тебе надо отрисовывать не по OnClick, а по OnMouseDown "захватывать" мышь, по OnMouseMove - перемещать линию, до тех пор, пока не произойдет OnMouseUp (при котором мышь "освобождается")...
Тебе надо отрисовывать не по OnClick, а по OnMouseDown "захватывать" мышь, по OnMouseMove - перемещать линию, до тех пор, пока не произойдет OnMouseUp (при котором мышь "освобождается")...
А как можно сделать чтоб при 1ом нажатии накнопку мыши линия прекращалась и от точки ее завершения сразуже тянулясь новая линия(ну это я сделал), а при двойном нажатии на кнопку линия прекращается мыш полностью от нее отвязывается и можно тянуть новую линию совершенно не связанную с предыдущей?
1. Ввести состояние (см.конечные автоматы) и отслеживать двойной щелчок. 2. Рисовать ручками, проверяя, что та точка, которую ты хочешь закрасить, содержит цвет фона, а не линии.
Чтото не совсем понимаю как это реализовать можно пояснить?
Рисуешь линию по точкам (например, алгоритмом Брезенхема), проверяя при этом, какого цвета точка, которую ты хочешь закрасить. Если цвета фона - рисуешь, если другого цвета - пропускаешь.
Рисуешь линию по точкам (например, алгоритмом Брезенхема), проверяя при этом, какого цвета точка, которую ты хочешь закрасить. Если цвета фона - рисуешь, если другого цвета - пропускаешь.
Эх теперь возникла новая проблема(линии я рисую по пикселям) когда я вытягиваю линию и хочу ее завершить она не остается а закрашивается белым.Почему это происходит я понимаю а вот избежать этого никак не выходит
procedure DrawLine4Connected(x1,y1,x2,y2 : Integer;col:tcolor); var x, y, dx, dy, sx, sy, z, e, i : Integer; Ch : Boolean; begin x := x1; y := y1; dx := Abs(x2-x1); dy := Abs(y2-y1); If x2-x1>0 then sx:=1 else sx:=-1; If y2-y1>0 then sy:=1 else sy:=-1; e := 2*dy-dx; Ch:=dy>=dx; if Ch then begin z := dx; dx := dy; dy := z; end; i := 1; repeat image1.Canvas.Pixels[x, y]:=col; if e<dx then begin if Ch then y := y+sy else x := x+sx; e := e+2*dy; end else begin if Ch then x := x+sx else y := y+sy; e := e-2*dx; end; i := i+1; until i>dx+dy; image1.Canvas.Pixels[x, y]:=col;
end;
var p: TPoint; begin p := Point(Mouse.CursorPos.X, Mouse.CursorPos.Y); p := Image1.ScreenToClient(p); DrawLine4Connected(pfx,pfy,px,py ,clwhite);{закрашиваю предыдущюю линию} {Image1.Canvas.lineto(fx,fy);} if cl=true then begin
Вот тут я и двигаю линию она должна завершатся при событии Image1Click и если при этом она закрашивает линию белым значит почемуто обрабатывается и Image1MouseMove?Что подправить чтоб заработало?
Ты по-русски напиши, чего хочешь добиться, что для этого делаешь, что получаешь и чем то, что получаешь, отличается от того, что хочешь. Вполне вероятно этого уже окажется достаточным для того, чтобы найти ошибку.
Из того, что я вижу в коде: у тебя ВСЕГДА рисуется белым (подозреваю, так ты стираешь), но НЕ ВСЕГДА - черным. При таком способе рисования, естественно, белых линий и будет рисоваться больше, чем черных. Могу повторить свой совет: ввести дополнительную переменную состояния и сделать конечный автомат.
Ты по-русски напиши, чего хочешь добиться, что для этого делаешь, что получаешь и чем то, что получаешь, отличается от того, что хочешь. Вполне вероятно этого уже окажется достаточным для того, чтобы найти ошибку.
Из того, что я вижу в коде: у тебя ВСЕГДА рисуется белым (подозреваю, так ты стираешь), но НЕ ВСЕГДА - черным. При таком способе рисования, естественно, белых линий и будет рисоваться больше, чем черных. Могу повторить свой совет: ввести дополнительную переменную состояния и сделать конечный автомат.
Если по русски то вот чего я хочу: кликаю мышуой по изображению(1 раз) фиксируется точка перемещаю мыш линия от этой точки тянется за указателем мыши кликаю опять по изображению (1раз) линия завершается но мыш не освобождается (те от точки завершения старой линии тянется новая) рисую очередную линию и кликаю по изображению (2раза) линия завершается и мыш освобождается полностью(те можно проводить новую линию не связанную с предыдущим изображением).Ну вот вобщем и все работает все токо ничего невидно ( линии закрашиваются белым).Я понимаю что нужно ввести новую переменную состояния но не понимаю где изменять условие ее истинности?
Сэр знаком с таким знаком препинания как запятая? Очень тяжело читать. Если ты и программы так же пишешь, не удивляюсь, почему они не работают.
Значит, вводим состояния: 0. Неопределенное состояние - на всякий случай: если вдруг переменная примет это значение, будем знать, что где-то эта переменная портится. 1. "свободная мышь" - нигде ничего не рисуем. 2. нажата кнопка мыши. 3. мышь "тянет линию". 4. таймаут после двойного щелчка (кто знает, сколько сообщений о нажатии/отпускании мыши мы получим во время двойного щелчка - чтобы они нам не мешали)
Мышь находится в одном из приведенных состояний, в начале - "1". Мы отслеживаем сообщения: A - перемещение мыши, B - нажатие мыши, C - отпускание мыши, D - двойной щелчок.
В зависимости от того, в каком состоянии мы находились, получая то или иное сообщение, мы выполняем определенное действие (в частном случае - ничего не делаем) и переходим в другое состояние.
Осталось расписать таблицу переходов и записать ее на любимом ЯВУ. Например, для 1: 1A - ничего не делаем, 1B - переходим в режим 2, 1C - невозможная комбинация - сообщаем об ошибке, 1D - ничего не делаем.
для 2: 2A - стираем старую линию и рисуем новую, 2B - невозможная комбинация - сообщаем об ошибке, 2C - переходим в режим 3, 2D - переходим в режим 4.
для 3: 3A - стираем старую линию и рисуем новую, 3B - отрисованную линию оставляем и запоминаем точку нажаия новой линии, 3C - переходим в режим 2, 3D - переходим в режим 4.
для 4: 4A - ничего не делаем, проверяем, не вышел ли таймаут, если вышел, переходим в состояние 1, 4B - ничего не делаем, проверяем, не вышел ли таймаут, если вышел, переходим в состояние 1, 4C - ничего не делаем, проверяем, не вышел ли таймаут, если вышел, переходим в состояние 1, 4D - возобновляем таймаут.
PS. Писал особенно не продумывая, просто для иллюстрации.
Сэр знаком с таким знаком препинания как запятая? Очень тяжело читать. Если ты и программы так же пишешь, не удивляюсь, почему они не работают.
Значит, вводим состояния: 0. Неопределенное состояние - на всякий случай: если вдруг переменная примет это значение, будем знать, что где-то эта переменная портится. 1. "свободная мышь" - нигде ничего не рисуем. 2. нажата кнопка мыши. 3. мышь "тянет линию". 4. таймаут после двойного щелчка (кто знает, сколько сообщений о нажатии/отпускании мыши мы получим во время двойного щелчка - чтобы они нам не мешали)
Мышь находится в одном из приведенных состояний, в начале - "1". Мы отслеживаем сообщения: A - перемещение мыши, B - нажатие мыши, C - отпускание мыши, D - двойной щелчок.
В зависимости от того, в каком состоянии мы находились, получая то или иное сообщение, мы выполняем определенное действие (в частном случае - ничего не делаем) и переходим в другое состояние.
Осталось расписать таблицу переходов и записать ее на любимом ЯВУ. Например, для 1: 1A - ничего не делаем, 1B - переходим в режим 2, 1C - невозможная комбинация - сообщаем об ошибке, 1D - ничего не делаем.
для 2: 2A - стираем старую линию и рисуем новую, 2B - невозможная комбинация - сообщаем об ошибке, 2C - переходим в режим 3, 2D - переходим в режим 4.
для 3: 3A - стираем старую линию и рисуем новую, 3B - отрисованную линию оставляем и запоминаем точку нажаия новой линии, 3C - переходим в режим 2, 3D - переходим в режим 4.
для 4: 4A - ничего не делаем, проверяем, не вышел ли таймаут, если вышел, переходим в состояние 1, 4B - ничего не делаем, проверяем, не вышел ли таймаут, если вышел, переходим в состояние 1, 4C - ничего не делаем, проверяем, не вышел ли таймаут, если вышел, переходим в состояние 1, 4D - возобновляем таймаут.
PS. Писал особенно не продумывая, просто для иллюстрации.
Спасибо огромное Теперь вроде все наладил.Остался последний глупый вопрос как узнать какого цвета пиксель
procedure DrawLine4Connected(x1,y1,x2,y2 : Integer;col:tcolor); var x, y, dx, dy, sx, sy, z, e, i : Integer; Ch,cl : Boolean; begin x := x1; y := y1; dx := Abs(x2-x1); dy := Abs(y2-y1); If x2-x1>0 then sx:=1 else sx:=-1; If y2-y1>0 then sy:=1 else sy:=-1; e := 2*dy-dx; Ch:=dy>=dx; if Ch then begin z := dx; dx := dy; dy := z; end; i := 1; repeat if image1.Canvas.Pixels[x, y]=clblack then cl:=true else cl:=false; if cl=false then image1.Canvas.Pixels[x, y]:=col; if e<dx then begin if Ch then y := y+sy else x := x+sx; e := e+2*dy; end else begin if Ch then x := x+sx else y := y+sy; e := e-2*dx; end; i := i+1; until i>dx+dy; { if image1.Canvas.Pixels[x, y]=clblack then cl:=true else cl:=false; if cl=false then } image1.Canvas.Pixels[x, y]:=col;
end;
Я пытаюсь добится чтоб линия белого цвета не затирала линию черного цвета.Ну с алгоритмом все ясно если цвет пикселя фона отличен от цвета фона то не рисуем пиксель иначе рисуем.Таквот вся проблема в том как узнать какого цвета пиксель на фоне я попробовал так
if image1.Canvas.Pixels[x, y]=clblack then{вот тут я пытаюсь узнать цвет пикселя фона (видимо не верно)} cl:=true else cl:=false; if cl=false then{тут если пиксель на фоне не черный рисуем точку} image1.Canvas.Pixels[x, y]:=col;
Видимо if image1.Canvas.Pixels[x, y]=clblack тут проверяется не цвет пикселя фона а цвет того который я нарисовал до этого?Как правильно узнать цвет пикселя на фоне?