PDA

View Full Version : How to display marquee animation of QProgressBar properly when using it in QTreeView



Infinity
5th August 2013, 02:25
Hi,

I'm displaying QProgressBars in a QTreeView by subclassing QItemDelegate. Here's the code:


void ProgressBarItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionProgressBar progressBarOption;
progressBarOption.state = QStyle::State_Enabled;
progressBarOption.direction = QApplication::layoutDirection();
progressBarOption.rect = option.rect;
progressBarOption.fontMetrics = QApplication::fontMetrics();
progressBarOption.textAlignment = Qt::AlignCenter;
progressBarOption.textVisible = true;

if(...)
{...}
else if(...)
{...}
else if(...)
{
progressBarOption.progress = 50;
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
}

QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
}


As you can see I'm using the marquee animation of the progress bar (in some conditions) by setting minimum and maximimum to 0.
I actually get the animation, but it doesn't look well because the progress bar isn't redrawn fast enough.
Is there a way to redraw the progress bar fast enough to display the animation properly? Is it possible to tell the QItemDelegate to call paint() more frequent? Is it possible to display an QProgressBar directly, instead of calling QApplication::style()->drawControl(...)?

wysota
5th August 2013, 07:32
Is it possible to tell the QItemDelegate to call paint() more frequent?
You can connect a timer's timeout() signal to the view's update slot() (possibly passing in the coordinates of the item containing the progress bar). But don't be suprised if CPU usage will go sky high.


Is it possible to display an QProgressBar directly, instead of calling QApplication::style()->drawControl(...)?

Yes but you will have to control its geometry yourself (including clipping and showing/hiding the widget). An alternative is to use setIndexWidget() but then the bar will not be tied to your model in any way.

Infinity
9th August 2013, 14:18
I found another solution: I create a QProgressBar as editor display it via openPersistentEditor() permanently. It is not nice because the QProgressBar is a display widget and no editor, but it works without high CPU usage, without writing a lot of code and the QProgressBar is still tied to the model.

wysota
9th August 2013, 14:23
I found another solution: I create a QProgressBar as editor display it via openPersistentEditor() permanently. It is not nice because the QProgressBar is a display widget and no editor, but it works without high CPU usage, without writing a lot of code and the QProgressBar is still tied to the model.

Did you test it on a model with more than a couple of rows?

Infinity
10th August 2013, 18:05
I'm already using persistent editors in another column in the QTreeView (QComboBoxes).

Do you think that I have to expect performance problems?
I've just tested my application with 218 rows (although I think more than 50 rows at the same time are already unrealistic). The CPU usage is a bit high I'm resizing the window or the columns but I think that's not a big problem. The memory usage is also ok.

EDIT: I've tested the application again with 218 rows, but without the usage of persistent editors. The CPU usage is only a few percent lower and the memory usage only about 5 MB.

wysota
10th August 2013, 18:36
Do you think that I have to expect performance problems?
Yes, you should expect performance problems. Especially if you run on Windows that constantly redraws progress bars.

Infinity
10th August 2013, 20:11
As already described, I don't notice a big difference between using persistent editors and not using them. But I tested the application only on Linux (using the QGtkStyle). I will test is on Windows later.


that constantly redraws progress bars
That's true, all progress bars (and not only the progress bars that are currently shown) will be constantly redrawn when I update all values constantly.

wysota
10th August 2013, 21:45
That's true, all progress bars (and not only the progress bars that are currently shown) will be constantly redrawn when I update all values constantly.

There is no such thing as "constantly" in computers. Everything is discrete and updating bars "constantly" usually doesn't make much sense. The point here is that Vista+ draws the progress bar animated regardless if it changes its values or not.

Infinity
10th August 2013, 23:04
You are right, "constantly" doesn't make sense.


the progress bar animated regardless if it changes its values or not
I haven't thought of that yet because I don't use Windows so often.

Maybe I can reduce that problem by hiding progress bars that aren't visible. I will try it and test it on Windows.

wysota
11th August 2013, 01:25
I haven't thought of that yet because I don't use Windows so often.
Neither do I but my students had to deal with the animated progress bar problem back in Qt 4.4-ish days. I don't think much has changed since then in this regard.


Maybe I can reduce that problem by hiding progress bars that aren't visible. I will try it and test it on Windows.
I think you should first think if you really need to update all those bars "constantly" as this seems to me like a bigger problem than Windows redrawing progress bars (you can always draw a progress bar yourself in the delegate to overcome this issue).

Infinity
11th August 2013, 15:53
I tested the application under Windows. There are no performance problems, but the CPU usage is higher. I think the animation (which I don't really need) is not worth it considering the higher CPU usage.

As already mentioned I'm also displaying QComboBoxes in another column. Currently I'm using openPersistentEditor() to display them. Now I've tried to display them by manual painting:


void ComboBoxItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const//(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionComboBox comboBoxOption;
comboBoxOption.rect = option.rect;
comboBoxOption.state = option.state;
comboBoxOption.state |= QStyle::State_Enabled;
comboBoxOption.state |= QStyle::State_On;
comboBoxOption.subControls = QStyle::SC_All;
comboBoxOption.editable = false;
comboBoxOption.currentText = index.model()->data(index).toString();

QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &comboBoxOption, painter);
QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &comboBoxOption, painter);
}


On Windows the code works, but on Linux (when using QGtkStyle) I'm just getting the ComboBoxLabel. Does anybody know why painting the combo box not works with QGtkStyle?

wysota
11th August 2013, 19:56
Drawing a combobox is one thing. Making it work like a combobox is another. If you want to hear my personal opinion then pushing comboboxes into table columns is a violation against user experience :) If you consider what the column contains -- it contains some VALUE. The way you change the value and the sole fact that you can change the value (or not) is meaningless while displaying that value. If you display a bunch of comboboxes in a column, you just clutter the display and you have no functional benefit over just displaying the value contained in the field. If the user wants to edit a field, he will enter edit mode and use the combo that pops up, to modify the value which afterwards will again be displayed in the column.