英文:
How to keep a custom scrollbar proportional to the visible content in a graph?
问题
问题描述
我一直在开发一个自定义网格控件,其视口的大小恰好是1024个像素,用于绘制信号点。请注意,完整的信号也正好包括1024个点。这意味着一个信号将占据整个网格的宽度。
我还可以对图形进行缩放,这会将信号点的数量乘以缩放因子。具体来说:
const int SignalLength = 1024;
int ZoomFactor = 2; // 用户更新
int NewPoints = SignalLength * ZoomFactor;
我一直在尝试创建自定义的刷子/滚动条,以帮助浏览缩放的信号。然而,在维护滚动和可见内容的比例方面,我一直遇到问题。
可视化示例 [缩放因子:2]
我已经处理的一些参数包括:
-
滚动按钮:每个按钮的大小为50x50像素。
-
可滚动区域:由于滚动按钮而减小。即
Grid宽度 - (50*2)
:924个像素。 -
刷子宽度:将始终为
可滚动区域 / 缩放因子
。
请注意图像中的箭头,它显示信号的可见部分与刷子不同步。我猜想刷子移动得比网格实际显示得更快。
代码
private void ZoomFactor_Changed(object sender, EventArgs e)
{
if (ZoomFactor > 1)
{
Scrubber.Width = (ScrubberTrackPanel.Width / ZoomFactor);
ScrubberWidth.Text = Scrubber.Width.ToString();
ScrubberTrackPanel.Visible = true;
}
else
{
ScrubberTrackPanel.Visible = false;
Scrubber.Width = Scrubber.Parent.Width;
}
}
private void SfBtn_GridScrollRight_MouseDown(object sender, MouseEventArgs e)
{
// 左右两个按钮的标签属性都具有步进值。
// 左侧为-2
// 右侧为2
GlobalVars.GridScrubStepSize = 0 + int.Parse((SfButton)sender).Tag.ToString());
GridScrubberTimer.Start();
}
private void GridScrubberTimer_Tick(object sender, EventArgs e)
{
ScrollGrid(GlobalVars.GridScrubStepSize);
}
private void ScrollGrid(int StepSize)
{
var newStepPos = GlobalVars.ZoomedSignalLeft + StepSize;
// 如果到达图的边界(左/右)之一,停止滚动定时器。
if (newStepPos <= 0 || newStepPos >= 1024 * ZoomFactor && GridScrubberTimer.Enabled)
{
GridScrubberTimer.Stop();
return;
}
var ZoomedSignalSlice = GlobalVars.ZoomedSignal.Skip(newStepPos).Take(1024).ToList();
if (ZoomedSignalSlice.Count == 1024)
{
GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrubStepSize;
if (ScrubberTrackPanel.Visible)
{
Scrubber.Location = new Point(Scrubber.Location.X + (int)Math.Floor(GlobalVars.GridScrubStepSize/ (float)ZoomFactor), 0);
ScrubberCords.Text = Scrubber.Location.ToString();
}
GraphGrid.Refresh();
}
}
尝试的解决方案
我尝试了如何计算滚动条拇指的大小和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:
...
const int SignalLength = 1024;
int ZoomFactor = 2; //Updated by user
int NewPoints = SignalLength * ZoomFactor;
...
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
private void ZoomFactor_Changed(object sender, EventArgs e)
{
if (ZoomFactor > 1)
{
Scrubber.Width = (ScrubberTrackPanel.Width / ZoomFactor);
ScrubberWidth.Text = Scrubber.Width.ToString();
ScrubberTrackPanel.Visible = true;
}
else
{
ScrubberTrackPanel.Visible = false;
Scrubber.Width = Scrubber.Parent.Width;
}
}
private void SfBtn_GridScrollRight_MouseDown(object sender, MouseEventArgs e)
{
// Both left and right button's tag property have the step value.
// Left has -2
// Right has 2
GlobalVars.GridScrubStepSize = 0 + int.Parse((SfButton)sender).Tag.ToString());
GridScrubberTimer.Start();
}
private void GridScrubberTimer_Tick(object sender, EventArgs e)
{
ScrollGrid(GlobalVars.GridScrubStepSize);
}
private void ScrollGrid(int StepSize)
{
var newStepPos = GlobalVars.ZoomedSignalLeft + StepSize;
//To stop scroll timer if any of the boundry (left/right) of graph is reached.
if (newStepPos <= 0 || newStepPos >= 1024 * ZoomFactor && GridScrubberTimer.Enabled)
{
GridScrubberTimer.Stop();
return;
}
var ZoomedSignalSlice = GlobalVars.ZoomedSignal.Skip(newStepPos).Take(1024).ToList();
if (ZoomedSignalSlice.Count == 1024)
{
GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrubStepSize;
if (ScrubberTrackPanel.Visible)
{
Scrubber.Location = new Point(Scrubber.Location.X + (int)Math.Floor(GlobalVars.GridScrubStepSize/ (float)ZoomFactor), 0);
ScrubberCords.Text = Scrubber.Location.ToString();
}
GraphGrid.Refresh();
}
}
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
在经过数小时的代码调试后,我意识到位置计算完全错误。在修复后,滚动功能按预期工作,并适当地保持了比例。
以下是正确的代码:
...
GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrollStepSize;
// 将可见信号在网格上的当前起始位置映射到ScrollerTrackPanel范围内,然后除以ZoomFactor以获得在网格上可见信号图像上刮板位置与可见信号的比例位置。
int newx = (int)Math.Floor(GlobalVars.ZoomedSignalLeft / 1024F * ScrollerTrackPanel.Width / ZoomFactor);
Scrubber.Location = new Point(newx, 0);
...
英文:
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:
...
GlobalVars.ZoomedSignalLeft += GlobalVars.GridScrollStepSize;
// Mapping the current beginning position of the visible signal on the grid in the range of ScrollerTrackPanel and then dividing
// it with the ZoomFactor To get location of scrubber over the signal image proportional to the visible signal on the grid.
int newx = (int)Math.Floor(GlobalVars.ZoomedSignalLeft / 1024F * ScrollerTrackPanel.Width / ZoomFactor);
Scrubber.Location = new Point(newx, 0);
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论