Python PyQt 进度条忙碌状态
我发现有几个问题和这个很像,比如:
不过大多数的例子和答案都是在一个GUI线程和一个数据处理线程上。
让我来解释一下我的情况。
我有三个类:
- 类MainWindow(继承自
QMainWindow
类,作为主界面) - 类LogInWidget(继承自
QWidget
类。这个类包含了所有的用户名/密码输入框和一个进度条,见下图)
第三个类DataTableWidget(继承自QWidget
类,包含一个显示几百上千条数据的表格)
这个程序的设计是这样的:一旦用户通过LogInWidget
登录成功,就能看到由DataTableWidget
显示的所有数据。
我使用.setCentralWidget
方法来设置LogInWidget
和DataTableWidget
。(也就是说,如果用户的密码正确,我会用
table = DataTableWidget ()
self.setCentralWidget(table)
来显示表格。
我的问题是:当用户登录时,由于要显示的数据量很大,界面会出现很长时间的卡顿,用户在看到数据表之前会感到很不流畅。
所以我想在程序加载表格之前,在LogInWidget
上显示一个忙碌的进度条。
我考虑使用QThread
来实现这个功能,但因为显示进度条和创建DataTableWidget
以及设置为中央窗口都是GUI任务,我应该怎么做呢?
2 个回答
这个事情没有简单直接的方法。不过,这里有个想法:
正如@schollii所说,你需要在DataTableWidget
渲染的时候发出一个信号。可惜的是,这个信号并不存在。即使存在,也得等到小部件渲染完成后才能处理。
不过,如果DataTableWidget
有一个模型,你可以用自己的方法覆盖data()
,这个方法可以先调用基类的data()
方法,然后更新一个进度条(不过只在第一次渲染表格时更新进度条,而不是在后续调用data()
时)。在视图渲染的时候,视图会多次调用data()
方法。这样,你就能在渲染过程中获取一些时间点的信息。
当然,进度条不会在控制返回到事件循环之前重新绘制(也就是渲染完成之前),但你可以通过调用QApplication.processEvents()
来解决这个问题。
需要注意的是,这种做法相当“hacky”,一般来说是不好的实践,完全破坏了模型-视图的原则。我不推荐这样做。不过我想不出其他方法能达到同样的效果。也许你可以考虑加快DataTableWidget
的渲染速度。例如,QTableView.resizeColumnsToContents()
被认为是比较慢的。你在某个地方调用这个方法了吗?
你需要把进度条的数值和数据表控件(DataTableWidget)发出的信号连接起来。不过,这样做的前提是数据表控件在渲染的时候会多次发出这个信号,但这不太可能。也许你只需要一种方式来显示界面正在忙,比如一个条形图,上面有一条线在两端之间来回移动。这样的话,你就不需要在这两个控件之间交换数据了。