2017-02-13 20 views
0

Я столкнулся с небольшой проблемой.
Представьте себе две вещи: форму, которая должна быть покрыта - обложка; и формы, которые будут охватывать Cover-Form-Tiles. Моя главная цель - покрыть мою обложку с черепицей. Так что это будет похоже на плитки. Я проиллюстрирую эту идею изображением ниже
enter image description here
Желтый цвет - обложка, коричневые формы - Плитка. На этом изображении вы можете видеть, что формы расположены слишком близко друг к другу - между ними нет свободного пространства. Это то что мне нужно.
Но когда я пытаюсь достичь такого же эффекта, я получаю неудовлетворительный результат. Он представлен на рисунке ниже
enter image description here
Второе изображение имеет смещение после последней плитки. Это происходит из-за разного размера формы. Я не знаю точно, какую ширину у меня будет иметь Cover-Form. Я просто разделяю всю ширину Cover-Form на три части. Но если Cover-Form имеет ширину, например, 173 пикселя, каждая из моих Tiles будет иметь ширину равной 173/3 = 57,6 пикселя, которая будет круглой до 58, но 58 * 3 = 174, и это плохо.Ошибки в расчетах позиций форм в Delphi

Код ниже работает как на втором изображении.

type 
    TTileArray = Array of Array of TPoint; 

// This routine comes here from David's answer below and were changed by me 
procedure EvenlySpacedTiles(PixelCountH, PixelCountV, TileCount: Integer; var ArrayOut: TTileArray); 
var 
    X: Integer; 
    Y: Integer; 
    OldH: Integer; 
    OldV: Integer; 
    OldCount: Integer; 
    OldCount1: Integer; 
    TempInt: Integer; 
begin 
    if (PixelCountH) or (PixelCountV) or(TileCount) = 0 then 
    Exit; 

    OldH := PixelCountH; 
    OldCount1 := TileCount; 
    for X:=Low(ArrayOut) to High(ArrayOut) do 
    begin 
     OldV := PixelCountV; 
     OldCount := TileCount; 

     TempInt := OldH div OldCount1; 
     Dec(OldH, TempInt); 
     Dec(OldCount1); 
     for Y:=Low(ArrayOut) to High(ArrayOut) do 
     begin 
      ArrayOut[X, Y] := Point(TempInt, OldV div OldCount); 
      Dec(OldV, ArrayOut[X, Y].Y); 
      Dec(OldCount); 
     end; 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    F: TForm; 
    P: TForm; 
    Delta: Integer; 
    PrevLeft: Integer; 
    PrevTop: Integer; 
    X:Integer; 
    Y: Integer; 
    Arr: TTileArray; 
    IncLeft: Integer; 
begin 
    Delta := 3; 

    F := TForm.Create(Application); 
    F.BorderStyle := Forms.bsNone; 
    F.SetBounds(0, 0, 173, 115); 
    F.Position := poDesktopCenter; 
    F.Color := $11DFEE; 
    F.Show; 

    SetLength(Arr, Delta, Delta); 
    EvenlySpacedTiles(F.Width, F.Height, Delta, Arr); 
    PrevLeft := F.Left; 
    PrevTop := F.Top; 
    IncLeft := 0; 
    for X:=Low(Arr) to High(Arr) do 
    begin 
     PrevTop := F.Top; 
     Inc(PrevLeft, IncLeft); 
     for Y:=Low(Arr) to High(Arr) do 
     begin 
      P := TForm.Create(Application); 
      P.FormStyle := fsStayOnTop; 
      P.BorderStyle := Forms.bsNone; 
      P.Color := Random($FFFFFF);//clSkyBlue; 
      P.Show; 
      P.Width := Arr[X, Y].X; 
      P.Height := Arr[X, Y].Y; 
      P.Left := PrevLeft; 
      P.Top := PrevTop; 
      P.Canvas.Rectangle(P.ClientRect); 
      Inc(PrevTop, Arr[X, Y].y); 
      IncLeft := Arr[X, Y].X; 
     end; 
    end; 
end; 

Так что мой вопрос: как я могу регулировать ширину всех плитки (3 для каждой строки) независимо от ширины чехле формы в?

Заранее спасибо.

Edited

P.S. Я модифицировал некоторые части кода выше. Теперь он отлично работает даже с чрезвычайно маленькой и большой шириной Cover-Form - от 67 px. до 1237 px. Конечно, есть способ улучшить этот код, но главная цель достигнута. Я думаю, что смогу закончить вертикальное размещение плиток завтра и опубликовать эту часть там.
Во многом комментарий Дэвида дает мне представление о том, как это сделать. Спасибо, Дэвид!

P.S.S.
Я прочитал первый комментарий Дэвида по диагонали, поэтому я обновляю код для работы по-другому, но результат все еще не очень хорош. Вы можете увидеть это на картинке ниже.
Первая плитка имеет 57 px. ширина; второй - 59 px .; третья плитка - всего 31 px.
Я просто не могу понять, как правильно разместить плитки, используя алгоритм, предложенный в комментарии Дэвида. enter image description here

P.S.S.S.
И снова нет результата.
enter image description here
Правая красная линия демонстрирует большой размер последней плитки. Каждая плитка имеет ширину 58 пикселей.
David написал (а):

173/3 = 58. 173-58 = 115. 115/2 = 58. 115-58 = 57. 57/1 = 57

Я могу рассчитать его в реальной жизни, но я не могу его реализовать в коде.
Исходный код обновлен.

P.S.S.S.S.
Процедура Дэвида не делает то, что он должен делать. Рисунок ниже иллюстрирует это.
enter image description here
Промежуток между первой и второй плиточками и красная линия с правой стороны, как на предыдущем рисунке.

P.S.S.S.S.S.
Ну, в это время первая часть моей задачи выполнена. Второй - добавляет больше плиток, но я не уверен, действительно ли они им нужны. И я благодарен за это David Heffernan !! Он тратит так много времени, чтобы объяснить мне некоторые вещи, и я не знаю, как сказать ему больше, чем просто «Большое спасибо». Я боюсь, я могу просто увеличить его репутацию и принять его пост в качестве ответа. Это действительно делает работу! На фото мы можем увидеть результат мне нужен
enter image description here

P.S.S.S.S.S.S.
Я обновил исходный код, чтобы он мог разместить плитки и вертикально.
enter image description here

+1

173 не точно делится на 3. Ergo, вы не можете использовать одну и ту же ширину для каждого столбца. Вместо этого сделайте это так. Начните с пикселов Npx. Разделите Ncol, округлите. Используйте это значение для столбца 0. Вычтите это значение из Npx и теперь разделите на Ncol-1. Завершите это значение и используйте для столбца 1. Повторите, пока вы не исчерпали пиксели и столбцы. –

+0

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

+0

@DavidHeffernan, вы имеете в виду следующую ситуацию, верно? Предположим, у меня есть Cover-Form с шириной 173 пикселя. Я знаю, что я должен разместить три плитки в строке, поэтому я разделяю 173/3 = 57. Это ширина каждой плитки. Затем я умножаю 3 плитки на 57 и получаю 171. Я знаю, что 171 меньше 173, и в соответствии с этим я должен сделать это: 173 - 171 = 2. Это место размера после последнего Плитка, которое представлено на втором изображение, поэтому я просто увеличиваю ширину последнего TIle, чтобы полностью соответствовать Cover-Form. Что вы думаете об этом методе? – Dima

ответ

2

Я хотел бы использовать простой алгоритм, как это:

function EvenlySpacedColumns(PixelCount, ColumnCount: Integer): TArray<Integer>; 
var 
    i: Integer; 
begin 
    Assert(PixelCount>0); 
    Assert(ColumnCount>0); 
    SetLength(Result, ColumnCount); 
    for i := low(Result) to high(Result) do begin 
    Result[i] := PixelCount div ColumnCount; 
    dec(PixelCount, Result[i]); 
    dec(ColumnCount); 
    end; 
end; 

Здесь я использую div, который фактически использует разделение с последующим усечением. Но вы могли бы использовать Round(PixelCount/ColumnCount), если хотите. Это несколько произвольно, поэтому я лично предпочел бы целочисленную арифметику на том основании, что следует избегать арифметики с плавающей запятой, если это не необходимо.

+0

это хороший фрагмент кода, но он не работает. Может, я сделал что-то не так? Пожалуйста, повторите мой вопрос, я добавил некоторую информацию. – Dima

+0

Код работает нормально. Вы используете его неправильно. 'EvenlySpacedColumns (173, 3)' дает '(57, 58, 58)'. Сумма этих трех значений составляет '173'. Как вы вписываете это в свой код, это ваша проблема. Я призываю вас приложить все усилия. Кажется, вы перестали думать о своей проблеме. –

+0

Задайте себе, что делает P.SetBounds (F.Left + Arr [i] * i, F.Top, Arr [i], Round (h)) '. Почему, почему вы используете 'Arr [i] * i'? !!! Конечно, я мог бы написать ваш код для вас, но в чем бы дело. Не сдавайся. Не объявляйте, что «мой код не работает». Проблема с вами. Ответ можно найти в зеркале. Очень просто продемонстрировать, что представленный мной код делает то, что предназначено. Теперь вам просто нужно выяснить, как правильно выложить свои элементы управления. Думать! –

 Смежные вопросы

  • Нет связанных вопросов^_^