You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm实现单张图片随机切换显示位置的技术咨询

Solution: Single Image Random Position Switching in WinForms

Got it, let's adjust your code so we get a single image moving to random positions instead of spawning multiple copies all over the form. The original approach using CreateGraphics just draws new images on top each iteration—we'll use PictureBox controls instead, which are far cleaner for this kind of dynamic image positioning in WinForms.

Modified Full Code

using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace War_Game
{
    public partial class Form1 : Form
    {
        private Thread _allyThread;
        private Thread _foeThread;
        private readonly Random _rdm = new Random();
        private PictureBox _allyPic;
        private PictureBox _foePic;

        public Form1()
        {
            InitializeComponent();
            SetupPictureBoxes();
        }

        private void SetupPictureBoxes()
        {
            // Initialize Ally PictureBox
            _allyPic = new PictureBox
            {
                Size = new Size(30, 30),
                Image = new Bitmap(@"C:\Users\x\Downloads\sandler.png"),
                SizeMode = PictureBoxSizeMode.StretchImage,
                Visible = false
            };
            Controls.Add(_allyPic);

            // Initialize Foe PictureBox
            _foePic = new PictureBox
            {
                Size = new Size(30, 30),
                Image = new Bitmap(@"C:\Users\x\Downloads\nicolas.png"),
                SizeMode = PictureBoxSizeMode.StretchImage,
                Visible = false
            };
            Controls.Add(_foePic);
        }

        private void ally_Click(object sender, EventArgs e)
        {
            // Stop existing thread if running to avoid duplicates
            if (_allyThread?.IsAlive == true)
                _allyThread.Abort();

            _allyThread = new Thread(MoveAllyImage);
            _allyThread.Start();
        }

        private void MoveAllyImage()
        {
            _allyPic.Invoke((MethodInvoker)(() => _allyPic.Visible = true));
            
            for (int i = 0; i < 100; i++)
            {
                // Calculate random position that keeps the image inside the form
                int x = _rdm.Next(0, ClientSize.Width - _allyPic.Width);
                int y = _rdm.Next(0, ClientSize.Height - _allyPic.Height);

                // Update PictureBox location safely via Invoke (UI thread only!)
                _allyPic.Invoke((MethodInvoker)(() => 
                {
                    _allyPic.Location = new Point(x, y);
                }));

                Thread.Sleep(100);
            }

            _allyPic.Invoke((MethodInvoker)(() => _allyPic.Visible = false));
            MessageBox.Show("Adam Sandler has invaded your program!");
        }

        private void foe_Click(object sender, EventArgs e)
        {
            // Stop existing thread if running
            if (_foeThread?.IsAlive == true)
                _foeThread.Abort();

            _foeThread = new Thread(MoveFoeImage);
            _foeThread.Start();
        }

        private void MoveFoeImage()
        {
            _foePic.Invoke((MethodInvoker)(() => _foePic.Visible = true));
            
            for (int i = 0; i < 100; i++)
            {
                int x = _rdm.Next(0, ClientSize.Width - _foePic.Width);
                int y = _rdm.Next(0, ClientSize.Height - _foePic.Height);

                _foePic.Invoke((MethodInvoker)(() => 
                {
                    _foePic.Location = new Point(x, y);
                }));

                Thread.Sleep(100);
            }

            _foePic.Invoke((MethodInvoker)(() => _foePic.Visible = false));
            MessageBox.Show("Nicolas Cage has invaded your program!");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Clean up threads on form close to avoid memory leaks
            _allyThread?.Abort();
            _foeThread?.Abort();
        }
    }
}

Key Changes Explained

  • PictureBox Controls: We use PictureBox instead of direct CreateGraphics drawing—this lets us easily update the image's position without leaving old images on the form.
  • Safe Cross-Thread Operations: WinForms controls can only be modified from the UI thread, so we use Control.Invoke to update the PictureBox location and visibility from our background threads.
  • Thread Safety: We check if a thread is already running before starting a new one, and clean up threads when the form closes to prevent memory leaks.
  • Boundary Checks: When calculating random positions, we subtract the image's width/height from the form's client size to ensure the entire image stays visible inside the form.
  • Clean Visibility: We hide the PictureBox when the movement loop finishes, keeping the form tidy after the invasion message.

内容的提问来源于stack exchange,提问作者user11526364

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 14:22:44