Window.Width / 7 = Imprecise Result

Hi, I’m coding a simple calendar based on 7 days displayed at time.

To achieve the result you see here I just implemented SimpleDraw 2018 but I’m getting a really frustrating issue cause my

DayBox.Width = ObjectClass.Width = Window.Width / 7

gives not a precise result while rendering the screen. Sometimes it does sometimes it doesen’t.

I also tried using DOUBLE values rather than ITEGER ones but nothing.

Somebody with a higher exp than me may be able to tell me if the “frustrating gap” it can be resolved.

Thanks you all for reading and solving.

I can’t really see anything on the screenshot. But it’s easy to understand why you have a gap.

Let’s make a simple example: you want to paint 2 columns 100 pixels wide. But your window is 205 pixels wide. You will get a gap of 5 pixels. You either need to make the second column 105 pixels or you need to distribute the 5 pixels to both columns.

1 Like

Actually I think your exemplification not correct, not at all at least.

I’m not tring to fill the Total.Width with a fixed Width but I’m using that width to calculate the exact width of each subdivision.

The process it’s reversed and I’d expect that TotalX / 7 x 7 gives a exact result.

That’s math.

Hi Andres, welcome to Xojo!

Likely you’re seeing a gap because in the division of your Window width by 7, you’re probably getting a decimal portion as a result, e.g., 120.65. And the width or height of Xojo objects typically only accept Integer (whole number) values. Which means any decimal portion of the number is either truncated or rounded incorrectly. So when you add up the width of all the “DayBox” objects, the total is less than the actual width of the window. Thus, the gap.

Others may recommend solving this sort of issue using a different approach, but if this was me, I might try the following bit of code:

Var w As Int32 = Floor(Window.Width / 7) // round down to a whole number
DayBox1.Width = w
DayBox2.Width = w
DayBox3.Width = w
DayBox4.Width = w
DayBox5.Width = w
DayBox6.Width = w
DayBox7.Width = w + (Window.Width - (w * 7))

The width of the last DayBox will be slightly wider than it’s siblings, which should make up the gap you’re seeing. Of course you could add the left-over portion to a different DayBox, it doesn’t have to be the last one. That’s up to you.

I hope this helps.

1 Like

Very well explained Scott, thank you very much.

This also explains why using DOUBLE values instead of ITEGER ones does not have impact on this graphic error at all.

Unfortunately this wont solve my problem so I will not mark your answer as Solution.

I hope for a Next Xojo version, with Objects Accepting Double values for advaced graphic features.

Didn’t I say the same thing? Why does that not solve your problem? What IS the problem?

What do you hope?

Sorry Beatrix, this is very subtle, the only premise that makes the difference between yours and Scott’s answer is that

Xojo objects cannot manage double values for graphic operations.

The Rounding Off is the real issue I guess.

If my target is 18px I may accept 17.8px (=18px) but not 17px (=18px).

So once again:

I hope for a Next Xojo version, with objects

=> Accepting Double values for advaced graphic features.

You did Beatrix. Sorry, I didn’t see your post while I was writing mine.

1 Like

Well, I think it does. But what you might find is that the use of Doubles with Graphic object dimensions and positioning may not align with the pixel density of your monitor. For example, if you’re using a non-retina display (Scale Factor 1.0), you can draw a line that is 1.5 pixels thick (but it won’t look like it). Which is why I usually round any graphic dimension to a whole number and treat the math as Integers to get a sharper look to things, even on a Retina display.

Edited: If you want to make your graphics ultra-sharp on a Retina display, you may need to use the current ScaleFactor in your math, so your output matches what the current display will produce.

2 Likes

That’s perfectly clear now, but also a notable peculiarity the fact that objects cannot directly “string” decimals.

If I’m not wrong a Xojo object can handle the decimal value but not in real time, using a Property as to store the “preference about grade of approximation” to be used along for ***next graphic operations.

Why not to set it at the max by default?

I’m hoping for a car that runs on grass cuttings.

Xojo doesnt work on decimals (yet) and you may wait a long time for it to happen.
I offer 3 further refinements to the solution above , however:

if you have 7 columns and the width of the window does not divide by 7 to integers:

1/ change the window size so that it does, or
2/ add a small border left and right to account for the extra pixels
3/ add a pixel to some of the columns, not just the one at the end. For example, if you have 4 spare pixels, make 4 of the columns 1 pixel wider, instead of the last one 4 pixels wider.

2 Likes

1/ My same idea.

Setted the start Window.Width from 1250 to 1246 and a totally

Renewed wish for the year to come…

! Nobody gonna resize that window !

:rofl:

You can make it resizable or not in the IDE.
And you can set min and max widths to be the same

Sure Jeff, definitely not the kind of pro solution I’d expect in 2021 but thank you all for your time anyway!

From a quick look at SimpleDraw 2018 it seemingly uses realbasic.rect which don’t support doubles. Xojo switched over to doubles for all drawing routines a while back (with the introduction of Rect) and it would seem that the SimpleDraw 2018 library you’re using is the issue here which will be causing the rounding issue you’re getting. As you will probably encounter numerous issues with scaled desktops in the future which rely on decimal placements you might want to refactor the library to use doubles throughout or switch away from that library.

1 Like

Can’t you use a more recent version ?

Nota: I have only 2021 Xojos versions on this M1 MBP, and this example does not exists. This may be a clue…

Thank you Julian, that’s good to know, unfortunately SimpleDraw 2018 is the only version I’ve been able to get. If I just need to change the realbasic.rect to Rect I think I can just do it by myself, should be an easy work to modifying this few lines:

Dim NewRectangle As New Realbasic.Rect(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height)

NewRectangle.Left = NewRectangle.Left + xDelta
NewRectangle.Top = NewRectangle.Top + yDelta

Return NewRectangle

However here my result, creating an ObjectClass for each 23 hours of 7 days, I don’t have implemented any Db fetch yet but still very slow.

Probably it’s me cause I’m using a code loop to create each single HourObjectClass. Any suggestion sbout it’s really appreciated.

  • Found my problem was I forget to remove Refresh after each New Object.

Clean & Smooth now.

The correct way to handle this is to spread the remainder out over the columns.

// Window Width is 1200 in this example
Var ColumnWidth As Integer = Floor(Self.Width / 7) // 171
Var Remainder As Integer = Self.Width - (ColumnWidth * 7) // 3
For ColumnNumber As Integer = 1 To 7
  Var ActualColumnWidth As Integer = ColumnWidth
  If ColumnNumber <= Remainder Then
    ActualColumnWidth = ActualColumnWidth + 1 // 172 for columns 1-3. 171 for columns 4-7.
  End If
Next ColumnNumber

There are ways you could compact the logic a little, such as using an inline if statement to compute the individual column widths. I made this code intentionally verbose for the same of demonstration.

This way every column looks exactly the same width to the eye, but they aren’t really.

1 Like

Thank you Thom, your interest is really appreciated, I yet figured out such a kind of solution even if I think an automatic rounding system based on double values to >absolute destination values< should be considered to be implemented too.

  • Conceptually thinking