【发布时间】:2015-06-29 13:28:49
【问题描述】:
我编写了一个程序,它读取一个短视频,然后以降低的 FPS 写入几百帧。它运行良好,但“if”循环阻塞了 UI。我尝试创建一个 backgroudWorker 来处理“if”循环,同时可以显示 UI 值,并且可以通过“取消”按钮中断该过程。 我的问题是:我无法让“if”循环遍历所有帧:
for (i = 0; i < frames_number; i++)
到最后一帧!它停在 100,即使我尝试了多种解决方案将“i”的进度转换为百分比,例如:
progress = System::Convert::ToInt32((100*(i / frames_number)));
或
progress = (int)((float)i / (float)frames_number *100);
以下是代码的重要sn-ps:
private: System::Void CreateSlowMo_Click(System::Object^ sender, System::EventArgs^ e) {
VideoCapture inputVideo(videoToOpenNameStr);
if (!inputVideo.isOpened()) {
MessageBox::Show(L"Error");
}
fps = int(inputVideo.get(CAP_PROP_FPS)); // get the frame rate of the video
frames_number = int(inputVideo.get(CAP_PROP_FRAME_COUNT)); // get the total frames in the video
this->progressBar1->Maximum = frames_number; // Initilize the progress bar's maximum to the number of frames
outputVideo.open(name, CV_FOURCC('M', 'J', 'P', 'G'), fps_wanted, resolution, true); // Create an output video
if (outputVideo.isOpened())
{
this->backgroundWorker1->RunWorkerAsync(progress); // Delegating the blocking operations to the background worker
}
else {
MessageBox::Show(L"Error creating the video");
CreateSlowMo_button->Enabled = true;
}
}
backgroundWorker1_DoWork:
private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
progress = (int)e->Argument; // get the intial value of the argument
for (i = 0; i < frames_number; i++)
{
inputVideo >> source; // read frame
if (backgroundWorker1->CancellationPending) { // check if the User clicked on "Cancel"
e->Cancel = true;
break; // Stop the convertion
}
if (source.empty()) { // we reached the last frame
break;
// CreateSlowMo_button->Enabled = true;
}
if (progress > 100)
{ // verify we didn't exceed 100% of the task
backgroundWorker1->ReportProgress(100);
break;
}
outputVideo << source; // write the frame to the output video
progress = (int)(((float)i / (float)frames_number)* 100);
backgroundWorker1->ReportProgress(progress);
}
this->backgroundWorker1->ReportProgress(100);
e->Result = progress;
}
backgroundWorker1_ProgressChanged:
private: System::Void backgroundWorker1_ProgressChanged(System::Object^ sender, System::ComponentModel::ProgressChangedEventArgs^ e) {
this->progressBar1->Value = e->ProgressPercentage;
toolStripStatusLabel1->Text = "Processing..." + progressBar1->Value.ToString() + "%";
richTextBox6->Text = e->ProgressPercentage.ToString();
}
backgroundWorker1_RunWorkerCompleted:
private: System::Void backgroundWorker1_RunWorkerCompleted(System::Object^ sender, System::ComponentModel::RunWorkerCompletedEventArgs^ e) {
// in case the background process is finished with a cancel
if (e->Cancelled)
{
toolStripStatusLabel1->Text = "Task Cancelled";
}
// check if an error occurred in the backgroud process
else if (e->Error != nullptr)
{
toolStripStatusLabel1->Text = "Error while creating the SlowMo";
}
else
{ // task completed normally
this->toolStripStatusLabel1->Text = "SlowMo Created successfully!";
this->cancel_button->Enabled = false;
MessageBox::Show(L"Finished creating the sloMo");
this->toolStripStatusLabel1->Text = "Done";
this->CreateSlowMo_button->Enabled = true;
this->richTextBox5->Text = "value " + e->Result;
}
}
这里是结果的一些截图(我添加了文本框来可视化 'i'、'progress' 和 e->result 的值)'i' 和 'progress' 是 int=0,在文件 'variables 中定义.h'
extern int i ;
extern int progress;
和'variables.cpp':
int i = 0;
int progress =0;
【问题讨论】:
-
您的代码中有一个明显的错误,您正在从 0..100 计算进度,但 ProgressBar::Maximum 不是 100。简单的解决方法是删除
this->progressBar1->Maximum = frames_number;分配。跨度> -
我改变了它,但它只影响了progressBar(它是完全绿色的)并且不能通过所有的帧(这里是589)。结果如下:i.imgur.com/H6rP9xZ.pngi.imgur.com/wYAYKSO.png
标签: c++ visual-c++ visual-studio-2013 backgroundworker