Jak w QListView odczytac indeks zaznaczonego elementu

0

kod aplikacji https://github.com/mariuszmaximus/ListView001

Mam wektor zawierający elementy typu "OneFile"
Dla użytkownika wyświetlam wartości z pola "nameOnScreen"
Użytkownik wybiera plik z listy i naciska ENTER

Jak odczytać indeks zaznaczonego elementu w QListView ? Chciałbym dla wybranego elementu odczytać wartość "filename"

Czy też nie tedy droga i muszę użyć czegoś innego zamiast "QStringListModel" ?

//
struct OneFile{
    QString nameOnScreen;
    QString filename;
    OneFile(QString _nameOnScreen, QString _filename )
    {
        nameOnScreen = _nameOnScreen;
        filename = _filename;
    }
};

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    std::vector <OneFile> files;
    QStringListModel *model;
protected:
    void keyPressEvent(QKeyEvent *event);
};
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    files.push_back( OneFile("opis1","plik1.txt")  );
    files.push_back( OneFile("opis2","plik2.txt")  );
    files.push_back( OneFile("opis3","plik3.txt")  );


    // Create model
    model = new QStringListModel(this);

    // Make data
    QStringList List;

    // Using a for loop with index
     for (std::size_t i = 0; i < files.size(); ++i)
     {
         //List.append(cfg->probes[i].c_str());
         List.append(files[i].nameOnScreen);
     }

     // Populate our model
     model->setStringList(List);

     // Glue model and view together
     ui->listView->setModel(model);
}

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



void Widget::keyPressEvent(QKeyEvent *event)
{
    if (event->key()==Qt::Key_Return)
    {
        QModelIndexList list =ui->listView->selectionModel()->selectedIndexes();
        QStringList slist;
        foreach(const QModelIndex &index, list){
            slist.append( index.data(Qt::DisplayRole ).toString());
        }
        qDebug() << slist.join(",");

    }

}
2

Nie powinieneś używać: void Widget::keyPressEvent(QKeyEvent *event)
Skorzystaj z właściwego sygnału, chyba chodzi ci o to: QAbstractItemView::edit(const QModelIndex &index)

Co do nieużywania QStringListModel to lepiej byłoby napisać swoją klasę dziedziczącą po QAbstractListModel, ale wygląda na to, że na razie za wysokie progi dla ciebie.

1

całe qt jest oparte na sygnale np. klikasz cos na widget to sie sygnał który przejmujesz do jakiegos towjego slotu i tam obsługujesz. Przyjrzyj się temu
https://doc.qt.io/qt-5/qlistview.html#indexesMoved

edit:
https://doc.qt.io/qt-5/qabstractitemview.html#clicked

0

Użytkownik oprogramowania nie ma lekko, nie ma myszki ani ekranu dotykowego , tylko klawiatura membranowa :(
Jeszcze całe szczęście że jest to zwykłą klawiatura (z punktu widzenia OS i aplikacji , kawałek elektroniki wpięty w szynę I2C) a nie porty IO gdzieś na procesorze

Dlatego taki przykład z keyPressEvent

szukałem https://doc.qt.io/qt-5/qmodelindex.html#row
i byłem na tej stronie ale szukałem uzywajac słow jak w Delphi , wiec i nie znalazłem ;)

1

czytamy dokumentacje do końca
[signal]
void QAbstractItemView::activated(const QModelIndex &index)
This signal is emitted when the item specified by index is activated by the user. How to activate items depends on the platform; e.g., by single- or double-clicking the item, or by pressing the Return or Enter key when the item is current.

0

Wszyscy mają rację !

keyPressEvent działa póki jest jeden komponent , jak dodam drugą listę albo widok tabeli to już nie wiem na jakim komponencie naciśnięto ENTER

QAbstractItemView::activated rzeczywiście działa na ENTER,

Ewentualnie w przyszłości może być problem jak będę chciał używać myszki i klawiatury jednocześnie
Bo w QAbstractItemView::activated mam zamkniecie okna , jak jest tylko klawiatura to jest OK
jednak klikniecie myszka w element listy zamyka moje okno dialogowe

void Widget::Execute()
{
  Widget * dlg = new Widget(nullptr);
  dlg->show();
}

void Widget::onActivated(const QModelIndex &index)
{

    qDebug() << "onActivated  index.row()=" << index.row();
    
    close(); // zamykam okno !!!
}

pomyśle o tym trochę potem

1

przyznam że nie rozumiem pomysłu w którym kliknięcie na listę zamyka oko. Chyba że wybranie z listy ma zamknąć okno listy i otworzyć jakieś drugie. Chciałbym zwrócić też uwagę iż w qt mamy budowę rodzic-dziecko więc ostrożnie z tym nullptr w konstruktorach jako parent. Może inaczej co chesz zrobić?

0

do sterowania mam 6 przycisków: Left, Right , Up, Down oraz ESC i ENTER
Wyświetlam dla użytkownika okno dialogowe z lista elementów i ma wybrać (1 z n)
koledzy w wątku napisali aby użyć [signal] -> void QAbstractItemView::activated zamiast keyPressEvent
bo tylko ten sygnał reaguje na ENTER
I to wszystko jest OK póki nie ma myszki, ja nie zalecam podłączania myszek do moich urządzeń , ale tez nie blokuje tego :)
Aby mieć ideał trzeba by zrobić klasę która dziedziczy po QListView i zaimplementować keyPressEvent na poziomie kontrolki

Jak masz chwilę to możesz zerknąć na git-a (link na początku wątku )

Pojawił sie nowy problem !

Zaznaczam na liście Item10
zamykam listę (naciskam ENTER) zapisuje do zmiennej idx_wybrany wybraną pozycję
Uruchamiam ponownie okno dialogowe z zaznaczonym elementem Item10
Naciskam strzełkę do dołu aby zaznaczyć element "Item11" a zaznacza sie Item2

Wygląda to tak jakby zaznaczenie i fokus to nie było to samo , i to jest OK, tylko nie wiem jak ustawić jedno i drugie ?

    // select item on list
    QItemSelectionModel::SelectionFlags flag = QItemSelectionModel::Select;
    ui->listView->selectionModel()->select(model->index(idx_wybrany), flag); //

OK! poprawna wersja:

ui->listView->setCurrentIndex(model->index(idx_wybrany));

ui->listView->selectionModel()->select ... to tylko zaznacza
ui->listView->setCurrentIndex( w Delphi to by sie nazywalo ItemIndex ;) )

0

Trochę mnie dziwi twój problem bo dokumentacja mówi:
e.g., by single- or double-clicking the item, or by pressing the Return or Enter key when the item is current.
Czyli klikanie też powinno hulać. Ale ok to może być platform specific.
ale przemyślenia na szybko

  1. Nie widzę problemu w jendoczesnej obsłudze sygnałów activeted i clicked.
  2. Istnieje też coś takiego dla qt jak eventfilters. Tworzysz osobną klasę filtrującą eventy po czym instalujesz ją w docelowym obiekcie. Nie koniecznie musisz używać dziedziczenia. Ale filtrów używałem dawno temu i sygnalizuję tylko że jest też inna opcja. https://doc.qt.io/qt-5/eventsandfilters.html

1 użytkowników online, w tym zalogowanych: 0, gości: 1