[英]Display pop up with animated gif while loading file
The goal of my program is to load a directory into my treeview node, which takes more 10 sec(since the directory resides in a remote PC). 我程序的目标是将目录加载到我的treeview节点中,这需要花费10秒钟以上的时间(因为该目录位于远程PC中)。 During this time I shall add a pop up image of waiting. 在这段时间内,我将添加一个等待的弹出图像。 I copied the answer of this post: How can i show an image while my application is loading to my code, like: 我复制了这篇文章的答案: 我如何在应用程序加载到代码中时显示图像 ,例如:
private void treeView2_AfterSelect(object sender, TreeViewEventArgs e)
{
Form f = new Form();
f.Size = new Size(20, 25);
Image im = Image.FromFile(@"C:\Documents and Settings\JiangC\Documenti\Immagini\loader.gif");
f.FormBorderStyle = FormBorderStyle.None;
f.MinimizeBox = false;
f.MaximizeBox = false;
f.AutoSize = true;
PictureBox pb = new PictureBox();
//pb.Dock = DockStyle.Fill;
pb.SizeMode = PictureBoxSizeMode.AutoSize;
pb.Image = im;
pb.Location = new Point(50, 50);
f.Controls.Add(pb);
f.Show();
// Application.DoEvents();
BuildTree(directory, treeView2.Nodes, treeView2.SelectedNode);
f.Close();
}
What I want to do is that during the loading (when Buildtree() method is implementing) the form f with the picturebox pb will be shown, and after loading they just disappear. 我想做的是在加载过程中(当实现Buildtree()方法时)将显示带有图片框pb的窗体f,并且在加载后它们会消失。
The first problem is in "pb.Dock = DockStyle.Fill;" 第一个问题是“ pb.Dock = DockStyle.Fill;”。 If I uncomment it, this form f will not be shown during the loading(but I can see its minimized window in the bottom of the screen). 如果我取消注释,则在加载过程中将不会显示此表格f(但是我可以在屏幕底部看到其最小化的窗口)。 Only if I take off this line the form f could be shown out. 只有在我取消这一行后,表格f才能显示出来。 The second problem is "f.Show();" 第二个问题是“ f.Show();”。 When the form f is shown, the picturebox pb isn't shown at all(just an empty hole). 当显示表格f时,根本没有显示图片框pb(只是一个空洞)。 If I modify it into "f.ShowDialog();", the form f with the picture could be shown. 如果将其修改为“ f.ShowDialog();”,则可以显示带有图片的形式f。 However here comes the third problem, which is the form f will be always there, my function "BuildTree();" 但是,这里出现了第三个问题,即形式f永远存在,即我的函数“ BuildTree();”。 isn't implemented at all! 根本没有实现!
The forth problem is if I add the line "Application.DoEvents();", it works quite fine, during the loading the form f with the picturebox will be shown and after the loading the f will disappear, but the picture in f is a gif, in this case the gif doesn't animate at all! 第四个问题是,如果我添加“ Application.DoEvents();”行,它会很好地工作,在加载过程中将显示带有图片框的表单f,并且在加载后f将消失,但是f中的图片是gif,在这种情况下,gif根本没有动画!
So anybody could help me solve the problem? 那么有人可以帮助我解决问题吗?
Here's my code of BuildTree function: 这是我的BuildTree函数代码:
private void BuildTree(DirectoryInfo[] directoryInfo, TreeNodeCollection addInMe, TreeNode clicked)
{
for (int i = 0; i < directoryInfo.Length; i++)
{
var files = directoryInfo[i].GetFiles();
int length = files.Length;
clicked.Nodes.Add(directoryInfo[i].Name);
List<TreeNode> dateNode = new List<TreeNode>();
string[] allDates = new string[length];
try
{
for (int j = 0; j < length; j++)
{
allDates[j] = files[j].Name.Substring(11, 6);
}
}
catch (Exception e)
{ }
string[] date = allDates.Distinct().ToArray();
for (int k = 0; k < date.Length; k++) //From here to the end
{
// is my code loading file
dateNode.Add(clicked.Nodes.Add(date[i]));
for (int j = 0; j < length; j++)
{
// curNode.Nodes.Add(file.FullName, file.Name);
if (files[j].Name.Substring(11, 6) == date[i])
{
dateNode[i].Nodes.Add(files[j].FullName, files[j].Name);
}
}
}
foreach (DirectoryInfo subdir in directoryInfo[i].GetDirectories())
{
BuildTree(subdir, clicked.Nodes);
}
}
}
It depends on whether your BuildTree() method can be executed on background thread or not. 这取决于您的BuildTree()方法是否可以在后台线程上执行。 since you are passing references to properties of TreeView control I'm assuming that that code has to be executed on UI thread. 由于您要传递对TreeView控件属性的引用,因此我假设必须在UI线程上执行该代码。 In this case th only thing I can suggest to you is call Application.DoEvents(); 在这种情况下,我唯一可以建议的就是调用Application.DoEvents();。 from within BuildTree() method, for example in a loop. 从BuildTree()方法中,例如在循环中。
Also if you are making any long term calls to get data inside BuildTree() method, you should make these on background thread and synchronize with UI in any convenient way. 另外,如果要在BuildTree()方法中进行任何长期调用以获取数据,则应在后台线程上进行这些调用,并以任何方便的方式与UI同步。
[EDIT] I had a quick look at your BuildTree() method. [编辑]我快速浏览了您的BuildTree()方法。 I think in this case the best approach for you would be: 我认为在这种情况下,最适合您的方法是:
Code in treeView2_AfterSelect() would looks like this: treeView2_AfterSelect()中的代码如下所示:
//...
f.Show();
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (ss, ee) =>
{
ee.Result = PrepareData(directory); // prepare all data required to build the Tree
}
bw.RunWorkerCompleted += (ss, ee) =>
{
BuildTreeByData(ee.Result, addInMe, clicked);
f.Close();
}
bw.RunWorkerAsync();
Add this line to your code, before calling f.Show(): 在调用f.Show()之前,将以下行添加到您的代码中:
f.Activated += (s, e) => BuildTree(directory, treeView2.Nodes, treeView2.SelectedNode);
// it's f.Shown for Windows Forms, Activated is for WPF
It subscribes an anonymous event handler to the OnShow event of your f form. 它为f窗体的OnShow事件订阅了一个匿名事件处理程序。 In this handler you simply call your method. 在此处理程序中,您只需调用您的方法。
If it doesn't work, you will have to replace the call to BuildTree here for a BackgroundWorker call , since it is possible that your BuildTree method access UI controls, and that is a big no-no. 如果不起作用,则必须在此处将对BuildTree的调用替换为BackgroundWorker调用 ,因为BuildTree方法可能会访问UI控件,这是一个很大的禁忌。 Call this code instead of f.ShowDialog: 调用以下代码代替f.ShowDialog:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (ss, ee) =>
{
f.ShowDialog(this);
BuildTree(directory, treeView2.Nodes, treeView2.SelectedNode);
}
bw.RunWorkerCompleted += (ss, ee) => f.Close();
bw.RunWorkerAsync();
And change every access and modification to your controls in BuildTree like this: 并像这样更改对BuildTree中控件的所有访问和修改:
this.Invoke((MethodInvoker) (() =>
{
// access you control here
}));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.