1

I have found several questions that looks similar to this such as:

But most of the examples and answers were on 1 GUI thread and 1 data processing thread.

Let me explain my scenario.

I have 3 classes:

  1. class MainWindow (Inherited from QMainWindow class and act as main GUI)
  2. class LogInWidget (Inherited from QWidget class.This class consists of all the username/password field + a progress bar, pls see the image below)

LogInWidget

3.class DataTableWidget (Inherited from QWidget class.consist of a table that display a few hundreds thousands of data)

The program is designed so that once a user logged in to the program via LogInWidget, he will be able to see all the data displayed by the DataTableWidget.

I use .setCentralWidget method to set both LogInWidget and DataTableWidget.(ie.if the user password is correct, i use

table = DataTableWidget ()
self.setCentralWidget(table)

to display the table.

My problem is: When user logged in, there is a big GUI freeze before he can see the data table as there are so many data entry to display via the table.

So I would like to show a busy progress bar (on my LogInWidget) before the program finish loading the table.

I thought of using Qthread to accomplish it but since both tasks, displaying progress bar and creating DataTableWidget and setting as centralwidget is GUI tasks, how should i approach it?

Community
  • 1
  • 1
Chris Aung
  • 9,152
  • 33
  • 82
  • 127
  • Take a look at the qt documentation searching for `moveToThread`. – Hyperboreus Mar 27 '14 at 15:51
  • 1
    I don't think it is safe to move Qt GUI objects to another thread. Specifically it says here ( http://qt-project.org/doc/qt-4.8/threads-qobject.html ): "Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.". – three_pineapples Mar 28 '14 at 03:19

2 Answers2

1

You would have to connect your progress bar value to a signal from the DataTableWidget. But this in turn assumes that the DataTableWidget generates this signal many times while rendering it, which is not likely. Perhaps all you need is a way to show that the GUI is busy, like bar with a line on it that goes back and forth between the two ends of the bar. Then you don't need to exchange data between the the two widgets.

Oliver
  • 27,510
  • 9
  • 72
  • 103
  • This seems to be a good solution. You could simply connect the [dataChanged](http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#dataChanged) signal of the table's model to `qApp.processEvents`. – ekhumoro Mar 29 '14 at 00:34
1

There is no straight forward way to do it. However, here is an idea:

As @schollii says, you need a signal to be emitted by DataTableWidget while it is rendering. Such a signal does not exist. And even if it did, it wouldn't be processed until the widget was rendered

However, if DataTableWidget has a model, you could override the data() method with your own which just calls the data() method of the base class and also updates a progress bar (though only update the progress bar when first rendering the table, not during subsequent calls to data()). As the view renders, the view will be calling the data() method many times. This way you get access to points in time during the rendering process.

Of course the progress bar will not redraw until control returns to the event loop (the rendering finishes), but you could probably work around that by calling QApplication.processEvents().

Note that this is quite hacky, in general bad practice, and completely destroys the model-view paradigm. I don't recommend doing it. But I can't think of anyway to achieve the same outcome. Perhaps you could just speed up the rendering of the DataTableWidget. For instance, QTableView.resizeColumnsToContents() is known to be slow. Are you calling that anywhere?

three_pineapples
  • 11,579
  • 5
  • 38
  • 75
  • The `setData` method of the model must emit `dataChanged`, so why not connect to that? – ekhumoro Mar 29 '14 at 00:37
  • @ekhumoro I didn't think that the `dataChanged` signal would be emitted in the case of showing (rendering) a view for a model that was already full of data. The question seemed to indicate that the slowdown was coming from drawing the view, rather than filling the model with data. I could be wrong though. – three_pineapples Mar 29 '14 at 01:21
  • And you could be right - the question is not completely clear. – ekhumoro Mar 29 '14 at 01:26