WinForm中使用Timer从底部垂直缩小矩形的实现问询
解决WinForm Timer实现矩形从底部向上缩小的问题
你现在的核心问题应该是没搞对矩形的坐标计算——要实现宽度不变、从底部向上缩减高度,关键是固定矩形的底部位置,通过调整顶部Y坐标来让高度逐步变小,而不是单纯改高度值却不调整位置。
先给你梳理下思路,再上修改后的代码:
关键逻辑说明
WinForm的坐标系是左上角为(0,0),Y轴向下递增。所以要让矩形从底部往上缩,我们需要:
- 固定矩形的宽度和底部Y坐标(比如贴在窗体底部上方)
- 每次Timer触发时,减小矩形的高度,同时把矩形的顶部Y坐标往上移(也就是Y值变大),这样底部位置不动,高度从下往上“收”
完整代码示例
1. 定义变量
先在窗体类里定义需要的参数:
// 矩形的固定宽度 private int _fixedRectWidth = 200; // 矩形当前的高度(初始值设为你原来的195) private int _currentRectHeight = 195; // 矩形的底部Y坐标(固定不动) private int _rectBottomY; // 用于控制缩小的Timer private Timer _shrinkTimer;
2. 初始化参数和Timer
在窗体的Load事件里初始化:
private void Form1_Load(object sender, EventArgs e) { // 设置矩形底部位置:距离窗体底部50像素(可自行调整) _rectBottomY = this.ClientSize.Height - 50; // 初始化Timer _shrinkTimer = new Timer(); _shrinkTimer.Interval = 50; // 每50毫秒缩一次,数值越小速度越快 _shrinkTimer.Tick += ShrinkTimer_Tick; // 可以加个按钮来触发开始缩小,比如: // Button startBtn = new Button(); // startBtn.Text = "开始缩小"; // startBtn.Click += (s, args) => _shrinkTimer.Start(); // this.Controls.Add(startBtn); }
3. Timer Tick事件处理
这里负责更新高度并触发重绘:
private void ShrinkTimer_Tick(object sender, EventArgs e) { // 当高度还大于0时继续缩小,避免负数 if (_currentRectHeight > 0) { // 每次减少5像素高度,可调整步长 _currentRectHeight -= 5; // 触发窗体重绘,会调用Paint事件 this.Invalidate(); } else { // 高度缩到0就停止Timer _shrinkTimer.Stop(); } }
4. 在Paint事件里绘制矩形
不要直接在Timer里用CreateGraphics,这种方式容易导致闪烁和资源泄漏,正确的做法是用窗体的Paint事件:
private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; // 计算矩形的顶部Y坐标:底部Y - 当前高度 int rectTopY = _rectBottomY - _currentRectHeight; // 计算矩形的X坐标,让它在窗体中居中 int rectX = (this.ClientSize.Width - _fixedRectWidth) / 2; // 创建矩形对象 Rectangle targetRect = new Rectangle(rectX, rectTopY, _fixedRectWidth, _currentRectHeight); // 绘制矩形(这里用红色填充,你可以换成自己的样式) g.FillRectangle(Brushes.DarkRed, targetRect); // 也可以加个边框 g.DrawRectangle(Pens.Black, targetRect); }
为什么你之前的代码没成功?
你原来的代码可能只是单纯修改了size(高度)但没调整矩形的Y坐标,导致矩形是从顶部往下缩小,而不是底部往上。另外直接在Timer里创建Graphics对象没有及时释放,容易出问题,用Invalidate()触发Paint事件是WinForm绘制的标准做法。
内容的提问来源于stack exchange,提问作者Mr_Robot_XL
相关产品推荐
相关产品推荐

