site  contact  subhomenews

How to create a progress bar for a gtkdialog-based GUI

October 31, 2020 — BarryK

I implemented this solution in the early hours of this morning -- nice progress bar using an animated GIF. This is now in the new BluePup still-under-development bluetooth manager.

BluePup is a shell script, that uses gtkdialog for the GUI. There is a "SCAN" button, that takes 40 seconds, and I thought that it would be nice to have a progress bar. Well, gtkdialog has the <progressbar> tag, however, the official documentation shows it being used in a popup window, not embedded in the main GUI. I discovered there is a reason for that -- it doesn't work so well embedded.

I started the GUI with <progressbar --visible="false">, however, it starts running, invisibly. Getting it to start and stop, and reset proved to be very difficult.

Eventually, I thought, why not just use an animated SVG or GIF? They can be one-shot, not looping. This solution turned out to be very easy. I decided on GIF, mainly because we have the 'gifsicle' utility in EasyOS (and it is in most puppies, or used to be).

I used mtPaint, and created a rectangle 240x14 pixels, 8-colour palette, indexed-colour, with the desired background colour. I then drew a little rectangle on it -- let's see, wanted 30 iterations of the animation, so the rectangle was 8x14 pixels. Here it is:

img1

When I created the little rectangle, I had saved it to the clipboard, so all that I had to do was paste it, and save as 002.gif and so on. However, I saved them with the yellow colour set to transparent. Pretty quick, I had 30 images, 001.gif to 030.gif, all in the same folder.

I opened a terminal in the folder, and created the animation:

# gifsicle --delay=134 --no-loopcount $(ls -1 | sort -n | tr '\n' ' ') > progressbar.gif
# gifview -a progressbar.gif

The delay between frames is 1.34 seconds, so total play time is 40 seconds.

If I want to change the background colour, only have to do it to the first frame, 001.gif, as the others all have the yellow set to transparent. progressbar.gif is only 3900 bytes.

Here is how it is inserted in BluePup, my GIF is named bar240x14-40sec.gif:

    <hbox>
<text><label>$(gettext 'Search for new devices:')</label></text>
<button>
<label>$(gettext 'SCAN')</label>
<action>hide:STATUSFRAME</action>
<action>echo -e \"\x3Cb\x3E\x3Cspan color='#8000ff'\x3E$(gettext 'Scanning, please wait...')\x3C/span\x3E\x3C/b\x3E\" > /tmp/bluepup/scan-status</action>
<action>/usr/local/bluepup/support/scan & </action>
<action>show:SCANBAR</action>
<action>refresh:SCANBAR</action>
</button>
</hbox>
<text use-markup=\"true\" align=\"1\" auto-refresh=\"true\">
<variable>SCANSTATUS</variable>
<input file>/tmp/bluepup/scan-status</input>
</text>
<pixmap visible=\"false\">
<variable>SCANBAR</variable>
<input file>/usr/local/bluepup/icons/bar240x14-40sec.gif</input>
</pixmap>

The progress bar will play, just once, whenever there is <action>refresh:SCANBAR</action>, which causes the GIF to be loaded from file. I presume that it is not loaded at first startup of the GUI, as have <pixmap visible="false">. To hide the progress-bar after playing it, need to have <action>hide:SCANBAR</action> somewhere else.

Very simple, thought I would put it out there, in case anyone else using gtkdialog might find this solution useful.  Here is the gifsicle man page:

https://linux.die.net/man/1/gifsicle 

Tags: easy