Qt - kontrolka QListView
Stronę tą wyświetlono już: 3279 razy
Kontrolka QListView wizualnie przypomina wcześniej omawianą kontrolkę QListWidget, jednakże funkcjonuje ona na nieco innej zasadzie i umożliwia znacznie większą elastyczność sterowania jej funkcjonalnością i wyglądem. Niestety jest to obarczone nieco bardziej złożonym procesem obsługi tej kontrolki. W przykładzie, który mam zamiar pokazać wyeliminowałem konieczność tworzenia dodatkowych kontrolek do wprowadzania danych przez użytkownika do mojej listy. W kontrolce QListView po odpowiednim ustawieniu jej właściwości metodą setEditTriggers i zaznaczeniu myszką jednej z dostępnych pozycji można zmienić jej zawartość wpisując po prostu tekst. Klawisz enter zatwierdza zmianę. To samo można zrobić klikając dwukrotnie na danym elemencie listy i edytując zawarty w nim tekst.
Zanim przejdę do kodu warto zerknąć łaskawym okiem na wygląd samego graficznego interfejsu użytkownika, na który składa się tylko jedna kontrolka QListView, która zastąpi wszystkie dodatkowe przyciski i kontrolkę QLineEdit z poprzedniej strony.

W kodzie obiekt klasy QListView nazwałem countriesList.
Kod programu w pliku mainwindow.h:
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- #include <QStringListModel>
- #include <QDebug>
- #include <QMessageBox>
- #include <QShortcut>
- namespace Ui {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- QStringListModel *countriesListModel; // model, który zostanie podpięty pod kontrolkę QListView
- QString country; // pomocnicza zmienna konieczna do przechowywania informacji o tekście zawartym w danym elemencie kontrolki przed jego modyfikacją
- QShortcut *shDelete; // skrót klawiaturowy do podpięcia slotu onDeleteItem
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private slots:
- // slot podpięty pod sygnał wysyłany, gdy tekst w elementach kontrolki został zmieniony
- void countryDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int> ());
- // slot podpięty pod sygnał wysyłany, gdy element w kontrolce został kliknięty dwa razy (co będzie oznaczało edycję tekstu kontrolki
- void on_countriesList_doubleClicked(const QModelIndex &index);
- // slot podpięty pod skrót klawiaturowy oznaczający usuwanie elementu zaznaczonego
- void onDeleteItem();
- // slot podpięty pod sygnał wysyłany, gdy wcześniej zaznaczony na liście element został nadpisany poprzez rozpoczęcie wpisywania tekstu
- void on_countriesList_pressed(const QModelIndex &index);
- private:
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
Kontrolka QListView do dodawania elementów listy wykorzystuje obiekt klasy QStringListModel, który po utworzeniu trzeba podpiąć pod obiekt klasy QListView wykorzystując jej metodę setModel. Wszystko to zostanie uczynione w konstruktorze klasy MainWindow w pliku mainwindow.cpp:
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- countriesListModel = new QStringListModel(this); // tworzenie nowego obiektu modelu
- countriesListModel->setStringList(
- {"Polska", "Czechy", "Słowacja"} // dodaję parę początkowych pozycji
- );
- ui->countriesList->setModel(countriesListModel); // podpinam model pod kontrolkę QListView
- ui->countriesList->setEditTriggers(
- QAbstractItemView::AnyKeyPressed | // edycja zaznaczonego elementu na dowolny znak tekstowy
- QAbstractItemView::DoubleClicked // edycja elementu po dwukrotnym kliknięciu lewym przyciskiem myszy
- );
- int row = countriesListModel->rowCount(); // pobieram liczbę wierszy
- countriesListModel->insertRow(row); // wstawiam dodatkowy wiersz na końcu
- QModelIndex index = countriesListModel->index(row, 0); // pobieram obiekt wstawionego indeksu
- countriesListModel->setData(index, QVariant("*")); // i ustawiam jego tekst
- // podpięcie sygnału dataChanged obiektu countriesListModel pod slot countryDataChanged okna głównego
- QObject::connect(countriesListModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(countryDataChanged(QModelIndex,QModelIndex,QVector<int>)));
- // tworzę skrót klawiaturowy podpięty pod kontrolkę QListView
- QShortcut* shDelete = new QShortcut(QKeySequence(Qt::Key_Delete), ui->countriesList);
- // podpinam sygnał obiektu shDelete pod slot onDeleteItem okna głównego
- connect(shDelete, SIGNAL(activated()), this, SLOT(onDeleteItem()));
- }
- MainWindow::~MainWindow()
- {
- delete ui;
- }
- void MainWindow::countryDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles){
- if(topLeft != bottomRight) // jak więcej niż dwa elementy są edytowane to nie wykonuj dalszych działań
- return;
- int rowCount = countriesListModel->rowCount(); // pobieram liczbę wierszy
- // jeżeli tekst jest pusty
- if(topLeft.data().toString() == ""){
- countriesListModel->setData(topLeft, country); // to przywracam pierwotne ustawienie
- return;
- }
- // wyszukuję elementy pasujące do wprowadzonego tekstu
- QModelIndexList finded = countriesListModel->match(countriesListModel->index(0, 0), Qt::DisplayRole, topLeft.data(), -1, Qt::MatchExactly);
- // jak znaleziono więcej niż jeden to znaczy, że taki element już istniał
- if(finded.size() > 1){
- QMessageBox::warning(this, "Uwaga!", "Kraj o nazwie: " + topLeft.data().toString() + " już jest na liście");
- countriesListModel->setData(topLeft, country);
- }else if(topLeft.row() == rowCount - 1){ // jeżeli edytowany był ostatni element
- if(topLeft.data().toString() != "*"){ // i tekst nie jest "*" to
- countriesListModel->insertRow(rowCount); // dodaję nową pozycję
- QModelIndex index = countriesListModel->index(rowCount, 0); // pobieram jej obiekt
- countriesListModel->setData(index, QVariant("*")); // i ustawiam tekst na "*"
- }
- }
- }
- void MainWindow::on_countriesList_doubleClicked(const QModelIndex &index)
- {
- country = index.data().toString(); // zapamiętywanie początkowej wartości edytowanego indeksu
- }
- void MainWindow::onDeleteItem(){
- int row = ui->countriesList->currentIndex().row(); // pobieram indeks
- if(row != countriesListModel->rowCount() - 1){ // jak nie jest równy ostatniemu elementowi to
- countriesListModel->removeRow(row); // usuwam wiersz
- }
- }
- void MainWindow::on_countriesList_pressed(const QModelIndex &index)
- {
- country = index.data().toString(); // zapamiętywanie początkowej wartości edytowanego indeksu
- }

Tytuł:
Architektura oprogramowania bez tajemnic. Wykorzystaj język C++ do tworzenia wydajnych aplikacji i systemów
Autor:
Adrian Ostrowski, Piotr Gaczkowski

Tytuł:
Opus magnum C++ 11. Programowanie w języku C++. Wydanie II poprawione (komplet)
Autor:
Jerzy Grębosz

Tytuł:
Programowanie wieloplatformowe z C++ i wxWidgets 3
Autor:
Bartosz W. Warzocha

Tytuł:
Język C++ i przetwarzanie współbieżne w akcji. Wydanie II
Autor:
Anthony Williams

Tytuł:
C++ dla bystrzaków. Wydanie VII
Autor:
Stephen R. Davis

Tytuł:
Tablice informatyczne. Podstawy C++
Autor:
Radosław Sokół

Tytuł:
Opus magnum C++11. Programowanie w języku C++ (komplet)
Autor:
Jerzy Grębosz

Tytuł:
OpenCV 3. Komputerowe rozpoznawanie obrazu w C++ przy użyciu biblioteki OpenCV
Autor:
Adrian Kaehler, Gary Bradski

Tytuł:
C++ w 24 godziny. Wydanie VI
Autor:
Rogers Cadenhead, Jesse Liberty

Tytuł:
C++ Optymalizacja kodu. Sprawdzone techniki zwiększania wydajności
Autor:
Guntheroth Kurt