如何使自定义滚动条与图表中可见内容成比例?

huangapple go评论92阅读模式
英文:

How to keep a custom scrollbar proportional to the visible content in a graph?

问题

问题描述

我一直在开发一个自定义网格控件,其视口的大小恰好是1024像素,用于绘制信号点。请注意,完整的信号也正好包括1024个点。这意味着一个信号将占据整个网格的宽度。

我还可以对图形进行缩放,这会将信号点的数量乘以缩放因子。具体来说:

  1. const int SignalLength = 1024;
  2. int ZoomFactor = 2; // 用户更新
  3. int NewPoints = SignalLength * ZoomFactor;

我一直在尝试创建自定义的刷子/滚动条,以帮助浏览缩放的信号。然而,在维护滚动和可见内容的比例方面,我一直遇到问题。

可视化示例 [缩放因子:2]

如何使自定义滚动条与图表中可见内容成比例?

我已经处理的一些参数包括:

  • 滚动按钮:每个按钮的大小为50x50像素。

  • 可滚动区域:由于滚动按钮而减小。即Grid宽度 - (50*2)924个像素。

  • 刷子宽度:将始终为可滚动区域 / 缩放因子

请注意图像中的箭头,它显示信号的可见部分与刷子不同步。我猜想刷子移动得比网格实际显示得更快。

代码

  1. private void ZoomFactor_Changed(object sender, EventArgs e)
  2. {
  3. if (ZoomFactor > 1)
  4. {
  5. Scrubber.Width = (ScrubberTrackPanel.Width / ZoomFactor);
  6. ScrubberWidth.Text = Scrubber.Width.ToString();
  7. ScrubberTrackPanel.Visible = true;
  8. }
  9. else
  10. {
  11. ScrubberTrackPanel.Visible = false;
  12. Scrubber.Width = Scrubber.Parent.Width;
  13. }
  14. }
  15. private void SfBtn_GridScrollRight_MouseDown(object sender, MouseEventArgs e)
  16. {
  17. // 左右两个按钮的标签属性都具有步进值。
  18. // 左侧为-2
  19. // 右侧为2
  20. GlobalVars.GridScrubStepSize = 0 + int.Parse((SfButton)sender).Tag.ToString());
  21. GridScrubberTimer.Start();
  22. }
  23. private void GridScrubberTimer_Tick(object sender, EventArgs e)
  24. {
  25. ScrollGrid(GlobalVars.GridScrubStepSize);
  26. }
  27. private void ScrollGrid(int StepSize)
  28. {
  29. var newStepPos = GlobalVars.ZoomedSignalLeft + StepSize;
  30. // 如果到达图的边界(左/右)之一,停止滚动定时器。
  31. if (newStepPos <= 0 || newStepPos >= 1024 * ZoomFactor && GridScrubberTimer.Enabled)
  32. {
  33. GridScrubberTimer.Stop();
  34. return;
  35. }
  36. var ZoomedSignalSlice = GlobalVars.ZoomedSignal.Skip(newStepPos).Take(1024).ToList();
  37. if (ZoomedSignalSlice.Count == 1024)
  38. {
  39. GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrubStepSize;
  40. if (ScrubberTrackPanel.Visible)
  41. {
  42. Scrubber.Location = new Point(Scrubber.Location.X + (int)Math.Floor(GlobalVars.GridScrubStepSize/ (float)ZoomFactor), 0);
  43. ScrubberCords.Text = Scrubber.Location.ToString();
  44. }
  45. GraphGrid.Refresh();
  46. }
  47. }

尝试的解决方案

我尝试了如何计算滚动条拇指的大小https://stackoverflow.com/questions/22035363/formula-for-content-step-of-scrollbar,但不知何故,我无法正确把握比例。

我确定自己漏掉了一些非常明显的(并且愚蠢的:p)东西,您将在其中提供指导。
1: https://i.stack.imgur.com/mBGwO.png
2: https://stackoverflow.com/questions/16366795/how-to-calculate-the-size-of-scroll-bar-thumb
3: https://stackoverflow.com/questions/22035363/formula-for-content-step-of-scrollbar

英文:

Problem Statement

I've been working on a custom grid control whose viewport is exactly of size 1024 pixels which is used to plot signal points. Note that a complete signal also consist of exactly 1024 points. This means that one signal spread to the whole width of the grid.

I can also zoom into the graph which increases the Signal points times ZoomFactor. which is:

  1. ...
  2. const int SignalLength = 1024;
  3. int ZoomFactor = 2; //Updated by user
  4. int NewPoints = SignalLength * ZoomFactor;
  5. ...

I've been trying to create custom scrubber/scroller which helps in scrolling through a zoomed signal. However, I've been facing issues during maintaining the proportions of scroll and visible content in sync.


Visual Example [ZoomFactor: 2]

如何使自定义滚动条与图表中可见内容成比例?

A few parameters that I've worked are:

  • Scroll Buttons : Each of Size 50x50 pixels

  • Scrollable Area: Which reduces due to Scroll buttons. That is Grid Width - (50*2): 924 pixels.

  • Scrubber Width : Which will always be Scrollable Area / ZoomFactor

Notice the arrows in image which shows the visible section of signal is not in sync with the scrubber. I guess the scrubber is moving too fast than what the grid is actually showing.


Code

  1. private void ZoomFactor_Changed(object sender, EventArgs e)
  2. {
  3. if (ZoomFactor &gt; 1)
  4. {
  5. Scrubber.Width = (ScrubberTrackPanel.Width / ZoomFactor);
  6. ScrubberWidth.Text = Scrubber.Width.ToString();
  7. ScrubberTrackPanel.Visible = true;
  8. }
  9. else
  10. {
  11. ScrubberTrackPanel.Visible = false;
  12. Scrubber.Width = Scrubber.Parent.Width;
  13. }
  14. }
  15. private void SfBtn_GridScrollRight_MouseDown(object sender, MouseEventArgs e)
  16. {
  17. // Both left and right button&#39;s tag property have the step value.
  18. // Left has -2
  19. // Right has 2
  20. GlobalVars.GridScrubStepSize = 0 + int.Parse((SfButton)sender).Tag.ToString());
  21. GridScrubberTimer.Start();
  22. }
  23. private void GridScrubberTimer_Tick(object sender, EventArgs e)
  24. {
  25. ScrollGrid(GlobalVars.GridScrubStepSize);
  26. }
  27. private void ScrollGrid(int StepSize)
  28. {
  29. var newStepPos = GlobalVars.ZoomedSignalLeft + StepSize;
  30. //To stop scroll timer if any of the boundry (left/right) of graph is reached.
  31. if (newStepPos &lt;= 0 || newStepPos &gt;= 1024 * ZoomFactor &amp;&amp; GridScrubberTimer.Enabled)
  32. {
  33. GridScrubberTimer.Stop();
  34. return;
  35. }
  36. var ZoomedSignalSlice = GlobalVars.ZoomedSignal.Skip(newStepPos).Take(1024).ToList();
  37. if (ZoomedSignalSlice.Count == 1024)
  38. {
  39. GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrubStepSize;
  40. if (ScrubberTrackPanel.Visible)
  41. {
  42. Scrubber.Location = new Point(Scrubber.Location.X + (int)Math.Floor(GlobalVars.GridScrubStepSize/ (float)ZoomFactor), 0);
  43. ScrubberCords.Text = Scrubber.Location.ToString();
  44. }
  45. GraphGrid.Refresh();
  46. }
  47. }

Tried Solutions

I've tried How to calculate the size of scroll bar thumb and https://stackoverflow.com/questions/22035363/formula-for-content-step-of-scrollbar but somehow I'm not able to grasp the proportions correctly.

I'm sure I'm missing something very obvious (&& stupid :p) thing which you will shed light on.

答案1

得分: 1

在经过数小时的代码调试后,我意识到位置计算完全错误。在修复后,滚动功能按预期工作,并适当地保持了比例。

以下是正确的代码:

  1. ...
  2. GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrollStepSize;
  3. // 将可见信号在网格上的当前起始位置映射到ScrollerTrackPanel范围内,然后除以ZoomFactor以获得在网格上可见信号图像上刮板位置与可见信号的比例位置。
  4. int newx = (int)Math.Floor(GlobalVars.ZoomedSignalLeft / 1024F * ScrollerTrackPanel.Width / ZoomFactor);
  5. Scrubber.Location = new Point(newx, 0);
  6. ...
英文:

After tinkering a lot with the code for hours I realized the calculation for the location was very wrong. After fixing it, the scroll is working as expected while maintaining the proportions appropriately.

Below is the correct code:

  1. ...
  2. GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrollStepSize;
  3. // Mapping the current beginning position of the visible signal on the grid in the range of ScrollerTrackPanel and then dividing
  4. // it with the ZoomFactor To get location of scrubber over the signal image proportional to the visible signal on the grid.
  5. int newx = (int)Math.Floor(GlobalVars.ZoomedSignalLeft / 1024F * ScrollerTrackPanel.Width / ZoomFactor);
  6. Scrubber.Location = new Point(newx, 0);
  7. ...

huangapple
  • 本文由 发表于 2023年3月1日 14:37:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75600277.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定