Hierachical data in TreeViews and TreeView updating technique - c++

I have lots of (hierachical) data that I show in a TreeView (could be around 20K items or more, including children items). The peculiar problem with my data is that each object shown in the treeview can exist in many treeview items. What I mean by that is that I might have an hierarchy like this one:
Item_A -> Item_B -> ItemC
Item_B -> Item_C
ItemC
Lets assume that Item_A contains Item_B which contains Item_C as it is shown above. This means that my list will also show the hierarchy of Item_B and Item_C. Consider now that something happens to an an object shown as Item_B (e.g name change). Then of course both items
must be updated. Consider now thousands of items in the treeview with complex hierarchies. What strategy would you use to update the treeview? Speed is of course the main concern here but also ease of use and maintenance. Currently I hold internal mappings of list items to objects and vice-versa to find and update items quickly. Is that a correct strategy? By recreating the list after each update I can throw lots of code away, but I wouldn't know which item paths were expanded or collapsed. How could I solve this problem? Should I store expanded paths in an internal container?
Thank you.
PS: Programming language is C++, and GUI lib is QT3.

I did something similar long time ago, using the windows TreeView common control.
What I did was set the CUSTOMDRAW flag, keep a single instance of each possible different node and make each node point to this instance: The 3 Item_C nodes would each have a pointer to the same unique Item_C instance.
So, when I change the data on Item_C I only needed to Invoke InvalidateRect() on the 3 Item_C nodes in order to reflect the changes done on the (single) changed data.
I suppose you could apply the same strategy here.

Use Qt4 model/view if you can use Qt4 in your project.
You will have to write your own model which can be tedious if you've never done so, but once setup you can reference/update multiple instances of the same object easily. Selections/Multiple selection can be handled too.
I'm not a big fan of Qt's model/view implementation (given model/view/controller design pattern is quite old) but it helps to organize data in gUIs

Disable updates using widget->setUpdatesEnabled(false), then edit all you want, and then renable it with widget->setUpdatesEnabled(true).
See the Qt documentation.

I solved a similar problem using the wxWidgets tree control. I used a singleton reference counter to track the objects I was putting in the control, and an iterator to traverse them. Here's an example.
class ReferenceCounter
{
public:
// Singleton pattern. Implementation left up to you.
static ReferenceCounter& get();
void add(const TreeData& data) {
mCounter[data.getId()].push_back(&data);
}
void remove(const TreeData& data) {
const CounterType::const_iterator itr = mCounter.find(data.getId());
if (itr != mCounter.end()) {
ItemType& items = itr->second;
items.erase(std::remove(items.begin(), items.end(), &data), items.end());
if (items.empty()) {
mCounter.erase(itr);
}
}
}
typedef std::vector<TreeData*> ItemType;
ItemType::iterator begin(const TreeData& data) {
const CounterType::const_iterator itr = mCounter.find(data.getId());
if (itr != mCounter.end()) {
return itr->second.begin();
}
// Else condition handling left up to you.
}
ItemType::iterator end(const TreeData& data) {
const CounterType::const_iterator itr = mCounter.find(data.getId());
if (itr != mCounter.end()) {
return itr->second.end();
}
// Else condition handling left up to you.
}
private:
typedef std::map<int, ItemType> CounterType;
CounterType mCounter;
};
class TreeData
{
public:
TreeData() { ReferenceCounter::get().add(*this); }
~TreeData() { ReferenceCounter::get().remove(*this); }
// Get database rows or whatever your tree is tracking.
int getId() const;
};
So given any TreeData, you can look up all the other TreeData's with matching ids in the reference counter. This makes it easy and fast keeping names and stuff up to date. Our tree handles over 1,000,000 nodes without a problem. In my implementation, I wrapped the iteration stuff up in a boost::iterator_facade class for easier use.

Related

Qt C++ Memento Design Pattern, I am trying to add a Undo/Redo function to my program, but why doesn't it work properly?

I am learning about the Memento Design Pattern and have constructed a simple Program for this purpose.
I have constructed 2 classes, Container, which only holds a QString called Code
The GUI is very simple, there is a QListWidget that displays a list of Container Items that have not been allocated to an Pallet Object, i.e. unallocated.
The Pallet class contains a QList of type Container, which would be allocated.
The MainWindow class has both a QList of type Container and Pallet, the former holding the previously mentioned unallocated Container Items.
The unallocated Items are displayed in a QListWidget Object, and a new Container item is appended whenever a specific QPushButton is pressed.
When adding an unallocated item to a Pallet, the number of which is determined by a QSpinBox, the item disappears from the list and is stored in that Pallet's QList<Container*>.
At the same time, the Pallet's information is displayed in a QTextEdit on a seperate Tab.
My Problem is that when I press the Button assigned to undo the last step, it successfully undoes the changes to the unallocated QList, but not to the Pallet QList.
Here are the Code Fragments that deal with my attempt at the Memento Design Pattern:
//memento class
class Memento
{
private:
Memento();
friend class MainWindow;
void setPallet_State(QList<Pallet*> PList);
void setUnallocated_State(QList<Container*> CList);
QList<Pallet*> getPallet_State();
QList<Container*> getUnallocated_State();
QList<Pallet*> Pallet_State;
QList<Container*> Unallocated_State;
};
//memento implementation
Memento::Memento()
{
}
void Memento::setPallet_State(QList<Pallet *> PList)
{
Pallet_State = PList;
}
void Memento::setUnallocated_State(QList<Container *> CList)
{
Unallocated_State = CList;
}
QList<Pallet *> Memento::getPallet_State()
{
return Pallet_State;
}
QList<Container *> Memento::getUnallocated_State()
{
return Unallocated_State;
}
Here are some of the cases where I implemented the Memento class in the MainWindow:
//inside of MainWindow class
public:
...
void move_to_Pallet();
Memento createMemento();
...
Memento MEMENTO = Memento(); //caretaker for when undoing
Memento RESTORE_MEMENTO = Memento(); //caretaker for redo
void RestoreMoment(Memento X);
void runUndo();
void runRedo();
...
Note: the '...' in the code above is arbitrary and had nothing to do the the problem.
//implementation of above functions
void MainWindow::move_to_Pallet()
{
//creating a memento in case of Backup
MEMENTO = createMemento();
...
//this is supposed to create a memento in case I need to redo
RESTORE_MEMENTO = createMemento();
}
Memento MainWindow::createMemento()
{
QList<Pallet*> Pallet_List;
Pallet_List = PAL_List;
QList<Container*> U_Container;
U_Container = Unallocated;
Memento moment;
moment.setPallet_State(Pallet_List);
moment.setUnallocated_State(U_Container);
return moment;
}
void MainWindow::RestoreMoment(Memento X)
{
PAL_List.clear();
PAL_List = X.getPallet_State();
Unallocated.clear();
Unallocated = X.getUnallocated_State();
print_Lists(); //this just displays the information within the MainWindow's Pallet QList and
//it's contents
}
void MainWindow::runUndo()
{
RestoreMoment(MEMENTO);
}
void MainWindow::runRedo()
{
RestoreMoment(RESTORE_MEMENTO);
}
The Problem that I have is that when I add only one Container Item from the 'unallocated' list to a pallet, i.e. the very first item of the pallet, the undo/redo function works as intended with any number of pallets, once more items are added to pallets, the MainWindow's Pallet QList does not seem to update as it should.
In fact, it can duplicate items sometimes.
Here is a quick example:
Before Undoing, this is what the unallocated list and the Pallet List looks like:
And this is what this becomes after I run the Undo function
What am I doing wrong here?
Please notice: the problem lies in the fact you're using a list of pointers to store the pallets.
It goes like this:
pallet list has 2 items
before modifying it you copy the list to the memento
then you add a container to the last of the two items
At this point you should notice that the list of pallets isn't really changed: same two pointers there. What changed (and wasn't saved in the memento) is an extra item in the internal list of containers held by the last pallet in the pallets list. All that was saved in the memento, instead, was a list of two pointers, and that's what you'll have back when you use the memento to restore the previous state.
Now, just to make it work as you intended, you have two choices:
change the way to represent your state and use QList<Pallet> instead of QList<Pallet *>
change the way to save your state in the memento, thus making a deep copy of the pallets list each time:
void Memento::setPallet_State(QList<Pallet *> PList)
{
Pallet_State.clear();
for(auto p : PList)
{
Pallet_State.append(new Pallet(*p));
}
}

Weird behaviour encapsulated std::list in std::vector sometimes

I am working on a RTS game. This game has buildings and actors. A building or actor is an instance of the buildings or actors class. These instances are stored in a std::vector for easy interaction by iterator id.
The actors and buildings can do tasks, these are stored in an std::list instantiated by the class in other words that list lives inside std::vector<actors>. The problem now is that every so often when information about this tasks needs retrieval or the tasks has to be removed from the list the program will crash with either "access violation", "trying to pop_front on empty list" or "trying to call front() on a empty list". Even though the previous line of code was a double check to see if the list was indeed not empty! It is also hard to reproduce because it happens every so often.
I suspect that someway somehow iterators or pointers get invalidated, since the list lives in a vector. I tried circumventing that by reserving space for 1600 units and 1600 buildings. However the problem still persists.
if (!this->listOfOrders.empty()) {
switch (this->listOfOrders.front().orderType) { //error here calling front() on empty list
case stackOrderTypes::stackActionMove:
this->updateGoal(this->listOfOrders.front().goal, 0);
break;
case stackOrderTypes::stackActionGather:
this->updateGoal(this->listOfOrders.front().goal, 0);
this->setGatheringRecource(true);
break;
}
}
I am really at a loss here.
Simplified class construct to illustrate:
enum class stackOrderTypes
{
stackActionMove,
stackActionGather
//and so on...
};
struct goal
{
int x;
int y;
}
struct orderStack
{
cords goal;
stackOrderTypes orderType;
};
class actors
{
public:
//other functions here
void doNextStackedCommand();
void stackOrder(cords Goal, stackOrderTypes orderType);
private:
//other stuff goes here
std::list<orderStack> listOfOrders;
};
std::vector<actors> listOfActors; //all actors live in here
To know what problem is causing this error, you need first to find exactly where in your code the problem is happening.
However, from what you describe I see a possible cause of you problem : items removals.
I suppose you have some loops iterating over your orders, and under some conditions you remove orders from your order list. Check if your code looks like this :
for (auto it = orderList.begin(); it != orderList.end(); ++it)
{
// Some code there
if (OrderIsFinished() == true)
orderList.erase(it);
// Some code there
}
This is a common mistake. After calling erase, the item pointed by the iterator it gets removed and it is invalidated. To keep iterators consistent after a removal, you need to change the way you iterate through all elements :
auto it = orderList.begin();
while (it != orderList.end())
{
// Some code there
if (OrderIsFinished() == true)
it = orderList.erase(it);
else
++it;
}
It was in fact a data race issue. There was a std::async updater running for builds while the update function was also called in the main thread!

How to implement a list feature that limits options based on other selected options?

This is a general design question to a problem I am facing.
I am implementing a UI list of items where the user can select multiple items at once. Some of the options, however, are grouped in a sense that only one of those items may be selected at once due to business logic. E.g. If list contains items, A, B, C there needs to be a way to specify the logic where either A, B or C can be selected at once.
I have considered implementing within the class design a variable which contains list of the other items which are grouped and so cannot be selected if any in that list are already selected. However, this seems like a difficult thing to maintain because if there are 3 items in a group, all 3 must be updated if an additional item is added to that group.
What would be a better design solution to this problem?
One option would be to have an std::shared_ptr<unsigned> group_selection as a member in each selectable object. Then if two objects, say a and c must not be selected at the same time have the shared pointer point to the same object. That way, selecting a and updating ++*a.group_selection will enable you to check if *c.group_selection is zero before selecting c.
Example:
#include <memory>
class Selectable {
private:
bool selected = false;
std::shared_ptr<unsigned> group_selection;
public:
Selectable() : group_selection(std::make_shared<unsigned>(0)) {}
~Selectable() {
unselect();
}
void add_to_group(Selectable const& of) {
group_selection = of.group_selection;
}
bool can_select() const {
return *group_selection == 0;
}
void select() {
if (!selected)
++*group_selection;
selected = true;
}
void unselect() {
if (selected)
--*group_selection;
selected = false;
}
};

What datastructure best to use to aggregate data?

I have a tree of things that get asked what data they have, coming from the root.
Technically I have lists of items and I want to put these lists together and also sometimes check through all lists if the items contained in them changed since the last call I made to them.
Right now I use a function akin to
virtual std::vector<MyProject::Item *> get_stuff(param_t query);
With an implementation often times akin to
std::vector<MyProject::Item *> get_stuff(param_t query) {
std::vector<MyProject::Item *> result;
for(Item *i : this->inner_collection) {
std::vector<MyProject::Item *> inner = i->get_stuff(query);
result.insert(result.end(), inner.start(), inner.end());
}
return result;
}
As seen above I use a std::vector to pass this along. Is there a better collection type to do these queries? One that is way better and easier to program with when needing to append stuff to one another quite often?

Properties editor design pattern?

Warning: This is super in-depth. I understand if you don't even want to read this, this is mostly for me to sort out my thought process.
Okay, so here's what I'm trying to do. I've got these objects:
When you click on one (or select several) it should display their properties on the right (as shown). When you edit said properties it should update the internal variables immediately.
I'm trying to decide on the best way to do this. I figure the selected objects should be stored as a list of pointers. It's either that, or have an isSelected bool on each object, and then iterate over all of them, ignoring the non-selected ones, which is just inefficient. So we click on one, or select several, and then the selectedObjects list is populated. We then need to display the properties. To keep things simple for the time being, we'll assume that all objects are of the same type (share the same set of properties). Since there aren't any instance-specific properties, I figure we should probably store these properties as static variables inside the Object class. Properties basically just have a name (like "Allow Sleep"). There is one PropertyManager for each type of property (int,bool,double). PropertyManagers store all the values for properties of their respective type (this is all from the Qt API). Unfortunately, because PropertyManagers are required to create Properties I can't really decouple the two. I suppose this means that I have to place the PropertyManagers with the Properties (as static variables). This means we have one set of properties, and one set of property managers to manage all the variables in all the objects. Each property manager can only have one callback. That means this callback has to update all the properties of its respective type, for all objects (a nested loop). This yields something like this (in pseudo-code):
function valueChanged(property, value) {
if(property == xPosProp) {
foreach(selectedObj as obj) {
obj->setXPos(value);
}
} else if(property == ...
Which already bothers me a little bit, because we're using if statements where we shouldn't need them. The way around this would be to create a different property manager for every single property, so that we can have unique callbacks. This also means we need two objects for each property, but it might be a price worth paying for cleaner code (I really don't know what the performance costs are right now, but as I know you'll also say -- optimize when it becomes a problem). So then we end up with a ton of callbacks:
function xPosChanged(property, value) {
foreach(selectedObj as obj) {
obj->setXPos(value);
}
}
Which eliminates the entire if/else garbage but adds a dozen more event-listeners. Let's assume I go with this method. So now we had a wad of static Properties, along with their corresponding static PropertyManagers. Presumably I'd store the list of selected objects as Object::selectedObjects too since they're used in all the event callbacks, which logically belong in the object class. So then we have a wad of static event callbacks too. That's all fine and dandy.
So now when you edit a property, we can update the interal variables for all the selected objects via the event callback. But what happens when the internal variable is updated via some other means, how do we update the property? This happens to be a physics simulator, so all the objects will have many of their variables continuously updated. I can't add callbacks for these because the physics is handled by another 3rd party library. I guess this means I just have to assume all the variables have been changed after each time step. So after each time step, I have to update all the properties for all the selected objects. Fine, I can do that.
Last issue (I hope), is what values should we display when multiple objects are selected an there is an inconsistency? I guess my options are to leave it blank/0 or display a random object's properties. I don't think one option is much better than the other, but hopefully Qt provides a method to highlight such properties so that I can at least notify the user. So how do I figure out which properties to "highlight"? I guess I iterate over all the selected objects, and all their properties, compare them, and as soon as there is a mismatch I can highlight it. So to clarify, upon selected some objects:
add all objects to a selectedObjects list
populate the properties editor
find which properties have identical values and update the editor appropriately
I think I should store the properties in a list too so that I can just push the whole list onto the properties editor rather than adding each property individually. Should allow for more flexibility down the road I think.
I think that about covers it... I'm still not certain how I feel about having so many static variables, and a semi-singleton class (the static variables would be initialized once when the first object is created I guess). But I don't see a better solution.
Please post your thoughts if you actually read this. I guess that's not really a question, so let me rephrase for the haters, What adjustments can I make to my suggested design-pattern to yield cleaner, more understandable, or more efficient code? (or something along those lines).
Looks like I need to clarify. By "property" I mean like "Allow Sleeping", or "Velocity" -- all objects have these properties -- their VALUES however, are unique to each instance. Properties hold the string that needs to be displayed, the valid range for the values, and all the widget info. PropertyManagers are the objects that actually hold the value. They control the callbacks, and the value that's displayed. There is also another copy of the value, that's actually used "internally" by the other 3rd party physics library.
Trying to actually implement this madness now. I have an EditorView (the black area drawing area in the image) which catches the mouseClick event. The mouseClick events then tells the physics simulator to query all the bodies at the cursor. Each physics body stores a reference (a void pointer!) back to my object class. The pointers get casted back to objects get pushed onto a list of selected objects. The EditorView then sends out a signal. The EditorWindow then catches this signal and passes it over to the PropertiesWindow along with the selected objects. Now the PropertiesWindow needs to query the objects for a list of properties to display... and that's as far as I've gotten so far. Mind boggling!
The Solution
/*
* File: PropertyBrowser.cpp
* Author: mark
*
* Created on August 23, 2009, 10:29 PM
*/
#include <QtCore/QMetaProperty>
#include "PropertyBrowser.h"
PropertyBrowser::PropertyBrowser(QWidget* parent)
: QtTreePropertyBrowser(parent), m_variantManager(new QtVariantPropertyManager(this)) {
setHeaderVisible(false);
setPropertiesWithoutValueMarked(true);
setIndentation(10);
setResizeMode(ResizeToContents);
setFactoryForManager(m_variantManager, new QtVariantEditorFactory);
setAlternatingRowColors(false);
}
void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &value) {
if(m_propertyMap.find(property) != m_propertyMap.end()) {
foreach(QObject *obj, m_selectedObjects) {
obj->setProperty(m_propertyMap[property], value);
}
}
}
QString PropertyBrowser::humanize(QString str) const {
return str.at(0).toUpper() + str.mid(1).replace(QRegExp("([a-z])([A-Z])"), "\\1 \\2");
}
void PropertyBrowser::setSelectedObjects(QList<QObject*> objs) {
foreach(QObject *obj, m_selectedObjects) {
obj->disconnect(this);
}
clear();
m_variantManager->clear();
m_selectedObjects = objs;
m_propertyMap.clear();
if(objs.isEmpty()) {
return;
}
for(int i = 0; i < objs.first()->metaObject()->propertyCount(); ++i) {
QMetaProperty metaProperty(objs.first()->metaObject()->property(i));
QtProperty * const property
= m_variantManager->addProperty(metaProperty.type(), humanize(metaProperty.name()));
property->setEnabled(metaProperty.isWritable());
m_propertyMap[property] = metaProperty.name();
addProperty(property);
}
foreach(QObject *obj, m_selectedObjects) {
connect(obj, SIGNAL(propertyChanged()), SLOT(objectUpdated()));
}
objectUpdated();
}
void PropertyBrowser::objectUpdated() {
if(m_selectedObjects.isEmpty()) {
return;
}
disconnect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)),
this, SLOT(valueChanged(QtProperty*, QVariant)));
QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
bool diff;
while(i.hasNext()) {
i.next();
diff = false;
for(int j = 1; j < m_selectedObjects.size(); ++j) {
if(m_selectedObjects.at(j)->property(i.value()) != m_selectedObjects.at(j - 1)->property(i.value())) {
diff = true;
break;
}
}
if(diff) setBackgroundColor(topLevelItem(i.key()), QColor(0xFF,0xFE,0xA9));
else setBackgroundColor(topLevelItem(i.key()), Qt::white);
m_variantManager->setValue(i.key(), m_selectedObjects.first()->property(i.value()));
}
connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)),
this, SLOT(valueChanged(QtProperty*, QVariant)));
}
With a big thanks to TimW
Did you have a look at Qt's (dynamic) property system?
bool QObject::setProperty ( const char * name, const QVariant & value );
QVariant QObject::property ( const char * name ) const
QList<QByteArray> QObject::dynamicPropertyNames () const;
//Changing the value of a dynamic property causes a
//QDynamicPropertyChangeEvent to be sent to the object.
function valueChanged(property, value) {
foreach(selectedObj as obj) {
obj->setProperty(property, value);
}
}
Example
This is an incomplete example to give you my idea about the property system.
I guess SelectableItem * selectedItem must be replaced with a list of items in your case.
class SelectableItem : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName );
Q_PROPERTY(int velocity READ velocity WRITE setVelocity);
public:
QString name() const { return m_name; }
int velocity() const {return m_velocity; }
public slots:
void setName(const QString& name)
{
if(name!=m_name)
{
m_name = name;
emit update();
}
}
void setVelocity(int value)
{
if(value!=m_velocity)
{
m_velocity = value;
emit update();
}
}
signals:
void update();
private:
QString m_name;
int m_velocity;
};
class MyPropertyWatcher : public QObject
{
Q_OBJECT
public:
MyPropertyWatcher(QObject *parent)
: QObject(parent),
m_variantManager(new QtVariantPropertyManager(this)),
m_propertyMap(),
m_selectedItem(),
!m_updatingValues(false)
{
connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), SLOT(valueChanged(QtProperty*,QVariant)));
m_propertyMap[m_variantManager->addProperty(QVariant::String, tr("Name"))] = "name";
m_propertyMap[m_variantManager->addProperty(QVariant::Int, tr("Velocity"))] = "velocity";
// Add mim, max ... to the property
// you could also add all the existing properties of a SelectableItem
// SelectableItem item;
// for(int i=0 ; i!=item.metaObject()->propertyCount(); ++i)
// {
// QMetaProperty metaProperty(item.metaObject()->property(i));
// QtProperty *const property
// = m_variantManager->addProperty(metaProperty.type(), metaProperty.name());
// m_propertyMap[property] = metaProperty.name()
// }
}
void setSelectedItem(SelectableItem * selectedItem)
{
if(m_selectedItem)
{
m_selectedItem->disconnect( this );
}
if(selectedItem)
{
connect(selectedItem, SIGNAL(update()), SLOT(itemUpdated()));
itemUpdated();
}
m_selectedItem = selectedItem;
}
private slots:
void valueChanged(QtProperty *property, const QVariant &value)
{
if(m_updatingValues)
{
return;
}
if(m_selectedItem && m_map)
{
QMap<QtProperty*, QByteArray>::const_iterator i = m_propertyMap.find(property);
if(i!=m_propertyMap.end())
m_selectedItem->setProperty(m_propertyMap[property], value);
}
}
void itemUpdated()
{
m_updatingValues = true;
QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
while(i.hasNext())
{
m_variantManager->next();
m_variantManager->setValue(
i.key(),
m_selectedItem->property(i.value()));
}
m_updatingValues = false;
}
private:
QtVariantPropertyManager *const m_variantManager;
QMap<QtProperty*, QByteArray> m_propertyMap;
QPointer<SelectableItem> m_selectedItem;
bool m_updatingValues;
};
Calm down, your code has not O(n^2) complextity. You have a nested loop, but only one counts to N (the number of objects), the other counts to a fixed number of properties, which is not related to N. So you have O(N).
For the static variables, you write "there aren't any instance-specific properties", later you write about updates of the individual properties of your objects, which are exactly instance-specific properties. Maybe you are confusing the "class Properties" (which is of course shared among all properties) with the individual properties? So I think you don't need static members at all.
Do you want to display changes to the objects only if they appear, or do you want a continuos display? If your hardware is able to handle the latter, I would recommend going that way. In that case, you have to iterate over all objects anyway and update them along the way.
Edit: The difference is that in the former (update on change) the drawing is initiated by the operation of changing the values, for example a object movement. For the latter, a continuos display, you would add a QTimer, which fires say 60 times a second and calls a SLOT(render()) which does the actual rendering of all objects. Depending on the rate of changes this may actually be faster. And it is probably easier to implement.
Another possibilty is let Qt handle the whole drawing, using a Graphics View, which handles the objects-to-draw internally in a very efficient tree structure. Take a look at
http://doc.trolltech.com/4.5/graphicsview.html
If you want to display only the changes, you could use individual callbacks for each properties value. Each time the value of a property is changed (in this case making the properties vlaues private and using setSomeThing(value)), you call the update function with an emit(update()). If you are absolutly concernd about emit being slow, you could use "real" callbacks via function pointers, but I don't recommend that, Qt's connect/signal/slot is so much easier to use. And the overhead is in most cases really neglible.