More fun in PySide! by Jeremy Ernst

This week's adventure involves doing something that you would think would be super simple, but instead involves image manipulation! I wanted to have the icons of the tabs of my animation control picker darken if they were not selected. With the image below, it isn't as clear as it could be as to which character tab is currently active. I added some height margins, but it would sure be a whole lot clearer if the images weren't the same value!


It became evident that I was going to need to take some of the knowledge from last week, and apply that to this problem. So let's drive into that.

First, I hooked up the tabWidget (currentChanged) to a new function that would do the image manipulation and set the icon. In this new function, the first thing I do is get the total number of character tabs, as well as get the currently selected tab.

As I loop through the tabs, if the tab I am on in the loop is the currently selected tab, I access a property on the tabWidget I created that will give me the QIcon in memory, so that I can set the tab icon back to the original image on disk.

If the tab is not the currently selected tab, I get the QIcon of the tab, then get the pixmap of the QIcon, and then convert that to a QImage.

This is the fun part! Now, I loop through the x and y positions of the image, sampling the rgb value of the pixel at those positions, darken that value using QColor's darker function, and then set the pixel on our temp QImage at the same x,y location to that new darker color. This continues until all pixels are read, darkened, and then set, on the new QImage.

Now all that is left to do, is to convert this QImage to a QPixmap, and set the tab icon to that new, darkened image (which only exists in memory, not on disk).

The end result now gives me exactly what I was looking for!

Much more clear!

Much more clear!

Here's the full function as well:

Hope this helps anyone else looking to do something similar! 




Customizing QToolTip by Jeremy Ernst

This is not a post about style-sheets. I wish it were that easy to add a background image to a QToolTip, but it's not.

I wanted to look into adding background images to tool-tips. The first thing I found was that you can use html as your tool-tip text to display an image in the tool-tip. But, I didn't want to just display and image. I wanted to display an image with text on top of it.

Here's how you can simply display an image as your tool-tip using HTML:

With this method, I would need to author tons of images just for tool-tips, which is crazy. I started digging into generating my own image using QPainter. While looking at the documentation, I found that QPainter had all sorts of handy functions to draw things, and this could all then be saved to a QPixMap. This worked really well! I supply an image to paint as the background, then draw text on top, then save that out as an image. I was pretty stoked when I got to this point. Here's the code for that:

My intention was to have 1 tool-tip image. It gets overwritten anytime a tool-tip is requested with the new image. However, when I would have widgets call on this method to generate their tool-tip image, it would only happen when that interface was instantiated, meaning the singular tool-tip would get stomped, and all widgets would end up with the same tool-tip.

The next idea was to give this method a unique filename to save out. But then I could end up with hundreds of tool-tip images, which isn't really much better than authoring my own. I really wanted the tool-tip image to be generated when a tool-tip was requested by a widget. To do this, I need to intercept the ToolTip QEvent. Okay, fine. How can I do this?

I created another function that is my own tool-tip event handler.

Now for the last steps. When creating a widget, I reassign the widget's event method to this method instead.

The tooltip_text property holds the text I want displayed on top of the image. The tooltip_size property, which is optional, determines which background image gets used. The first line, which is where this button's event method is reassigned, passes in itself as an argument so that I can query the above properties and set the tool-tip on that widget. This means there is only ever 1 tool-tip image, and it gets generated whenever a ToolTip event is intercepted (if that widget has reassigned its event method).

Below is what the end result looks like. Keep in mind it's the same image file being displayed on all of the buttons.


This was one of those things where I had the idea, and went down the rabbit hole until I figured it out. Is it super useful? Not really. But it adds an extra 5% of polish to my tool-tips I suppose!