我正在设计的程序通过获取图像的文件名来生成图像,在cdb中搜索该名称,然后使用该数据库项中的数据生成图片。所有这些都有效。我现在想要做的是添加一个进度条,因为如果你正在做大量的图片,它可能需要一段时间,所以进度条将有助于跟踪它。这是我正在使用的代码,但进度条中的进度不会提前,直到最后我想避免使用后台工作程序(如果可以的话)。
private void button5_Click(object sender, EventArgs e)
{
if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string folder = folderBrowserDialog1.SelectedPath;
DirectoryInfo dinfo = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
FileInfo[] Files = dinfo.GetFiles("*.jpg");
int count = Files.Length;
int current = 0;
foreach (FileInfo file in Files)
{
string path = Path.GetFileNameWithoutExtension(file.Name);
int cardid = Convert.ToInt32(path);
if (Program.CardData.ContainsKey(cardid))
{
DevPro_CardManager.cardmaker.IMG = LoadBitmap(folderBrowserDialog1.SelectedPath + "//" + file.Name);
string lev = Program.CardData[cardid].Level.ToString();
comboBox2.SelectedItem = lev;
string att = Program.CardData[cardid].Attribute.ToString();
if (att == "1")
{
att = "earth";
}
else if (att == "2")
{
att = "water";
}
else if (att == "4")
{
att = "fire";
}
else if (att == "8")
{
att = "wind";
}
else if (att == "16")
{
att = "light";
}
else if (att == "32")
{
att = "dark";
}
else if (att == "64")
{
att = "divine";
}
comboBox1.SelectedItem = att;
if (Program.CardData[cardid].Atk.ToString() == "-2")
{
textBox2.Text = "????";
}
else
{
textBox2.Text = Program.CardData[cardid].Atk.ToString();
}
if (Program.CardData[cardid].Def.ToString() == "-2")
{
textBox1.Text = "????";
}
else
{
textBox1.Text = Program.CardData[cardid].Def.ToString();
}
string ctp = Program.CardData[cardid].Type.ToString();
if (ctp == "2" || ctp == "130" || ctp == "65538" || ctp == "131074" || ctp == "262146" || ctp == "524290")
{
ctp = "spell";
}
else if (ctp == "4" || ctp == "1048580" || ctp == "131076")
{
ctp = "trap";
}
else if (ctp == "129" || ctp == "161")
{
ctp = "ritual";
}
else if (ctp == "65" || ctp == "97")
{
ctp = "fusion";
}
else if (ctp == "8193" || ctp == "8225" || ctp == "12321")
{
ctp = "synchro";
}
else if (ctp == "8388609" || ctp == "8388641")
{
ctp = "xyz";
}
else if (ctp == "33" || ctp == "545" || ctp == "1057" || ctp == "2081" || ctp == "4129" || ctp == "4194337")
{
ctp = "effect";
}
else if (ctp == "17" || ctp == "4113")
{
ctp = "normal";
}
else if (ctp == "16401")
{
ctp = "token";
}
comboBox3.SelectedItem = ctp;
GenerateCard();
ImageResizer.CropImage(361, 523, pictureBox1.Image, @"anime cards\" + Path.GetFileName(file.Name));
int cardcount = +1;
label8.Text = cardcount.ToString();
}
current++;
progressBar1.Value = current / count;
}
}
}
答案 0 :(得分:5)
我更喜欢BackgroundWorker而不是DoEvents。这是一种更清晰的方式来处理真正应该成为后台任务的事情。
由于泛型,调用并不像在MSDN上描述的那样复杂。
ControlName.Invoke(new Action(() => { /* UI update commands */ }));
更新:添加了示例
这是一个成功的BackgroundWorker的一个非常基本的例子。有几点需要注意。转换为浮点以正确计算百分比,以及使用for循环而不是foreach,因此计数器是固有的。对DoWork事件处理程序中对表单对象的唯一调用是使用带有通用委托的this.Invoke
来安全地调用要更新的UI对象,最后通过eventArgs将文件列表传递给BackgroundWorker。
public partial class Form1 : Form
{
BackgroundWorker fileParser;
public Form1()
{
InitializeComponent();
fileParser = new BackgroundWorker();
fileParser.WorkerReportsProgress = true;
fileParser.DoWork += new DoWorkEventHandler(fileParser_DoWork);
fileParser.ProgressChanged += new ProgressChangedEventHandler(fileParser_ProgressChanged);
// Emulating the FolderBrowserDialog results here
List<String> fileNames = new List<String> { "File 1", "File 2", "File 3", "File 4", "File 5" };
fileParser.RunWorkerAsync(fileNames);
}
void fileParser_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Update progress bar here
tbOutput.Text += e.ProgressPercentage.ToString() + "% | ";
}
void fileParser_DoWork(object sender, DoWorkEventArgs e)
{
List<String> fileNames = e.Argument as List<String>;
for (int i = 0; i < fileNames.Count; i++)
{
// Do intense work here
Thread.Sleep(2000);
this.Invoke(new Action(() => { tbOutput.Text += fileNames[i] + ": "; }));
float completePercent = ((float)(i + 1) / (float)fileNames.Count) * 100;
// Send event to update progress bar here
fileParser.ReportProgress(Convert.ToInt32(completePercent));
}
}
}
答案 1 :(得分:1)
请在进度条值更改后写下以下行
progressBar1.Value = current / count;
Application.DoEvents();
Application.DoEvents()会将更改应用于UI并进行刷新,以便您能够看到对UI的新更改。
答案 2 :(得分:1)
只是你看不到它,但它已经更新。
值应介于0和100之间。
尝试:
progressBar1.Value = (current / count) * 100;