QT add object pointer in a pointer list - list

I would like to add my parentWidget in a pointer list QList<QGraphicsWidget*> items from another class.
How can I add parentWidget in the items list and delete the parentWidget right after ?
Here is my code:
void DiagramScene::insertWidget(DiagramItem::DiagramType diagramtype)
{
QGraphicsWidget * parentWidget = new QGraphicsWidget;
//some code
connect(this,SIGNAL(sendToItemList(QGraphicsWidget*)),diagramitem,SLOT(addToItemList(QGraphicsWidget*)));
emit this->sendToItemList(parentWidget);
}
and this is my slot:
void DiagramItem::addToItemList(QGraphicsWidget* widget)
{
items.append(widget);
}
My actual code gives me this by each insertWidget call :
first call: items = 1 item
second call: items = 3 items
third call: items = 6 items
fourth call: items = 10 items

Related

Show Last element in QListView

It sounds trivial, but I could not find the function to show the last added element in a QListView.
It works with a model
// Create model
model = new QStringListModel(this);
// Make data
QStringList List;
// Populate our model
model->setStringList(List);
// Glue model and view together
listView->setModel(model);
Elements are added with
void WidgetMessageList::addString(const QString & message)
{
if(model->insertRow(model->rowCount())) {
QModelIndex index = model->index(model->rowCount() - 1, 0);
model->setData(index, message);
}
}
In this function the shown element should also be the last.
QAbstractItemView::scrollTo
Scrolls the view if necessary to ensure that the item at index is
visible. The view will try to position the item according to the given
hint.
http://doc.qt.io/archives/qt-4.8/qabstractitemview.html#scrollTo
Create a class attibute to hold the last index
Connect QAbstractItemModel::rowsInserted to a slot in your application
In the slot update the index accordingly

QT - Can I dynamically point to GUI's labels using a variable passed into a method?

I'm creating an inventory and want to reference my inventory Forms QLabels with the name of the item passed into my method.
The QLabels and the names of the items are the same so I wanted to reduce if statements by referencing a QLabel depending on the name of the item passed in.
void Zork::on_btnTake_clicked()
{
Item *item = new Item(ui->takeItem->currentText().toStdString());
Colin->addItemToInventory(item);
inventory_screen->addItem(item->getDescription()); //Enables the Item in the Inventory
currentRoom->deleteItem(item);
ui->takeItem->removeItem(ui->takeItem->currentIndex()); //Only remove the item in the foreground of combobox at the time take button was clicked
}
Calls this Method addItemToInventory(item):
void Inventory_Ui:: addItem(string itemName){
myUi->itemName->setText(QString::fromStdString(itemName));
}
I am unable to do so as itemName is not a member of Ui, although itemName does contain members of Ui.
Example:
In my Inventory_Ui Form I have 6 labels, one named broken_bottle. I want to pass broken_bottle into the method's parameter itemName and them use that as a reference so at run-time it would look like myUi->broken_bottle->setText...
I think I follow what you are asking to do. I would access it with findChild or findChildren.
http://doc.qt.io/qt-5/qobject.html#findChild
http://doc.qt.io/qt-5/qobject.html#findChildren
QList <QLabel *> labels = ui->myForm()->findChildren<QLabel*>();
QLabel* targetLabel = 0;
foreach(QLabel * label, labels)
{
if(label->text() == ui->takeItem->currentText())
{
targetLabel = label;
break;
}
}
if(targetLabel != 0)
{
// ... do something with targetLabel
}
or...
QList <QLabel *> labels = ui->myForm()->findChildren<QLabel*>();
foreach(QLabel * label, labels)
label->setObjectName(label->text());
// later
QLabel * targetLabel = ui->myForm()->findChild<QLabel*>("text of label");
if(targetLabel)
// use it
Or if you are connecting all these labels to the same slot, you can figure some of it out using the sender static method.
http://doc.qt.io/qt-5/qobject.html#sender
void MainWindow::on_takeItem_currentTextChanged()
{
QLabel* targetLabel = qobject_cast<QLabel*>QObject::sender();
if(targetLabel)
// do something with it
}
Hope that helps.

Getting variable from widget in a QListWidget

I have a custom QWidget class called VideoWidget. Its source file looks something like this:
VideoWidget::VideoWidget(QWidget *parent, string test) :
QWidget(parent)
{
pathname=test;
QLabel *label= new QLabel(pathname.c_str(), this);
//...
}
string VideoWidget::getFilePath(){
return pathname;
}
In my MainWindow class I add the VideoWidget to a QListWidget through looping through a xml file and getting the string argument from that file like this:
QDomNode node = rootXML.firstChild();
while( !node.isNull() )
{
if( node.isElement() )
{
QDomElement element = node.toElement();
VideoWidget* mytest = new VideoWidget(this, element.attribute( "Pathname", "not set").toStdString());
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(150,100));
ui->myList->addItem(item);
ui->myList->setItemWidget(item,mytest);
}
node = node.nextSibling();
}
This correctly fills my QListWidget with the VideoWidget where all the labels have a different value.
Now I'd like to get the pathname variable everytime I doubleclick on a item in the QListWidget like this:
connect(ui->myList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(playClip(QModelIndex)));
void MainWindow::playClip(QModelIndex index){
QListWidgetItem* item = ui->myList->itemAt(0,index.row());
VideoWidget* widget = dynamic_cast<VideoWidget*>(ui->myList->itemWidget(item));
cout << widget->getFilePath() << endl;
}
My problem is that widget->getFilePath() always returns the same value for every clicked widget. It is the value of the first time I set pathname=test;. What am I missing here?
This is probably mistake:
QListWidgetItem* item = ui->myList->itemAt(0,index.row());
Method "itemAt" takes x and y coordinates, not indexes. Use "takeItem" instead.
Next thing I want to say is that this part:
ui->myList->itemWidget(item)
is useless. You can convert "item" directly.
And last - use qobject_cast since you use Qt. And never use dynamic_case (especially when you anyway do not check result against NULL).

empty row in QTreeWidget after item delete

I have created a QTreeWidget with Qt Creator and filled it.
When i delete an item from the tree,an empty line moves down to the end of the tree.
When i then add to the tree, the item adds below the empty line.
How do i get rid of this empty line?
Image: http://picpaste.com/gpa-GNtd84Ev.PNG
void Gpa::on_removeButton_clicked()
{
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
item = ui->treeWidget->currentItem();
QString txt = item->text(0);
//search vector for item
int i;
for(i = 0; i < vec.size(); i++)
if(vec.at(i)->getCode() == txt)
break;
vec.erase(vec.begin() + i);
int index = ui->treeWidget->indexOfTopLevelItem(item);
ui->treeWidget->takeTopLevelItem(index);
}
If you are removing a top level item, you should take a look at this method:
QTreeWidgetItem * QTreeWidget::takeTopLevelItem ( int index )
Otherwise, if you are removing a child you should get a pointer to the top level item (or a child of a top level item) and use:
QTreeWidgetItem * QTreeWidgetItem::takeChild ( int index )
EDIT (after OP has posted his code)
I believe the problem lies here:
QTreeWidgetItem *item = new QTreeWidgetItem(ui->treeWidget);
item = ui->treeWidget->currentItem();
You are allocating a new QTreeWidgetItem, and then you assign the item you want to remove to that pointer. So basically, you are creating new empty item and you remove the old one. Try to change your code to:
QTreeWidgetItem *item;
item = ui->treeWidget->currentItem();

qt QGraphicsScene additem

http://qt-project.org/doc/qt-4.8/qgraphicsscene.html#addItem
said
If the item is already in a different scene, it will first be removed from its old scene, and then added to this scene as a
top-level.
I want to keep the item in old scene.
how can I do this?
myscene1.addItem(item);
myscene2.addItem(item);// I don't want to remove item from myscene1
You can make a copy of the item :
myscene1.addItem(item);
myscene2.addItem(item->clone());
An item cannot occupy two scenes at the same time, in the way that you cannot be in two places at the same time.
The only way to do this is to make a copy of the item and place it in the second scene.
What you could do is to create a new class. e.g.
class Position
{
...
QPoinfF pos;
...
}
Then you can add that class to your item.
class Item : public QGraphicsItem
{
...
public:
void setSharedPos(Position *pos)
{
sharedPosition = pos;
}
//implement the paint(...) function
//its beeing called by the scene
void paint(...)
{
//set the shared position here
setPos(sharedPos);
//paint the item
...
}
protected:
void QGraphicsItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
//get the position from the item that could have been moved
//you could also check if the position actually changed
sharedPosition->pos = pos();
}
private
Position *sharedPostion;
...
}
You would no have to create two items and give them both the same pointer to a Position object.
Item *item1 = new Item;
Item *item2 = new Item;
Position *sharedPos = new Position;
item1->setSharedPos(sharedPos);
item2->setSharedPos(sharedPos);
myScene1->addItem(item1);
myScene2->addItem(item2);
They should no at least share their position in the scenes.
If this works then you'll have to change the Position class to fit your needs and it should be working.
I am not quite shure if setting the position in the paint() function works. But thats how I would try to synchronise the items. If it does not work then you'll have to look for another place to update the settings of the items.
Or you could give the items a Pointer to each other and let them change the positions/settings directly.
e.g.
class Item : public QGraphicsItem
{
...
void QGraphicsItem::mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
otherItem->setPos(pos());
}
...
void setOtherItem(Item *item)
{
otherItem = item;
}
private:
Item *otherItem;
}
Item *item1 = new Item;
Item *item2 = new Item;
item1->setOtherItem(item2);
item2->setOtherItem(item1);
myScene1->addItem(item1);
myScene2->addItem(item2);