查看完整版本: [-- 如何在线程运行中,弹出对话框让用户选择,并暂停线程 --]

QTCN开发网 -> Qt基础编程 -> 如何在线程运行中,弹出对话框让用户选择,并暂停线程 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

stlcours 2016-09-04 05:45

如何在线程运行中,弹出对话框让用户选择,并暂停线程

就好比有一个线程在拷贝很多文件,但是忽然发现有一个文件已经存在了,请用户确认是否覆盖,此时需要弹出对话框,并暂停线程(Windows拷贝文件就是这样的)。
等到用户选择了yes或者no之后,继续进行拷贝。这种情况应该如何写代码?

我考虑使用如下方案:

if (文件已经存在) {
  lock;
  emit 信号; // 让GUI弹出一个对话框
  lock; // 此时必定卡住,因为前面已经锁过一次了
}
然后在用户点击确认按钮后,两次解锁,不知道这种方案可行吗?大家有没有什么更好的方案?因为我觉得主动连续两次上锁怪怪的,从来只见过一次上锁。




ysu533 2016-09-04 06:35
这里为什么要上锁,个人觉得不但不需要2个锁,一个都不是必要的,这个线程除了拷贝,要干什么了?

另外你线程是怎么写的? movetothread,还是什么?

stlcours 2016-09-04 13:43
ysu533:这里为什么要上锁,个人觉得不但不需要2个锁,一个都不是必要的,这个线程除了拷贝,要干什么了?
另外你线程是怎么写的? movetothread,还是什么?
 (2016-09-04 06:35) 

我在网上搜了一下,都是使用锁,或者用变量进行空循环进行控制。我这线程,就是挨个拷贝文件啊,没有干别的事情。但是是否覆盖原有的文件,总该问问吧。

另外,我这线程就是继承QThread,没有采用movetothread。最近努力学习movetothread方法,可总是感觉不适应,不知道为什么这种方法却是官方的推荐方法?

ysu533 2016-09-04 13:53
stlcours:我在网上搜了一下,都是使用锁,或者用变量进行空循环进行控制。我这线程,就是挨个拷贝文件啊,没有干别的事情。但是是否覆盖原有的文件,总该问问吧。
另外,我这线程就是继承QThread,没有采用movetothread。最近努力学习movetothread方法,可总是感觉不适应,不知道为什么这 .. (2016-09-04 13:43)

官方文档早改了,继承不是不能用啊,movethread更简单啊, 一会我简单的给你写个


ysu533 2016-09-04 14:12
加入copy对像是你用来执行拷贝操作的,

QThread * thread = new QThread();

copy->moveToThread(thread);

thread->start();

connect(copy, SIGNAL(fileExist()), xx, SLOT(XXXX()));
copy->start(files); 开始拷贝文件
---------------------

void Copy::start(const QStringList &files)  // 开始拷贝这些文件
{
    QTimer::singleShot(0, this, SLOT(copy())); // 这里不执行实际拷贝,通过信号槽间接调用 copy
}

void Copy::copy(const QStringList &files)
{
   foreach(QString file, files) {
      if(存在) {
         emit fileExist(file);
         break;
       } else {
          拷贝文件
      }
     emit copyFinished();
   }
}


这样就不用考虑跨线程的问题了。

stlcours 2016-09-04 15:19
谢谢你辛苦写了这么多代码,但是没有回答到问题的实质。emit fileExist(file)以后,是应该要把线程暂停住(卡住?),等待用户选择后再进行下一步的操作。你如何保证这一点呢?

ysu533 2016-09-04 16:26
stlcours:谢谢你辛苦写了这么多代码,但是没有回答到问题的实质。emit fileExist(file)以后,是应该要把线程暂停住(卡住?),等待用户选择后再进行下一步的操作。你如何保证这一点呢? (2016-09-04 15:19)

大哥,这都没看明白啊, emit fileexist之后有个break;已经跳出拷贝了,

会执行XXXX()这个槽。

如果这个槽如果什么也不做,那么拷贝就终止了

如果你需要跳过,你只需要稍微修改下代码 把files 这个变量保存下就行了。

然后你自己实现下 skip, retry, overwrite, 实现跳过,重试,覆盖的功能就行了。

不需要你去额外控制线程。 这就是movetothread的好处。


ysu533 2016-09-04 18:11
stlcours:
谢谢你辛苦写了这么多代码,但是没有回答到问题的实质。emit fileExist(file)以后,是应该要把线程暂停住(卡住?),等待用户选择后再进行下一步的操作。你如何保证这一点呢?


今天没什么事,写了比较完整的例子,见附件,有什么问题,可以交流,编译需要qt5,

实现功能是将一个目录中的文件拷贝到另一个目录,已存在文件,可以跳过继续复制,或者覆盖文件,或是终止复制。

[attachment=15719]

stlcours 2016-09-04 18:18
ysu533:今天没什么事,写了比较完整的例子,见附件,有什么问题,可以交流,编译需要qt5,
实现功能是将一个目录中的文件拷贝到另一个目录,已存在文件,可以跳过继续复制,或者覆盖文件,或是终止复制。
....... (2016-09-04 18:11) 

谢谢。全是lamda,家里的XP机子太旧了没法运行,明天到公司再试试。

不过我还是没有明白你的意思,怎么能离开break呢?根据用户的指示,再决定是否继续处理后面的文件,而你这样就是完全退出了,似乎不对啊。。。

ysu533 2016-09-04 18:22
stlcours:谢谢。全是lamda,家里的XP机子太旧了没法运行,明天到公司再试试。
不过我还是没有明白你的意思,怎么能离开break呢?根据用户的指示,再决定是否继续处理后面的文件,而你这样就是完全退出了,似乎不对啊。。。 (2016-09-04 18:18)

你试试,就知道对不对了。当然,代码结构不一定要这么写。 你可以故意制造冲突, 比如在第一个目录还没复制完,马上在ui上操作复制第二个目录,你会发现,并不会覆盖第一个目录的相关变量, 比如dircopy中的 fromList 和 toList。

我离开了,后面又回来了, 除非用户选择了 abort


哥依然潇洒 2016-09-05 08:51
新手回答圣骑士的对话看着果真很爽
!!!

ysu533 2016-09-05 11:14
哥依然潇洒:新手回答圣骑士的对话看着果真很爽
!!! (2016-09-05 08:51) 

啥意思?

gasdfrewq 2017-01-22 10:50
信号可以用阻塞模式等待界面执行完成之后再执行吧?
我之前这么用过,不知道适不适合你这个情况


查看完整版本: [-- 如何在线程运行中,弹出对话框让用户选择,并暂停线程 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled