C# 如何在Visual Studio中使用C访问picturebox中图像的名称#

C# 如何在Visual Studio中使用C访问picturebox中图像的名称#,c#,picturebox,C#,Picturebox,我有一个程序,使用picturebox有16个网格图块,但只使用5个图像,其余的图块只是一个黑色图像 我想知道“用户”点击了哪个图像 我有一个叫做image\u Click的方法(objectsender,EventArgs e) 我在这个方法中有一个if语句,它声明: if (peckedSquare.BackColor == Color.Black) { System.Diagnostics.Debug.WriteLine("Pecked a black square");

我有一个程序,使用picturebox有16个网格图块,但只使用5个图像,其余的图块只是一个黑色图像

我想知道“用户”点击了哪个图像

我有一个叫做image\u Click的方法(objectsender,EventArgs e)

我在这个方法中有一个if语句,它声明:

if (peckedSquare.BackColor == Color.Black)
{
    System.Diagnostics.Debug.WriteLine("Pecked a black square");
    return;
}
这会发送一个字符串,让我知道何时单击了黑色方块

有没有一种简单的方式可以说:

//伪代码:

if (peckedSquare.ImageName == pigeon1.png)
{
    System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}
我在谷歌上搜索了我的问题,但没有找到任何合适的答案

//编辑 我刚刚重新阅读了我的代码。 我用一个随机数将每张图片分配给一个picturebox正方形。 我把这个随机数作为变量,所以我可以用这个变量来确定点击了哪个图像。 即

或者更好

pigeonSelected = randomNumber + 1 //as I am using an array to store the images
System.Diagnostics.Debug.WriteLine("Pecked Pigeon Number {0}", pigeonSelected);

作为快速而肮脏的解决方案,我将使用
标记
属性来实现这一点,
null
用于黑色分幅,而其他分幅则使用文件路径(即使您的图像来自资源,它也始终可用),类似这样:

if (peckedSquare.Tag == null)
{
    Debug.WriteLine("Pecked a black square");
}
else
{
    switch (Path.GetFileName(peckedSquare.Tag.ToString()))
    {
        case "pigeon1.png":
        break;
    }
}
当然,当您创建分幅时,您必须将文件路径存储在
标记中:

PictureBox tile = new PictureBox();
tile.Image = Image.FromFile(path); // Or another source, of course
tile.Tag = path;
作为替代方法,您甚至可以为此使用
Name
属性,每个控件都被命名(设计器代码集成的主控件),但如果您在运行时创建控件,则可以将该值设置为所需的任何值(不仅是有效标识符)。与上面相同的用法只是不需要调用
ToString()

如何改进?

请允许我说这个解决方案不是很OOP。即使不进行大的重构,我们也可以做得更好。请注意,您可以在
标记
属性中存储所需的任何内容。一个数字,一个与文件名无关的简单字符串,甚至(可能更好)一个表示该图像的
枚举
(将操作委托给该对象)。这是一个非常原始的示例:

abstract class Tile {
    public abstract void Activate();
}

sealed class EmptyTile : Tile {
    public virtual void Activate() {
        Debug.WriteLine("Pecked a black square");
    }
}

sealed class ImageTile : Tile {
    public ImageTile(string content) {
        _content = content;
    }

    public virtual void Activate() {
        Debug.WriteLine(_content);
    }

    private string _content;
}
通过这种方式,您可以在单击事件处理程序中执行以下操作:

((Tile)peckedTile.Tag).Activate();
无需检查内部内容或与
null
进行比较。无
如果
和无
开关
,请不要忘记在创建平铺时放置适当的对象(
ImageTile
BlackTile
)。

使用方法从文件加载图像。然后文件路径将存储在 财产:

对Load方法的调用将覆盖ImageLocation属性,将ImageLocation设置为方法调用中指定的URL值

因此,您可以编写以下示例:

if (peckedSquare.ImageLocation.EndsWith("pigeon1.png"))
{
    System.Diagnostics.Debug.WriteLine("Pecked Pigeon number 1");
}

您可以使用@Adriano建议的标记属性执行类似的操作:

public Form1()
{
    InitializeComponent();
    pictureBox1.Click += pictureBox_Click;
    pictureBox2.Click += pictureBox_Click;
    pictureBox3.Click += pictureBox_Click;
    // ...
    pictureBox1.Tag = "picture1.png";
    pictureBox2.Tag = "picture2.png";
    pictureBox3.Tag = "picture3.png";
}

void pictureBox_Click(object sender, EventArgs e)
{
    PictureBox pb = sender as PictureBox;

    if (pb.BackColor != Color.Black)
        Debug.WriteLine(pb.Tag.ToString());
    else
        Debug.WriteLine("Black image");

}

我认为你可以做如下的事情:

    private List<PictureBox> pictures = null;
    string[] ImageNames = new string[]
            {
                "images\\test_1.jpg",
                "images\\test_2.jpg"
            };

    private void Form1_Load(object sender, EventArgs e)
    {

        pictures = new List<PictureBox>();
        for (var idx = 0; idx < ImageNames.Length; idx++)
        {
            pictures.Add(new PictureBox());
            pictures[idx].Image = new Bitmap(ImageNames[idx]);
            pictures[idx].Click += OnClick;

            // you'll want to set the offset and everything so it shows at the right place
            Controls.Add(pictures[idx]);
        }
    }

    private void OnClick(object sender, EventArgs eventArgs)
    {
        // you'll definitely want error handling here
        var ImageName = ImageNames[pictures.IndexOf((PictureBox) sender)];
    }
私有列表图片=null;
字符串[]图像名称=新字符串[]
{
“图像\\test_1.jpg”,
“图像\\test_2.jpg”
};
私有void Form1\u加载(对象发送方、事件参数e)
{
图片=新列表();
for(var idx=0;idx
您可以看到,在点击方法中,您将能够获得图像名称,我相信这就是您正在寻找的


正如其他人所说,您也可以使用“Tag”属性,前提是您没有将其用于其他目的。标签的好处在于,您可能还可以通过表单设计器对其进行编辑,这样您就可以比我上面使用的自动布局更巧妙地布局。祝你好运

你不能那样做。图像存在于内存中,无法跟踪其来源。
PictureBox.ImageLocation
属性?如果使用了
PictureBox.Load
:“对Load方法的调用将覆盖ImageLocation属性,将ImageLocation设置为方法调用中指定的URL值。”我假设您仅在此处使用windows窗体PictureBox。您能否保存对图像的引用,然后将“((PictureBox)sender.image”属性与您保存的图像列表进行比较?@drew_w我正在使用图像列表数组,并从该列表中随机选取一个图像。所以我可以说如果((PictureBox)sender).Image==鸽子图片[0],然后单击了鸽子1.png?我认为这个答案最适合我当前的代码。我将使用它,看看它是否有帮助。@pythonReuser也给第二个例子一个机会。它更具可读性,更面向对象(只是一点点)。
    private List<PictureBox> pictures = null;
    string[] ImageNames = new string[]
            {
                "images\\test_1.jpg",
                "images\\test_2.jpg"
            };

    private void Form1_Load(object sender, EventArgs e)
    {

        pictures = new List<PictureBox>();
        for (var idx = 0; idx < ImageNames.Length; idx++)
        {
            pictures.Add(new PictureBox());
            pictures[idx].Image = new Bitmap(ImageNames[idx]);
            pictures[idx].Click += OnClick;

            // you'll want to set the offset and everything so it shows at the right place
            Controls.Add(pictures[idx]);
        }
    }

    private void OnClick(object sender, EventArgs eventArgs)
    {
        // you'll definitely want error handling here
        var ImageName = ImageNames[pictures.IndexOf((PictureBox) sender)];
    }