Werte aus QTreeView auslesen

Alles rund um die Programmierung mit Qt
Antworten
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Werte aus QTreeView auslesen

Beitrag von dieter_ »

Mit dem Signal clicked(QmodelIndex) kann ich den mit der Maus angewählten Wert auslesen.
Mit der Tastatur die Werte auslesen habe ich Probleme.
Ich möchte die Werte auslesen können, wenn die Auf- und Abtasten gedrückt werden. Die Werte der ausgewählte Zeile will ermitteln ich ohne die Enter-Taste zu drücken.
Das Signal activated(QmodelIndex) wird es dann ausgelöst, wenn ich die Enter Taste drücke.
Bei den Pfeiltasten down und up wird aber kein Signal ausgelöst.
Ich habe dann versucht mit keyPressEvent(QKeyEvent *event) die Betätigung der Auf und Ab-Tasten abzufangen und auszuwerten.
Esc, Str+C, Funktionstasten beispielsweise kann ich abfangen. Bei der Ab-Tasten wird aber nur dann ein Ereignis ausgelöst,
wenn im TreeViewdie unterste Zeile bereits markiert ist.
Wenn die oberste Zeile markiert ist, kann ich das Drücken der Auf-Taste auswerten.

Wie kann ich das Auslesen mit den Pfeiltasten verwirklichen ohne die Enter-Taste zu drücken?
Grüße aus Südbaden
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von veeman »

Du kannst an das currentChanged-Signal des unterliegenden Selection-Model:
treeView->selectionModel()->currentChanged anknüpfen um an das aktuellr Element zu gelangen.

Alternativ von QTreeView ableiten und currentChanged überschreiben.

currentChanged wird bei jeglicher User-Selektion, ob Maus oder Tastatur, getriggert.
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Re: Werte aus QTreeView auslesen

Beitrag von dieter_ »

Ich brauche noch Hilfe, wobei ich zugeben muss, dass meine Qt-Kenntnisse mitelmäßig sind.
Das Auslesen mache ich bislang über einen zusätzlichen pushButton_folder. Dann verbinde ich diesen Button mit QTreeview mit dem Signal clicked(QModelIndex). (Ein Signal currentChanged existiert bei QTreeView leider nicht).Der Empfänger ist der genannte pushButton_folder mit dem Slot(click). In mainWindow.ccp gebe ich diese Befehlszeile ein:

Code: Alles auswählen

connect(pushButton_folder, SIGNAL(clicked() ), this, SLOT(folder_einlesen()));
und kann dann in folder_einlesen() den Wert ermitteln.
Wie müsste der Code in mainwindow.cpp aussehen, damit ich mit selectionModel() und currentChanged() an die Werte komme?
Vielen Dank für Deine Vorschläge.

Grüße aus Südbaden
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von veeman »

So ganz konnte ich dir nicht folgen, du liest mit QTreeView::clicked die aktuelle Selektion aus und wertest diese in deinem QPushButton::clicked event diesen aus?

Anyway, um an das aktuell ausgewählte Element zu kommen musst du wie schon angedeutet das entsprechende Signal des unterliegenden SelectionModels verknüpfen:

Code: Alles auswählen

connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(on_treeView_currentChanged(QModelIndex, QModelIndex)));
Achtung:
Wenn du die Slot-Signatur so wie ich es definiert hast (on_controName_signalName) wird ggf. das Signal mittels Auto-Connect-Feature verknüpft und die connect Anweisung bewirkt das die Funktion doppelt aufgerufen wird.
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Re: Werte aus QTreeView auslesen

Beitrag von dieter_ »

Bin leider nicht so richtig weitergekommen. Mir gelingt es nicht ohne Umweg über einen zusätzlichen Button an die Werte im TreeView zu kommen.
Ich habe das Programm so reduziert, dass es nur noch um das Auslesen der Werte aus dem TreeView geht:
Die mainwindow.h hat diesen Inhalt:

Code: Alles auswählen

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>
#include <QFileSystemModel> 
#include "ui_Main.h"

class MWindow : public QDialog,
                private Ui::Dialog {
    Q_OBJECT

public:
   MWindow();
   ~MWindow() {}
           
public slots: 
   void folder_einlesen();
private:
    QFileSystemModel *dirModel;
    QItemSelectionModel *selModel;
};
#endif
Der Inhalt der mainwindow.cpp ist folgendermaßen:

Code: Alles auswählen

#include <QtGui>
#include "mainWindow.h"

MWindow::MWindow()
{
   setupUi(this);
   dirModel = new QFileSystemModel;
   selModel = new QItemSelectionModel(dirModel);
   treeView->setModel(dirModel);
   treeView->setSelectionModel(selModel);
   treeView->setEnabled(true);
   QModelIndex cwdIndex = dirModel->index(QDir::rootPath());
   dirModel->setRootPath(QDir::rootPath());
   treeView->setRootIndex(cwdIndex);
   connect(pushButton, SIGNAL( clicked() ), this, SLOT(folder_einlesen()));
   
connect(treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this,SLOT(on_treeView_currentChanged(QModelIndex, QModelIndex)));
}

void MWindow::folder_einlesen() {
QString folder;
   QModelIndex index = treeView->currentIndex();
   QModelIndexList indexes = selModel->selectedIndexes();
   folder =  (dirModel->filePath(index));
qDebug() << "folder einlesen" << folder;
}
Die ui-Datei habe ich mit dem Designer erstellt und mit dem Designer diese Sender Slot Befehle gebildet:

Code: Alles auswählen

<sender>treeView</sender>
   <signal>clicked(QModelIndex)</signal>
   <receiver>pushButton</receiver>
   <slot>click()</slot>
Mit diesem Code kann ich mit dem Mausclick die Werte aus TreeView auslesen.
Der von Dir angegebene Code habe ich in mainwindwow.cpp eingefügt. Mit ui.treeview erhalte ich diese Fehlermeldung:

Code: Alles auswählen

mainWindow.cpp:17:9: error: ‘ui’ was not declared in this scope
 connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this,SLOT(on_treeView_currentChanged(QModelIndex, QModelIndex)));
Beim kompilieren ohne ui.treeview wird die ausführbare Datei erstellt.
Beim Ausführen erhalte ich diese Fehlermeldung:

Code: Alles auswählen

QObject::connect: No such slot MWindow::on_treeView_currentChanged(QModelIndex, QModelIndex)
QObject::connect:  (receiver name: 'Dialog')
Wo muss ich den Code ergänzen dass das Programm funktioniert.
Für Deine Hilfe bin ich schon sehr dankbar und eine weitere Information wäre super.

Grüße aus Südbaden
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von veeman »

Der namespace ui wird von meiner IDE/Einstellungen generiert. Je nach dem welche du verwendest, fällt dieser bei dir weg.

Du musst ansonsten einen Slot on_treeView_currentChanged definieren. Sonst weiß der nicht welche Funktion er aufrufen soll:

Code: Alles auswählen

public slots:
    void on_treeView_currentChanged(QModelIndex &current, QModelIndex &previous) ;

Code: Alles auswählen

void MWindow::on_treeView_currentChanged(QModelIndex &current, QModelIndex &previous)
{
// Tue etwas mit current, z. B
// qDebug() << current->data().toString();
} 
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Re: Werte aus QTreeView auslesen

Beitrag von dieter_ »

Ich habe mainwindow.h und mainwindow.cpp mit den von Dir angegebenen Zeilen ergänzt.
Die Kompilierung erfolgt ohne Fehlermeldung.
Beim Starten des Programm erhalte ich diese Hinweise:

Code: Alles auswählen

QMetaObject::connectSlotsByName: No matching signal for on_treeView_currentChanged(QModelIndex&,QModelIndex&)
QObject::connect: No such slot MWindow::on_treeView_currentChanged(QModelIndex &current, QModelIndex &previous)
QObject::connect:  (receiver name: 'Dialog')
Ändere ich mit der Maus das Auswählen im TreeView kann ich die Werte auslesen. Beim Ändern der Werte mit der Tastatur wird die Funktion void MWindow::on_treeView_currentChanged(QModelIndex &current, QModelIndex &previous) nicht angesprochen.

Ich habe gegoogelt (korrekt mit duckduckgo.com) und Deine Hinweise werden eigentlich bestätigt. Dennoch klappt es nicht. Hast Du eventuell noch einen Tipp?
Grüße aus Südbaden
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von veeman »

Der slot wird schon mal vom Autocennct feature erkannt (QMetaObject::connectSlotsByName) : kann an dieser stelle jedoch ignoriert werden.

Bin mir nicht sicher warjm der den fehler schmeisst, aber ich vermute, dass er sich an den Argumentnamen beim connect aufruf stört. Einfach mal current und previous weglassen.

Code: Alles auswählen

connect(treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex&, QModelIndex&)), this,SLOT(on_treeView_currentChanged(QModelIndex&, QModelIndex&)));
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Re: Werte aus QTreeView auslesen

Beitrag von dieter_ »

Das hatte ich schon probiert. Klappt leider nicht.
Werde mal die GUI nicht mit dem Designer sondern durch Code konstruieren. Mal schauen was rauskommt. Irgendwie scheint der Kontakt zwischen dem QTreeView in der GUI und dem Code in mainwindow.h und mainwindow.cpp nicht zu klappen.
Grüße aus Südbaden
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von Christian81 »

Das Signal ist "currentChanged(const QModelIndex &current, const QModelIndex &previous)" nicht "currentChanged(QModelIndex &current, QModelIndex &previous)".
Am sinnvollsten ist es, die neue Signal/Slot syntax zu benutzen, dann wirft der Compiler schon Fehler wenn die Argumente nicht passen: https://wiki.qt.io/New_Signal_Slot_Syntax/de
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von veeman »

Also die folgende (alte String basierte) Variante:

Code: Alles auswählen

connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(treeView_currentChanged(QModelIndex, QModelIndex)));
als auch die neue, von Christian81 erwähnte, Variante:

Code: Alles auswählen

connect(ui.treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MWindow::treeView_currentChanged);
funktioniert bei mir ohne Probleme.
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Re: Werte aus QTreeView auslesen

Beitrag von dieter_ »

Ich habe mit dem qtcreator ein neues Programm erstellt und auf dieser Basis den Code für das auslesen des QTreeView hinzugefügt.
Es funktioniert bei mir nur dieser Code:

Code: Alles auswählen

connect(ui.treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::treeView_currentChanged);
Da dem Programm current und previous nicht bekannt ist lese ich die Werte so aus:

Code: Alles auswählen

QString folder;
   QModelIndex index = ui->treeView->currentIndex();
   QModelIndexList indexes = selModel->selectedIndexes();
   folder =  (dirModel->filePath(index));
Da dieser Beitrag doch recht oft gelesen wurde gebe ich nachstehend den kompletten Code an, damit das Programm nachvollzogen werden kann.
Danke für Eure Mithilfe und Grüße aus Südbaden

Code von mainwindow.h

Code: Alles auswählen

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDialog>
#include <QDirModel>
#include <QTreeView>
#include <QFileSystemModel> 

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void pushButton_clicked();
    
private:
    Ui::MainWindow *ui;
    QDirModel *model;
    QFileSystemModel *dirModel;
    QItemSelectionModel *selModel;
};

#endif // MAINWINDOW_H
mainwindow.cpp:

Code: Alles auswählen

#include <QtGui>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QString homepath = QDir::homePath();
    QString rootpath = QDir::rootPath();
    dirModel = new QFileSystemModel;
    selModel = new QItemSelectionModel(dirModel);
    ui->treeView->setModel(dirModel);
    ui->treeView->setSelectionModel(selModel);
    ui->treeView->setEnabled(true);
    QModelIndex cwdIndex = dirModel->index(QDir::rootPath());
  // dirModel->setRootPath(QDir::rootPath());
    dirModel->setRootPath(QDir::homePath());
    ui->treeView->setRootIndex(cwdIndex);
    connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::pushButton_clicked);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::pushButton_clicked()
{
QString folder;
   QModelIndex index = ui->treeView->currentIndex();
   QModelIndexList indexes = selModel->selectedIndexes();
   folder =  (dirModel->filePath(index));
qDebug() << "folder einlesen index" << folder;
} 
main.cpp:

Code: Alles auswählen

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[]){
    QApplication a(argc, argv);
    MainWindow window;
    window.show();
    return a.exec();
}
Code der pro-Datei:

Code: Alles auswählen

#-------------------------------------------------
#
# Project created by QtCreator 2019-02-11T15:07:51
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = treeviewdirmodel
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui
und noch der Code der Oberfläche mainwindow.ui:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QTreeView" name="treeView">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>20</y>
      <width>361</width>
      <height>192</height>
     </rect>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>120</x>
      <y>110</y>
      <width>99</width>
      <height>27</height>
     </rect>
    </property>
    <property name="text">
     <string>dummy</string>
    </property>
   </widget>
   <zorder>pushButton</zorder>
   <zorder>treeView</zorder>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>400</width>
     <height>25</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections>
  <connection>
   <sender>treeView</sender>
   <signal>clicked(QModelIndex)</signal>
   <receiver>pushButton</receiver>
   <slot>click()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>89</x>
     <y>144</y>
    </hint>
    <hint type="destinationlabel">
     <x>349</x>
     <y>173</y>
    </hint>
   </hints>
  </connection>
 </connections>
</ui>
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von Christian81 »

Beide Beispiele von veeman funktionieren und sind korrekt.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
dieter_
Beiträge: 18
Registriert: 11. November 2012 12:16

Re: Werte aus QTreeView auslesen

Beitrag von dieter_ »

Bei mir funktionieren nun auch beide Möglichkeiten.
Noch diese Frage: Wie kannst Du den Wert auslesen? Die von mir angegebene Möglichkeit funktioniert in beiden Fällen.
Wäre interessant zu wissen wie Du das auslesen bewerkstelligst
Grüße aus Südbaden
veeman
Beiträge: 277
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Werte aus QTreeView auslesen

Beitrag von veeman »

Ich sehe gerade, dass du die Parameter gänzlich weggelassen hast. Das ist natürlich nicht Ziel des ganzen.

Hier die Header und Source Datei ohne schnik schnak von mir.

Header:

Code: Alles auswählen

#include <QtWidgets/QMainWindow>
#include "ui_mwindow.h"

class MWindow : public QMainWindow
{
	Q_OBJECT

public:
	MWindow(QWidget *parent = Q_NULLPTR);

private:
	Ui::MWindow ui;

public slots:
	void treeView_currentChanged(const QModelIndex &current, const QModelIndex &previous);
};
Source:

Code: Alles auswählen

#include "MWindow.h"
#include <qdirmodel.h>
#include <qdebug.h>

MWindow::MWindow(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	ui.treeView->setModel(new QDirModel(this));

	connect(ui.treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MWindow::treeView_currentChanged);
}

void MWindow::treeView_currentChanged(const QModelIndex &current, const QModelIndex &previous)
{
	QString displayValue = current.data(Qt::DisplayRole).toString();
	QString selectedFolder = qobject_cast<QDirModel*>(ui.treeView->model())->filePath(current);
	qDebug() << displayValue << selectedFolder;
}
Antworten