Advanced widgets

It is with the advanced widgets that the real fun starts. PyQt has a range of really powerful widgets that allows you to build any kind of modern application you desire.

You will notice that many advanced Qt widgets are formed from the combination of a manager widget class and an item class. This holds for QCanvas with QCanvasItem, for QListView with QListViewItem and for many others.

QSimpleRichText, QTextView and QTextBrowser

These classes implement rich text viewers. They use html text and stylesheets to present data to a user. QTextView is limited to one page of text, while QTextBrowser includes hyperlink navigation. The class QStyleSheet is used to determine the graphical rendering of the contents of QTextView and QTextBrowser. QSimpleRichText is more like a label in use, and is intended for smaller texts. Indeed, if you stuff a QLabel with rich text, it will get displayed using QSimpleRichText. These classes do not provide a complete web-browser rendering engine — that would be too much for a mere toolkit, but the rendering is quite good.

QTextEdit

Available only in Qt3, not in Qt2, QTextEdit is a rich text editing widget. This is a very powerful class, almost a complete wordprocessor in its own right - except that it doesn't have a notion of the concept of ‘page'. The KDE Office wordprocessor, KWord is built around it.

QTextEdit can display images, text in fancy fonts across the whole Unicode range, tables and lists. Internally, QTextEdit uses the same subset of HTML that QTextView and friends use. If your text is saved in a different file format, you will first have to convert it to HTML, and that makes QTextEdit difficult to use for purposes such as a programmers editor, but has everything needed to create a rich text input pane for an email client, for instance. (Not that I condone sending html-formatted email!)

QListView and QListViewItem

This is possibly the most overworked PyQt class — it seems to be used in almost every application. QListView doubles as a listview and a treeview. People coming from a Visual Basic background will be delighted with the ease of use of this treeview. Adding an item in a tree is a simple matter of creating a QListViewItem with another QListViewItem for a parent.

Example 10-11. tree.py - building a tree

#
# tree.py - a simple tree with QListView
#
import sys
from qt import *


class MainWindow(QMainWindow):

    def __init__(self, *args):
        apply(QMainWindow.__init__, (self,) + args)
        self.tree = QListView(self)
        self.setCentralWidget(self.tree)
        self.tree.addColumn("item")
        self.tree.setRootIsDecorated(1)
        self.items=[]
        self.items.append(QListViewItem(self.tree, "testself1"))
        self.items.append(QListViewItem(self.items[-1], "child 1"))
        self.items.append(QListViewItem(self.items[-2], "child 2"))

def main(args):
    app=QApplication(args)
    win=MainWindow()
    win.show()
    app.connect(app, SIGNAL("lastWindowClosed()"),
                app, SLOT("quit()"))
    app.exec_loop()

if __name__=="__main__":
    main(sys.argv)
     

Note that inserting items in an unsorted QListView inserts the items at the top of the listview. Thus, if you insert items A, B and C, in that order, the order in the listview will be C, B, A. Try adding the following line in the constructor, before the listviewitems are created:

self.tree.setSorting(1,-1)
      

If you want your latest item to be the last in the branch, then you will have to give the item it comes after as a second argument— this can make for some quite irksome bookkeeping. (Remember our little XML parser plus treeview in the Section called A parser-formatter using signals and slots in Chapter 7? Well, this is the cause of one nasty bug in that code! In that treeview, all items are sorted within their node, and thus do not represent the structure of the XML document.)

QIconView and QIconViewItem

If you are familiar with the Listview control that's available on Windows, you might be somewhat surprised to learn that Qt's listview doesn't include an icon view mode. There is a separate icon view class QIconView that provides all the functionality you might expect, except for the easy switching between listview mode and iconview mode. You will need to use two widgets in a widget-stack (QWidgetStack) for that.

QSplitter

QSplitter is used to separate two gui items that can take a variable amount of space. The user can drag the splitter to give more room to one of those items. Splitters can be horizontal or vertical, and you can use splitters within splitters.

QCanvas, QCanvasView and QCanvasItems

This is a very powerful combination. Canvases are typically used in graphics applications, games or applications where a complex layout of text is required. QCanvasView is the real widget that includes scrollbars and can react to mouse presses or keyboard interaction. A QCanvasView can show (part of) a QCanvas, but a QCanvas can be shown on more than one QCanvasView. You can place QCanvasItems on a QCanvas. These items can represent simple geometric forms, chunks of text or sprites (sprites are independently moving, animated pictures). The following classes implement QCanvasItem:

From Qt 3, there is also QCanvasSpline, which can be used to draw bezier curves. Note that you cannot subclass QCanvasItem — this is explicitly forbidden in the Qt documentation: you will have to select a more specialized subclass of QCanvasItem.

Canvas items can move independently from each other, and can be rendered on top of other items, or below others (by clipping the obscured part). The PyQt canvas is completely double-buffered and thus gives a very smooth performance.

the Section called QCanvas in Chapter 21 shows a practical use for a QCanvas.

QTable, QTableItem and QTableView (or QGridView)

QTable and QTableView are completely different classes, but they should be discussed together, since both implement a way for a developer to present tabular data.

QTableView is rather difficult to use — it has a primitive, low-level interface and code based on it tends to be buggy. There is a lot of flexibility built into QTableView, but you cannot add widgets to cells. It has been deprecated in Qt3, where you can use the QGridView class instead.

QTable, by contrast, is a very high-level spreadsheet-like control, eminently suited for the presentation of database data. QTableItems are the items that fill the cells of a QTable, and are editable. It's easy to have a combobox or line editor pop-up when the user selects a certain cell. Windows users especially will know about the vast amount of ‘grid controls' that can be bought for Visual Basic or Visual C++ — QTable is the Qt equivalent, only not so bloated as most of those grids are.