winforms 如何在C# Windows窗体应用程序中保存数据库中图像列表中多个图像,然后在图片框中进行幻灯片放映?

roqulrg3  于 2022-11-17  发布在  C#
关注(0)|答案(1)|浏览(182)

我尝试使用openfiledialog将图片添加到图像列表中,然后将其保存在我的Ms Access数据库中,并以另一种形式调用它,通过使用计时器控件在图片框中滑动显示它们,但当我尝试使用打开文件对话框添加图片时,我收到此错误System.Drawing.dll中发生了类型为'System.OutOfMemoryException'的未处理异常其他信息:内存不足。
这是我代码

private void btnPicAdd_Click(object sender, EventArgs e)
        {            
            ofdTargetPic.Filter = "Image File (*.Gif;*.jpg)|*.Gif;*.jpg";
            ofdTargetPic.Title = "Add target picture";
            ofdTargetPic.Multiselect = true;
            ofdTargetPic.FileName = string.Empty;
            DialogResult result = ofdTargetPic.ShowDialog();
            if (result == DialogResult.OK)
            {
                picTargetchoose.SizeMode = PictureBoxSizeMode.StretchImage;
                foreach (var picture in ofdTargetPic.FileNames)
                {
                    imgltargetpic.Images.Add(Image.FromFile(picture));//error is here
                }
            }
        }

另外,如果可能的话,请告诉我可以用什么格式将图像列表数据保存在我的数据库中我知道代码,我只想知道我应该在我的数据库中打开什么空间来保存数据(图像列表输出数据的格式)
这里是代码,为那些谁需要学习如何添加数据到数据库

OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Target.accdb");//this addres here is based on where you save your data base    
OleDbCommand cmd = new OleDbCommand();
    cmd.CommandText = "insert into tablename(tablefieldname,tablefieldname,...)values('" + textboxName.Text + "','" + textboxfamily.Text + "')";
    cmd.Connection = con;
    con.Open();
    cmd.ExecuteNonQuery();
    con.Close();

更新的:首先是错误;;***System.Drawing.dll中发生类型为“System.OutOfMemoryException”的未处理异常其他信息:内存不足。***在我的问题是因为我选择的图像被损坏!!为清晰起见,我想显示保存的图像数据,从数据库中我的c# windows窗体应用程序在图片框中,我选择图像列表的原因是因为我想选择多个图像's,然后幻灯片显示他们使用计时器在一个图片框中,我已经写了代码,以显示给用户之前,保存在数据库中,这里是代码:

int selectedpic = 0;
private void timerpicslide_Tick(object sender, EventArgs e)
{
      picTargetchoose.Image = imgltargetpic.Images[selectedpic];
      if (selectedpic == imgltargetpic.Images.Count -1)
      {
           selectedpic = 0;
      }
      else
      {
           selectedpic++;
      }
}

我用计时器选择图片的图像列表中一个接一个的每一次计时器滴答声(记住启动计时器时,你添加图片的)现在的问题是我不能调用保存的数据到我的图像列表从数据库,并显示给用户使用图片框这里是我使用的代码:

private void cmbTarget_SelectedIndexChanged(object sender, EventArgs e)
{
    con.Open();
    OleDbDataAdapter da = new OleDbDataAdapter("select * from targetInfo where targetName like '" + cmbTarget.SelectedItem.ToString() + "%'", con);
    DataTable dt = new DataTable();
    da.Fill(dt);
    dgvtargetview.DataSource = dt;
    imglpicshow.Images.Add(Image.FromFile(dgvtargetview.CurrentRow.Cells[3].Value.ToString())); // where the problem lies

}

图像列表采用二进制数据我已经按照我们的朋友@Albert D. Kallal在回答中建议的方式将数据以OLE对象格式保存在我的数据库中,但现在我不能从数据库中取出并将其放入图像列表中进行处理。
感谢您抽出宝贵时间!

8aqjt8rx

8aqjt8rx1#

好吧,有人会假设,如果您要在Access?中保存原始二进制文件,那么图像控件可能会知道格式,但这表明您至少还应该有另一列,用于保存带有扩展名的文件名。
而且我至少会花一杯咖啡的时间来真正确定你想把文件存储在数据库中而不是文件夹中,然后只把路径名保存到数据库表中的文件夹中。
以上的原因很多,但这意味着:
如果你想采用sql server,那么数据迁移就变得非常容易了。
对于任何基于网络的软件-再次有一个路径到一个文件夹与图像是非常少的麻烦和工作。
用户可以很容易地从该文件夹中“复制文件”,搜索该文件夹中的文件名,并使用+启动他们最喜欢的图片编辑器和查看软件。如果你把该文件藏在数据库中,那么你就失去了使用任何和所有图片编辑器,甚至图片组织和图片幻灯片放映软件等,这使得任何其他软件很难使用这样的图片。
另外,不清楚您是希望在c#应用程序中显示图片,还是希望在Access窗体中显示图片?因此,应该在这里说明这个问题。
如前所述,您需要保存文件名的扩展名,因为如果您需要从数据库中提取图片,那么您需要文件扩展名(除非您只允许保存一种图片类型)。
您可以在Access数据库中使用oleDB类型列,或者使用memo。(但是,如果您将其作为二进制保存到memo类型列中,则需要在推入图像控件之前将字符串转换为byte[]。
因此,我使用了oleDB类型,我的数据库是:

请记住,我们根本没有使用Access使用的oleDB格式。这个选择实际上是一个简单的二进制数据blob。
在VBA/MS-Access中没有一点点代码的图像可以显示,但我假设我们在C# +中显示和使用一个winform。
好的,那么就说一个这样的形式--真实的简单:

因此,在顶部,我们浏览到一个文件-选择它
此代码:

private void cmdBrowseFile_Click(object sender, EventArgs e)
    {
        OpenFileDialog MyFile = new OpenFileDialog();

        MyFile.ShowDialog();
        if (MyFile.FileNames.Length > 0)
        {
            txtFile.Text = MyFile.FileName;
            txtFileName.Text = Path.GetFileName(txtFile.Text);

            ShowPicFile(MyFile.FileName);

        }
    }

    void ShowPicFile(string sFile)
    {
        pictureBox1.Image = ByteToImage(File.ReadAllBytes(sFile));

    }

    public static Bitmap ByteToImage(byte[] blob)
    {

        Bitmap image;
        using (MemoryStream stream = new MemoryStream(blob))
            image = new Bitmap(stream);

        return image;

    }

因此,如果我们浏览到file -,则显示(不保存到db)。
这样说:

因此,我只需将文件名放入右下角的框中,然后单击“保存到数据库
它将添加/保存到数据库。代码如下:

private void cmdSave_Click(object sender, EventArgs e)
    {
        // save picture as bytes to DB
        byte[] fData = File.ReadAllBytes(txtFile.Text);
        string strSQL =
            @"INSERT INTO MyPictures (FileName, PictureData)
            VALUES(@File, @Data)";
        OleDbCommand cmdSQL = new OleDbCommand(strSQL);
        cmdSQL.Parameters.Add("@File", OleDbType.VarWChar).Value = txtFileName.Text;
        cmdSQL.Parameters.Add("@Data", OleDbType.Binary).Value = fData;
        MyRstP(cmdSQL, false);

        // display in grid
        cmdSQL.CommandText = "SELECT ID, FileName FROM MyPIctures";
        cmdSQL.Parameters.Clear();
        dataGridView1.DataSource = MyRstP(cmdSQL);
        MessageBox.Show("saved");
    }

现在,新的一行出现在网格中。我可以单击任意一行,然后单击Show from DB。代码如下所示:

private void cmdShow_Click(object sender, EventArgs e)
    {
        int pk = (int)dataGridView1.CurrentRow.Cells[0].Value;
        OleDbCommand cmdSQL =
            new OleDbCommand("SELECT ID, PictureData FROM MyPictures WHERE ID = @ID");
        cmdSQL.Parameters.Add("@ID", OleDbType.Integer).Value = pk;

        DataRow OneRow = MyRstP(cmdSQL).Rows[0];
        
        pictureBox1.Image = ByteToImage((byte[])OneRow["PictureData"]);                
    }

我的助手程序

DataTable MyRstP(OleDbCommand cmdSQL, bool ReturnsData = true)
    {
        DataTable rstData = new DataTable();
        using (OleDbConnection conn = new OleDbConnection(Properties.Settings.Default.AccessDB))
        {
            using (cmdSQL)
            {
                cmdSQL.Connection = conn;
                conn.Open();
                    if (ReturnsData)
                        rstData.Load(cmdSQL.ExecuteReader());
                    else
                        cmdSQL.ExecuteNonQuery();
            }
        }
        return rstData;
    }

public static Bitmap ByteToImage(byte[] blob)
    {
        Bitmap image;
        using (MemoryStream stream = new MemoryStream(blob))
            image = new Bitmap(stream);

        return image;
    }

相关问题