I'm currently looking to a way to get the name of the selected items of a QTreeWidget.
I have create multiple QTreeWidgetItems to generate a file browser-like.
I need to know how to get the name of the folder selected.
I have found the
this->MyTree->selectedItems();
to get it but I'm not able to store the feedback which is supposed to be a QList format.
Any examples on how to store the selectedItems list ?
From the Qt documentation: QTreeWidget Class Reference , QTreeWidgetItem Class Reference
selectedItems() is a function of QTreeWidget.
QList QTreeWidget::selectedItems () const
Returns a list of all selected non-hidden items.
text() is a function of QTreeWidgetItem
QString QTreeWidgetItem::text ( int column ) const
Returns the text in the specified column.
Define a list of QTreeWidgetItem to store return value of selectedItems() .
For each item in the list use text() function to get it's string.
QList<QTreeWidgetItem *> itemList;
itemList = this->MyTree->selectedItems();
foreach(QTreeWidgetItem *item, itemList)
{
QString str = item->text();
//str is what you want
}
{
...
connect(treeWidget, &QTreeWidget::itemClicked, this, &MyForm::onItemClicked);
connect(treeWidget, &QTreeWidget::itemActivated, this, &MyForm::onItemClicked);
}
void MyForm::onItemClicked(QTreeWidgetItem *item, int) {
if (item == item0) {
stackedWidget->setCurrentWidget(widget0);
}
else if (item == item1) {
stackedWidget->setCurrentWidget(widget1);
}
}
Related
I need to retrieve the text in the order in which they appear on the user form. I am trying as below:
QString line = "QLineEdit";
QString combo = "QComboBox";
QList<QWidget *> childWidgets = ui->frame_3->findChildren<QWidget *>();
QStringList data;
for(auto widget : childWidgets){
if(widget->metaObject()->className() == line || widget->metaObject()->className() == combo){
data.append(widget->text()); //append the text of the lineEdits and ComboBoxes to data
}
}
I get the following compile error from the above code:
"no member named 'text' in QWidget
Since you pointed out the QWidget base class does not have a text member function you will need to access the QComboBox and QLineEdit directly to get the current text.
QList<QWidget *> childWidgets = ui->frame_3->findChildren<QWidget *>();
QStringList data;
for(auto widget : childWidgets){
auto combo = dynamic_cast<QComboBox*>(widget);
if (combo) {
data << combo->currentText(); // currentText() returns the text from the combobox
}
else {
auto lineEdit = dynamic_cast<QLineEdit*>(widget);
if (lineEdit) {
data << lineEdit->text(); // A line edit has a text() member.
}
}
}
This code does not handle ordering. I believe the order is in the same order as added to the parent.
I have created a custom list model following this guide Creating a cusotm model for a QListView. I am able to show a list of custom objects (such as the Employee as in the example) but I don't know how to retrieve back the selected ones (can I retrieve back the "linked" objects directly?).
Maybe do I have to do something with this command:
myLV->selectionModel()->selectedIndexes();
But I don't really know how to retrieve back the original custom objects.
[EDIT]
So far I have solved retrieving back the object adding a custom method inside my custom list model:
Employee* MyEmployeeListModel::getAtSelectedIndex(const QModelIndex& index){
return employees_.at(index.row());
}
And then calling this on the main window:
QModelIndexList selectedRows;
QItemSelectionModel * selmodel = ui->employeesLV->selectionModel();
selectedRows = selmodel->selectedRows();
MyEmployeeListModel* currModel = dynamic_cast <MyEmployeeListModel*>(ui->employeesLV->model());
for (const QModelIndex & index : selectedRows){
Employee* item=currModel->getAtSelectedIndex(index);
if (item) {
// do something with the item
}
}
Now what I am willing to know is if this is the real best practice or not.
I'm using the following code with a QTreeView (ui->treeMessages), but this should work with a QListView as well:
QModelIndexList selectedRows;
QItemSelectionModel * selmodel = ui->treeMessages->selectionModel();
selectedRows = selmodel->selectedRows();
for (const QModelIndex & index : selectedRows)
{
const QModelIndex sourceIndex = m_sortFilterModel->mapToSource(index);
ItemData * item = sourceIndex.internalPointer();
if (item) {
// do something
}
}
I'm making a Qt5.7 application where I am populating a QListView after reading stuff from a file. Here's the exact code of it.
QStringListModel *model;
model = new QStringListModel(this);
model->setStringList(stringList); //stringList has a list of strings
ui->listView->setModel(model);
ui->listView->setEditTriggers(QAbstractItemView::NoEditTriggers); //To disable editing
Now this displays the list just fine in a QListView that I have set up. What I need to do now is to get the string that has been double clicked and use that value elsewhere. How do I achieve that?
What I tried doing was to attach a listener to the QListView this way
... // the rest of the code
connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(fetch()));
...
And then I have the function fetch
void Window::fetch () {
qDebug() << "Something was clicked!";
QObject *s = sender();
qDebug() << s->objectName();
}
However the objectName() function returns "listView" and not the listView item or the index.
The signal already provides you with a QModelIndex which was clicked.
So you should change your slot to this:
void Window::fetch (QModelIndex index)
{
....
QModelIndex has now a column and a row property. Because a list has no columns you are interessted in the row. This is the index of the item clicked.
//get model and cast to QStringListModel
QStringListModel* listModel= qobject_cast<QStringListModel*>(ui->listView->model());
//get value at row()
QString value = listModel->stringList().at(index.row());
You should add the index as parameter of your slot. You can use that index to access the list
Your code should be some thing like this.
void Window::fetch (QModelIndex index) {
/* Do some thing you want to do*/
}
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.
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).