【问题标题】:C# display images randomly and one after anotherC#一个接一个地随机显示图像
【发布时间】:2017-11-27 03:06:34
【问题描述】:

我正在创建一个简单的基于表单的消息显示系统,每条消息都是一个 jpeg 图像,我想要实现的是当程序加载时(就在用户登录后)随机选择并显示其中一个 jpg,如果用户单击“下一步”按钮,则会显示另一个 jpg,直到全部显示为止。我想我需要将每个图像读入一个数组,然后从数组中随机选择一个,然后当用户单击 Next 时,继续移动到数组中的下一个项目。一个警告是我不希望程序锁定打开 jpg 文件,因为其他人需要能够删除它们。

我当前的代码如下,如果您能提供任何帮助和建议,我将不胜感激。

private void Form1_Load(object sender, EventArgs e)
 {
      var rand = new Random();
      var files = Directory.GetFiles(@"\\server\screens\", "*.jpg");
      pictureBox1.Image = System.Drawing.Bitmap.FromFile(files[rand.Next(files.Length)]);  
 }

private void buttonNextImage_Click(object sender, EventArgs e)
 {
      var rand = new Random();
      var files = Directory.GetFiles(@"\\server\screens\", "*.jpg");
      pictureBox1.Image = System.Drawing.Bitmap.FromFile(files[rand.Next(files.Length)]);
 }

非常感谢 史蒂文

【问题讨论】:

  • 您发布的代码到底有什么问题?
  • 当前代码锁定文件打开,我不知道如何创建图像数组。谢谢
  • 有一点值得指出...使用rand.Next,您可能不会浏览数组中的所有文件。请参考my answer below了解如何进行洗牌/随机化。

标签: c# picturebox


【解决方案1】:

不要使用Bitmap.FromFile,使用Bitmap.FromStream

using(var fs = new FileStream(files[rand.Next(files.Length),
                              FileMode.Open, FileAccess.Read))
{
    pictureBox1.Image = System.Drawing.Bitmap.FromStream(fs);
}

我不知道如何创建图像数组

var files = Directory.GetFiles("\\\\server\\screens\\", "*.jpg");
var images = new Image[files.Length];
for(int i = 0; i < files.Length; ++i)
{
    using(var fs = new FileStream(files[i], FileMode.Open, FileAccess.Read))
    {
        images[i] = System.Drawing.Image.FromStream(fs);
    }
}

【讨论】:

  • 嗨 Max,这很好用,但会多次显示相同的图像,我该如何解决这个问题?谢谢
  • 我没有编辑权限,但是,我认为第一行代码缺少右括号,应该是: using(var fs = new FileStream(files[rand.Next(files.Length) )], FileMode.Open, FileAccess.Read))
【解决方案2】:

这里有两件事:

  1. 将您的随机实例移到一个类成员中,这样它只会被实例化一次。
  2. 显示图像后,将其从文件数组中删除,以便仅未显示的图像保留在列表中。当列表为空时,您知道您已将它们全部显示出来。

【讨论】:

    【解决方案3】:

    扩展 Øyvind Bråthen 的回答,您可以在显示所有图片后重置数组,也可以使用计时器每隔一段时间自动更改图像?

    【讨论】:

      【解决方案4】:

      我相信你有两个选择:

      a) 您将 JPG 文件加载到内存流中(最坏的选择)。

      b) 您创建具有相同名称和后缀如“tmp”(即“1.tmp.jpg”)的临时文件。

      直接取“b”,创建副本后,你会为你想在类级别随机显示的那些文件做一个索引。

      之后,使用某种计时器在每次滴答后更改图像。

      最后,在每次滴答之后,您可以同步该文件路径数组,让您的程序显示最新的和最新的。

      这是我的建议:)

      【讨论】:

        【解决方案5】:

        提示列表:

        • 不要制作一组图片;为您已经显示的文件名制作HashSet&lt;string&gt;。然后,当单击 NEXT 时,再次遍历文件夹并忽略您已经显示的文件名。从剩下的(如果有的话)中随机选择一个。这样,即使文件夹内容在运行时发生变化,您仍然可以充分利用它。而且一次加载所有图像不会浪费内存。
        • 当需要显示图片时,像你一样加载它,然后Clone() 它,然后Dispose() 原始图像。这样它就不会锁定文件。
        • 显示下一张图片时,别忘了Dispose()上一张以释放资源。

        【讨论】:

          【解决方案6】:

          这是处理您的请求的一般方法。

          1. 将所选目录(来自您的示例,\\Server\Screens\)中的所有 jpeg 文件加载到一个数组中。

          2. 随机化文件数组。这是一个洗牌数组的示例实现:Most efficient way to randomly shuffle a list of integers

          3. 加载数组中的第一张图片。该数组显然包含文件名,因此您不能只将PictureBox 的 Image 属性指向所需的元素;你必须加载图像。

            由于您不想锁定图像,建议从流中加载图像(参考@max's answer)。

          4. 当用户点击下一个按钮时,加载下一张图片。您必须检查文件是否存在,因为根据您的问题,我推断用户可能会在文件加载之前将其删除。

          【讨论】:

            【解决方案7】:
            public static int id = 0;
            private void timer1_Tick(object sender, EventArgs e)
            {
                id = id + 1;
                filelocation = "E:\\example\\" + id + ".bmp";
                pictureBox1.Image = System.Drawing.Bitmap.FromFile(filelocation);
            }
            

            【讨论】:

            • 如果附有可靠的解释,此代码示例将更加有用。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-06-27
            • 1970-01-01
            • 1970-01-01
            • 2019-01-31
            • 1970-01-01
            相关资源
            最近更新 更多