Is there an equivalent of .NET's data binding in Qt?
I want to populate some combo boxes and other widgets with QStrings that refer to specific entities in my database. However, it would be cleaner if I could bind the data to these strings rather than either querying the database again based off of a new combobox selection or some other scheme based off of building my own index of entities that would be searched with the QStrings.
The best I've come up with is to derive these entities from QString and pushing them into the widgets this way, but I've yet to actually try it. I'm not sure if it will work the way I want it to, and it seems like a nasty hack.
If there is no data binding, what do you suggest?
Thank you.
As the user nonchalant mentioned in a comment you can use the QDataWidgetMapper class.
This is quite an easy way of binding arbitrary widgets to data that is stored in a QAbstractItemModel.
The example on the linked page shows in a few lines of code, how you can link your data model to common used input widgets:
QDataWidgetMapper *mapper = new QDataWidgetMapper;
mapper->setModel(model);
mapper->addMapping(mySpinBox, 0);
mapper->addMapping(myLineEdit, 1);
mapper->addMapping(myCountryChooser, 2);
mapper->toFirst();
One way is using Qt Model/View Classes (with base at QAbstractItemModel), but they need that you widget inherits QAbstractItemView (this is widgets like QTableView etc.).
If you want map Qt model to set of widgets, which haven't nothing common with QAbstractItemView you can use QDataWidgetMapper, which maps separate widget to Qt Model/View indexes. But anyway, as said Aaron Digulla, you must write some boiler plate code...
Well, for combobox specifically, you can set a model. For QObjects in general you can use the notify signal for properties to connect or other non-property related signals. I think there is another way to do it but I can't recall.
Related
Let's say i want to implement a library tool to manage different types of media. Therefore i have a base class Medium and derived classes e.g. Book and DVD which have additional properties.
My Problem is i can't figure out how to design the models correctly. I want to be able to show the media in one TableView with the basic properties from the Medium class as well as only the DVD's in another TableView with it's special properties from the derived class. And if i delete a DVD, i want it to be deleted in the Media table as well. Therefore i thought that they need to have the same data source.
What is the best way to achive this? Haven't found any example that illustrates that problem.
It can be simple one model which includes all columns from all three sources - medium, dvd, book.
In one view you make only columns of "medium" to be shown, other hidden, in another view you allows to show only "dvd" columns. But model object is just one applied as source to all views.
If one row is removed from the model, all views will be updated appropriate. Same about "add".
implement own Tree Item (take a look, for example: http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html#treeitem-class-definition)
add something like enum with types, add methods for your TreeItem to manipulate with types, then use proxy model(detailed example: http://doc.qt.io/qt-5/qsortfilterproxymodel.html#details) to sort data.
like:
enum Property {Book, DVD, Other };
class TreeItem
{
...
public:
Property GetProperty() const;
void setProperty(Property iProp);
...
};
Having a data stored in QVector<QVector<QString>> data; (or alternatively a list of lists of strings if you are a Pythonist) how should I subclass QAbstractItemModel to be able to display (read-only) such a simple structure in QTreeView? I would like to see something like this:
"group 1"
data[0][0]
data[0][1]
"group 2"
data[1][0]
data[1][1]
etc.
From the docs, I read that I should override index(), parent(), rowCount(), columnCount() and data(). What is the simplest possible implementation of these methods to achieve my goal?
To make the possible answer more enlightening, how can one subclass QAbstractItemModel without using the internal pointers (stored in QModelIndexes). All the examples I have seen use the underlying model in a form of a tree with nodes (having pointers to their children and parent nodes) which make is easy to wrap inside QAbstractItemModel using the internal pointers. But can we use QAbstractItemModel even without a tree/node-like underlying structure and without QModelIndex's internal pointers? My question is based on the docs saying that you can use internal pointers, but I have not yet seen any example without it.
It doesnt really matter which level of hierarchy you use, Create custom class node
with QVector(commonly QList<QString> QList is similar to std::deque) to store data, and pointer to its child nodes QList<Node*> children. Top level of hierarchy is invisible root node. Then process data in model.
Really great guide, with node and model examples:
http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html
You can basically copy-paste code and implement own setupModelData method.
I've looked in multiple places and cannot seem to find anything to work for my purpose.
I have this QComboBox that constantly changes (And could change after the program is completely finished).
To make it easier I made an Enum list for switch statements
public:
enum Race{
Race1,
Race2,
ect
}
The combo is filled with the same elements.
However, I want to make it even easier. So instead of changing the Combobox and changing the enum list, is there a way where all i have to do is add a new "race" to the enum list, that it will populate the combobox, so all i would have to do is a switch statement to handle new race?
Additional info:
I'm willing to put the enum list into a qstringlist.
I have Q_ENUMS (Race) set
Using Q_ENUMS will give you a way to iterate over your enum and add their enumerands to the combobox in a loop. However it will not give you the possibility to add a related GUI text for each enumerand. The enumerand name like it is written in your source code will be available only. Maybe your code side name is not what you want to see in your GUI as a text.
Remember that you can add any kind of QVariant supported user values to a combobox while you populate it with text strings... so you do not need to maintain an enumeration if there is some other kind key you can use instead.
I'm just starting with Qt and i'm having a doubt if the Model View is the right way to go here.
I have a following object which has to be persistent in some database:
Class Car:
{
private:
Qstring owner;
bool registered;
Qstring tires
}
The data should have the following view (it's a representation of a object Car):
My idea was to subclass the QAbstractItemView and try to adopt it to the customized QAbstractItemModel. The data is much better represented as objects than any of the default models mappings (list, table tree) which is why I can't see the benefits of using the Model View as shown in tutorial examples.
Would the model view be useful here, and what should the model/view costumization include?
You look like you're using standard QWidget UI elements. These already exist so there's no need to create them again using a QAbstractItemView. You can use the QtDesigner instead.
The Model-View pattern still applies though.
You can use the QStandardItemModel or your own custom QAbstractTableModel to handle the data storage and retrieval, and you can connect the UI with the model using the QDataWidgetMapper
Forgive me, I'm new to Flash Builder 4 and Actionscript 3 (actually, to programming as a whole beyond some very simplistic stuff). I have watched / read a bunch of tutorials, and started a project but now seem to have hit a wall. The answer is most likely simple, but seems to be alluding me.
How do I (or What approach should I take) to control visual elements, for instance, BorderContainer's, that I created dynamically?
As is, I have an Application containing a BorderContainer and a DataGrid. At runtime, 3 new BorderContainers (which are dragable, and resizeable) are created based on XML data that contains X & Y co-ordinates, and Height and Width values, and then added to the pre-existing BorderContainer. How would I go about getting the properties of these children BorderContainers to be displayed and remain up-to-date in the DataGrid (such as when they are moved/resized)?
My intentions in the future would be to have a custom component which displays a summary of these items in a separate area (think photoshop "layers" control, but much more simplistic), but wanted to get a better understanding of what's going on first.
Any input, documentation, examples, etc. is all appreciated. Again, I apologize for what may be an incredibly easy solution, or if any of my language is unclear, I'm new to this ^_^;
I would create an ArrayCollection of the BorderContainers with their various properties set (also make sure you call addElement on the parent BorderContainer). Make sure your ArrayCollection is declared as Bindable, then set it as the dataProvider for your DataGrid. Then specify the columns for your DataGrid based on whatever properties you want to display (height, width, etc). Now whenever the properties of the BorderContainers change, the DataGrid will automatically update.
Assuming a pure AS3 project, the best approach is to build a dictionary of your objects.
Let's also assume you've created identifiers for the components, or can easily create them at runtime.
var containers:Dictionary = new Dictionary();
private function _init():void
{
//some loop to create objects
containers[newObject.name] = newObject;
}
Later you can quickly access it by just grabbing the hashed index from the containers dictionary.
Now, assuming a Flex project, we have a few more approaches we can take:
DisplayObjectContainer implements getChildByName()
Group implements getElementAt, and numElements to iterate over, check names, and return value expected.
Personally, I still prefer the dictionary approach...
As for keeping things up to date, you can look into Binding (typically a Flex-only solution) or more appropriately investigate the events dispatched:
Event.RESIZE
Event.MOVE
etc.
In the handlers, just update your UI!
HTH, otherwise post more info and we'll see what we can figure out.