我有一个简单的Winforms GUI,它在GroupBox中有一个TrackBar,其标题是我用来显示所包含的TrackBar的值:
private void trackBar1_Scroll(object sender, EventArgs e)
{
UpdateTrackBarPositionText();
}
private void Form1_Load(object sender, EventArgs e)
{
UpdateTrackBarPositionText();
}
private void UpdateTrackBarPositionText()
{
groupBox1.Text = ORIGINAL_TRACKBAR_TEXT + qualitySelector.Value.ToString();
}
问题是当擦拭棒时,它和组的标签都会闪烁,特别是在快速擦洗时。对于这样一个简单的操作,CPU使用率也相当高。如何改进此实施?我想实时更新值,而不是在放手后更新,以便用户在选择时看到该值。 DoubleBuffered = true;
什么也没做。
编辑: 我在实例化时使用了反射来将GroupBox和条形设置为双缓冲。这有助于Box,但滑块仍然闪烁:(
答案 0 :(得分:1)
这是计时器的经典用例。让它更新标签,比方说,每秒10次。除此之外真的是一种矫枉过正,因为无论如何都没人能读得那么快。
您可以永久启用计时器,或者(作为优化)您可以在trackBar1_Scroll
启用计时器,并在计时器本身中禁用它,如果过去几个滴答的值没有改变。事实上,如果自上次更新后价值没有变化,也不要更新标签(可能会节省一些额外的闪烁)。
答案 1 :(得分:1)
您是否设置了Double Buffering。如果不是从那里开始,那么根据需要采用其他方法。
答案 2 :(得分:1)
这不能解决这个问题,但它会创建一个使用自定义控件的变通方法。
public partial class SliderControl : Control
{
public event EventHandler ValueChanged;
public int MinValue { get; set; }
public int MaxValue { get; set; }
public int Value { get; set; }
public SliderControl()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer, true);
this.MinValue=0;
this.MaxValue=100;
this.Value=50;
this.Text="Value";
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
SetBoundsCore(Left, Top, Width, 32, BoundsSpecified.Height);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
pe.Graphics.DrawRectangle(Pens.Black, 0, 0, Width-1, Height-16);
using (var gp = new GraphicsPath())
{
var rect = new Rectangle(0, 0, Value*(Width-1)/MaxValue-1, Height-16);
gp.AddRectangle(rect);
using (var br = new LinearGradientBrush(rect, Color.SteelBlue, Color.LightBlue, LinearGradientMode.Horizontal))
{
pe.Graphics.FillPath(br, gp);
pe.Graphics.DrawPath(Pens.DarkBlue, gp);
}
}
var text = $"{this.Text} = {this.Value}";
var sz = pe.Graphics.MeasureString(text, SystemFonts.SmallCaptionFont);
pe.Graphics.DrawString(text, SystemFonts.SmallCaptionFont, Brushes.Black, Width/2-sz.Width/2, Height-16);
}
private void SetClickValue(Point click_point)
{
int x = (click_point.X+1)*MaxValue/Width;
this.Value=x;
this.Refresh();
this.ValueChanged?.Invoke(this, new EventArgs());
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (e.Button==MouseButtons.Left)
{
SetClickValue(e.Location);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button==MouseButtons.Left)
{
SetClickValue(e.Location);
}
}
}