This exercise draws together many of the model/view features that have been covered in this and in earlier chapters.
Create an application that shows two widgets: a QListView and a custom BarGraphView. The data should be held in a custom BarGraphModel. The user should be able to edit the data through the QListView, using a custom BarGraphDelegate to control both the presentation and the editing of data items in the list view. The application is shown in Figure 16.5.
The model should be a QAbstractListModel subclass, and it should hold a list of data values (integers) and a dictionary of colors (keyed by "row"; e.g., the color with key 6 corresponds to the seventh data value and so on). The model should reimplement rowCount(), insertRows()—which should include calls to beginInsertRows() and endInsertRows() where appropriate, flags() to make the model editable, and setData() to allow the value (Qt.DisplayRole) and a value's color (Qt.UserRole) to be set and which should emit signals to indicate that data has changed—and data(), which should return the value, color, and for the Qt.DecorationRole, a 20 x 20 pixmap filled with the color. If no color has been set for a particular row, use a default of red.
The delegate is quite simple, and it is very similar to the IntegerColumnDelegate mentioned earlier in this chapter. The key difference is that the paint() method must be reimplemented, but only to set the alignment to Qt.AlignRight; the painting can still be done perfectly well by the base class.
The custom view will need to reimplement setModel(), in which connections should be made to the base class's update() method so that repainting occurs when the model's data is changed, minimumSizeHint(), sizeHint()—which can simply call minimumSizeHint()—and paintEvent(). The paint event can be done in slightly more than a dozen lines—make sure that you use QPainter.setWindow() so that the graph always fills the available space. All the methods should work correctly even if no model has been set—for example, with no model, the paint event should paint nothing.
Here is the code for the MainForm, to give you a feel for how the classes are used:
self.model = BarGraphModel() self.barGraphView = BarGraphView() self.barGraphView.setModel(self.model) self.listView = QListView() self.listView.setModel(self.model)
self.listView,setItemDelegate(BarGraphDelegate(0, 1000, self)) self.listView.setMaximumWidth(100) self.listView.setEditTriggers(QListView.DoubleClicked|
layout = QHBoxLayout() layout.addWidget(self.listView) layout.addWidget(self.barGraphView, 1) self.setLayout(layout)
In the model solution, we added some extra code to create 20 random items to create an initial bar graph. The whole thing can be done in less than 200 lines.
A solution is provided in chap16/bargrapher.pyw.
This page intentionally left blank
Was this article helpful?
Download Tube Jacker And Discover Everything You Need To Know About Jacking Unlimited Traffic From The Video Giant. The drop dead easy way to create winning video campaigns that will FLOOD your website with unstoppable FREE traffic, all on complete and total autopilot. How to exploit a sneaky method of boosting exposure and getting your videos to the top of Google within 72 hours, guaranteed.