Sunday, September 1, 2013

PyQt4: Widget that holds an image and a quit button

I made an extension to the WidgetWithQuit class I introduced recently in this post.
It now can hold an image (input should be a 2D or 3D numpy.ndarray). In WidgetWithQuit the quit button would keep its position relative to the bottom right corner. In WidgetWithPictureAndQuit the image displayed is resized likewise: It always keeps the distance to the borders and the quit button while keeping the aspect ratio. If the image, after resizing, is not centered (it happens, when it is not wide enough), it will be centered, such that the distance to the left and right border will be increased.
In addition to the usual imports, you now also need qimage2ndarray which can be installed via pip.
Please note that in order to make the example shown below work you will need the code introduced in my recent post.

from qimage2ndarray import array2qimage

class WidgetWithPictureAndQuit(WidgetWithQuit):
    def __init__(self, parent=None, buttontext="Quit", margin=10, image=None):
        WidgetWithQuit.__init__(self, parent, buttontext, margin)
        self.image = array2qimage(image)
        self.label = QtGui.QLabel(self)
        if self.image is not None:
            self.resize_image()

    def resize_image(self):
        widget_geometry = self.geometry()
        button_geometry = self.quit_button.geometry()
        width = widget_geometry.width() - 2*self.margin
        height = widget_geometry.height() - (button_geometry.height() + 3*self.margin)
        width_offset = self.margin
        pixmap = QtGui.QPixmap.fromImage(self.image).scaled(width, height, QtCore.Qt.KeepAspectRatio)
        if pixmap.width() < width:
            width_offset = (widget_geometry.width() - pixmap.width())/2
        self.label.setGeometry(width_offset, self.margin, width, height)
        self.label.setPixmap(pixmap)

    def resizeEvent(self, event):
        WidgetWithQuit.resizeEvent(self, event)
        self.resize_image()

PyQt: Qt Widget with button with a fixed margin from bottom right corner

PyQt4 provides an easy to use interface for the creation of GUI Applications. In order to get some practice in PyQt4 I decided to create a subclass WidgetWithQuit of QWidget that has a QuitButton (derived form QPushButton) as member variable that sends a quit signal to the qapp on a left click.
Thanks to the high level interface of PyQt4 this requires only a small modification of the resizeEvent function of QWidget (see code below).


from PyQt4 import QtGui, QtCore
import sys


class QuitButton(QtGui.QPushButton):
    def __init__(self, parent, text="Quit"):
        QtGui.QPushButton.__init__(self, text, parent)
        parent.connect(self, QtCore.SIGNAL('clicked()'),
                       QtGui.qApp, QtCore.SLOT('quit()'))
        self.resize(self.sizeHint().width(), 
                    self.sizeHint().height())


class WidgetWithQuit(QtGui.QWidget):
    """QWidget that has a QuitButton at the bottom right;
    margin specified in the constructor"""
    def __init__(self, parent=None, buttontext="Quit", margin=10):
        self.margin = margin
        QtGui.QWidget.__init__(self, parent)
        self.quit_button = QuitButton(self, text=buttontext)
        self.align_button()

    def align_button(self):
        widget_geometry = self.geometry()
        button_geometry = self.quit_button.geometry()
        width_offset = widget_geometry.width() - (button_geometry.width() + self.margin)
        height_offset = widget_geometry.height() - (button_geometry.height() + self.margin)
        self.quit_button.move(width_offset, height_offset)

    def resizeEvent(self, event):
        QtGui.QWidget.resizeEvent(self, event)
        self.align_button()


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    widget = WidgetWithQuit()
    widget.setGeometry(300, 300, 100, 100)
    widget.quit_button.setToolTip('Quit on left mouse click')
    widget.show()
    sys.exit(app.exec_())

Of course this is just a very simple, "academic" example; still it should be clear that PyQt4 offers an easy to use interface to build user-friendly GUI applications.
Thanks to C/C++ binding generators such as boost python you can still rely on fast C/C++ for the underlying algorithms which gives you the best of both worlds: easy implementation of the GUI using a high level language and fast algorithms working on (big) data in the background.
For the documentation of the classes used above, see:

Thursday, July 25, 2013

install_name_tool on OSX

Usually I do not have to cope with OSX. But today I had to and Apple's dylib policy drove me crazy (especially when there are many dylibs with absolute paths to their dependencies). The blogpost that saved the day for me introduced the handy tool install_name_tool. Calling with the -id switch, you can change the install name of the target. When used with the -change switch, install_name_tool will change the path to the dependency according to your settings (paths preferably relative!).
I wrote this post in case I ever have to deal with OSX again. Knowing that makes life a lot easier.

Saturday, July 20, 2013

blog recommendation

Whoever is interested in C++ should have a look at http://herbsutter.com/. Amongst other occupations Herb Sutter used to be a chair of the ISO C++ standards comittee. That qualifies him to produce interesting and informative posts on C++, especially with regard to standard C++.

For me the section Guru of the Week is  particularly useful. Every week there's a C++ problem (not a specific implementation task, but general questions regarding standard C++) that you can try to solve yourself. If you need a hint or are just interested in the solution, there is always an exhaustive answer. The problems are being updated to match C++14, therefore many problems are currently offline for revision. However, until they are back again, I recommend having a peek at the remaining ones.

Thursday, July 11, 2013

Disable CPU throttling in Debian (aptosid)

When building ATLAS you cannot have CPU throttling enabled:
"CPU Throttling apparently enabled! It appears you have cpu throttling enabled, which makes timings unreliable and an ATLAS install nonsensical. Aborting. "

Disabling throttling is just a single command (for each cpu):
cpufreq-set -g performance -c  <CPU>

Where CPU denotes the cpu index (0 through 7 in my case). If you do not have cpufreq-set, you can get it from the package cpufrequtils.

Wednesday, July 3, 2013

online UML diagrams

yuml is a website that allows you to draw UML diagrams online. You can export your diagrams to various formats, such as svg, png, json.


sample diagram generated using yuml

Sunday, June 30, 2013

Elisp Function to Add License File at Beginning of Buffer

I wrote a small function that allows for reading a file and adding it at the beginning of the buffer. This comes in handy when you need to add license terms to all your source files.
The function can be found in my .emacs on github. There is also a fake license containing just one line for trying that function.

The call syntax is
(add-license-handling license_dir license_type)

license_dir is the directory containing the license file (defaulting to ~/.emacs.d/license) and license_type is the license that you want to use stored in the file <license_dir>/<license_type>. You will also need the functions get_default_license_dir and get_default_license_type from my .emacs file to get this to work.
If you want to set different default values, add this to your .emacs:

(setq default_license_dir "~")
(setq default_license_type "FAKE")