Rozdział 10: Item view classes

Slides:



Advertisements
Podobne prezentacje
Java Data Objects.
Advertisements

Introduction to SystemC
Analiza wywołania i przebiegu przerwań w systemie Linux

Java Server Faces Tomasz Nowak.
Rozdział 5 Creating custom widgets Autor: Bartłomiej Suliga.
ALLEGRO PIERWSZA GRA: WYŚCIG
C++ w Objectivity Marcin Michalak s1744. Pomocne pakiety: Data Definition Language (DDL). Standard Template Library (STL). Active Schema.
Autor: Jarosław Hryciuk
Java vs C# Michał Prządka Tomasz Nowak
OOPC++ - operatory1 Operatory class complex { private: double re, im; public: complex (double r, double i = 0) { re = r; im = i; } friend complex operator+
GUI Struktury Spotkanie integracyjne Nazwa wydziału: EAIiE Nazwa katedry: Informatyka Miejsce i data prezentacji: Kraków,
Mirosław Ochodek Sponsorzy: JFace Jak jeszcze szybciej tworzyć interfejsy? ECESIS Eclipse Community Education Project An.
Testowanie oprogramowania metodą badania pokrycia kodu
Wstęp do Qt Qt to zestaw przenośnych bibliotek i narzędzi programistycznych dedykowanych dla języka C++ podstawowym składnikiem są klasy służące do budowy.
Seminarium Informatyka Prowadzący dr Grzegorz Wójcik
Łukasz Monkiewicz.
Współprogramy Plan: Motywacja Składnia Scenariusz obiektu współprogramu Przykłady Producent – konsument ( instrukcja attach ) Czytelnik -pisarze ( instukcja.
142 JAVA – sterowanie i wątki public class A20 extends javax.swing.JApplet implements ActionListener { private int licznik = 0; private JTextField t =
„Tworzenie aplikacji sieciowych w języku Java”
Język C# Copyright, 2004 © Adam Czajka.
Najpopularniejsze aplikacje ASP.NET i PHP.
REKURENCJA.
Porysujmy trochę czyli Łączenie SQLa, AutoCADa i Delphi
Dr inż. Piotr Czapiewski. Overloading Znaczenie inne niż w większości języków obiektowych Metoda dynamicznego tworzenia pól i metod Magiczne metody.
PRZELICZNIK DŁUGOŚCI w programie NetBeans IDE autorzy: Michał Mrozek i Marcin Mrugała 2012.
Krzysztof Manuszewski
db4o Kacper Skory Marcin Talarek
Australia.
Wyk. Michał Liszkowski kl. 6a Moje gimnazjum- KSO Edukator.
HISTORIA (cz.1) Po raz pierwszy kontynent Australii został odkryty przez Europejczyków w XVI wieku. Byli nimi Portugalczycy. Australia ich jednak nie.
portale społecznościowe
Nazywam się Kacper Składowski. Mam 19 lat. Chodzę do trzeciej klasy Technikum Elektronicznego w ZESPOLE PONDGIMNAZJALNYCH SZKÓŁ ZAWODOWYCH I OGÓLNOKSZTAŁCĄCYCH.
Irina Svichenyuk Valeria Poligova Skąd biorą się motywy dla podróży? Skąd biorą się motywy dla podróży? Każdy człowiek ma jakieś własne potrzeby. To.
Wycieczka w Pieniny Fotograficzna opowieść o tym, jak zespolone siły klas I a, II h, III a i III b zdobyły 9 VI 2006 r. Trzy Korony. Prezentację przygotowała.
PIO 2_2, Zofia Kruczkiewicz1 Wykład 2 – część druga Iteracyjno-rozwojowy cykl oprogramowania 2.
PIO. Autor -Zofia Kruczkiewicz1 Wykład 1-część druga Wstęp do inżynierii oprogramowania. Cykle rozwoju oprogramowania (część biznesowa aplikacji) iteracyjno-rozwojowy.
Propozycja siatki godzin Specjalność: Modelowanie i Programowanie Systemów Informatycznych.
AUTOR :WOJTEK NOWIK REPORTER : LUK SMIS PATRYK SORMAN PIOTREK COLO (KOLO)
Kolejna gra mająca na celu pokazanie świata kierowców ścigających się w nielegalnych ulicznych wyścigach podrasowanymi do granic możliwości samochodami.
Podstawy programowania
Mężczyzna, wiek 92 lata, drobny, o szlachetnym wyglądzie, dobrze ubrany i starannie ogolony, o porządnie uczesanych włosach, który się budzi każdego.
Przewodnik dla początkujących
Uwaga !!! Uczniowie SP 32 w Toruniu ! Zapraszamy was i Wasze rodziny do wzięcia udziału w Festynie Zdrowia, który odbędzie się 31 maja 2013 roku podczas.
Podstawy licencjonowania Exchange, SharePoint oraz Lync.
Adam Suwała DIY - DI.
Cz.8 Zdarzenia. Refleksja – przypomnienie Event Programowanie zdarzeniowe Do dzieła!
Antonie de Saint-Exupery
Myśli Ojca Świętego Jana Pawła II.
Prawo lokalne w Internecie Jakub Kasprzycki
Warsztaty C# Część 2 Grzegorz Piotrowski Grupa.NET PO
Warsztaty C# Część 3 Grzegorz Piotrowski Grupa.NET PO
TWORZENIE SPISU TREŚCI Opracowała: Iwona Kowalik.
Budowa programu #include /*instrukcje preprocesora */ #include int main(void) { /*podstawowa funkcja programu */ int a=1; /*deklaracja i inicjalizacja.
Są w życiu chwile, kiedy tak bardzo odczuwamy brak obecności innych,
Les meilleures photos de L'année 2005 D'après NBC Życie we dwójkę…pełne pieszczot Aby odkryć pełnię szczęścia, trzeba zbliżyć się do nieba…
Weronika Schneider. Na fotografiach widać obecne budynki Polpharmy.
Zmiany w Przepisach Gry w Piłkę Nożną od 1 września 2006r. Kolegium Sędziów Warmińsko-Mazurskiego Związku Piłki Nożnej.
Temat 6: Elementy podstawowe
WoF PLATFORMA KOMUNIKACJI. WoF jest platformą komunikacji systemem wspomagającym obieg informacji oraz zarządzanie w firmie Zapewnia elektroniczny obieg.
PRZYCHODZI BABA DO LEKARZA.
Warsztaty użytkowników programu PLANS – Karwia06 Język makropoleceń JMP programu PLANS Część I mgr inż. Tomasz Zdun.
Instrukcje sterujące: W instrukcjach sterujących podejmowane są decyzje o wykonaniu tych czy innych instrukcji programu. Decyzje te podejmowane są w zależności.
Magic Janusz ROŻEJ Komtech Sp. z o.o.
Pozyskiwanie partnerów. Model popytowego podejścia do tworzenia innowacji Definicja Dwa podejścia do UDI –Głos konsumenta –Przewodnictwo konsumenta Cechy.
TROCHĘ HISTORII Marek Zając PO CO UŻYWAĆ OPENCL? Marek Zając.
1.
Piotr Czapiewski Wydział Informatyki ZUT.  Extensible Markup Language  Język znaczników  Human-readable and machine-readable  Niezależny od platformy.
Wydział Elektroniki Kierunek: AiR Zaawansowane metody programowania Wykład 6.
Previously discusses: different kinds of variables
Zapis prezentacji:

Rozdział 10: Item view classes …czyli model-view-delegate …czyli model-view-controler wg Qt … czyli jak efektywnie przedstawiać dane w Qt

O co w tym chodzi? Chodzi o odseparowanie sposobu przedstawiania danych od struktury, która te dane przechowuje oraz od mechanizmu edycji i dodawania danych

Na schemacie wygląda to tak: Dane Model edycja delegat renderowanie Widok renderowanie

A po co? Duże zbiory danych Prezentacja tych samych danych na kilku widgetach (np. diagram + tabela danych) Zmiana struktury reprezentującej dane bez konieczności zmian w widokach – dostosowujemy tylko model Podmiana standardowego modelu danych na nowy, realizujący dodatkowe funkcje, na przykład sortowanie

„A ja tam nie chcę, mnie tam na cholerę…” dla wygody, w Qt 4 pozostają dostępne znane z Qt 3 widgety QListWidget, QTableWidget i QTreeWidget, które nie wymagają przejmowania się modelem danych – mają własny zintegrowany … i dlatego je dziś pominę

Modele w Qt

Bazowe klasy modelowe służą do tworzenia nowych modeli QAbstractListModel, QAbstractTableModel – wykorzystane w przykładach QAbstractItemModel – stworzona dla szerokiego zakresu modeli, umożliwia obsługę hierarchii element w modelu identyfikowany poprzez klasę QModelIndex, określającą dwie współrzędne: rząd (row) i kolumnę (column), a także opcjonalnie rodzica

Predefiniowane modele danych QStringListModel QStandardItemModel QDirModel QSqlQueryModel QSqlTableModel QSqlRelationalTableModel QSortFilterProxyModel

Team leaders

Team Leaders - konstruktor TeamLeadersDialog::TeamLeadersDialog (const QStringList &leaders,QWidget *parent):QDialog(parent) { model = new QStringListModel(this); model->setStringList(leaders); listView = new QListView; listView->setModel(model); listView->setEditTriggers(QAbstractItemView::AnyKeyPressed | QAbstractItemView::DoubleClicked); ... }

void TeamLeadersDialog::insert() { int row = listView->currentIndex().row(); model->insertRows(row, 1); QModelIndex index = model->index(row); listView->setCurrentIndex(index); listView->edit(index); } void TeamLeadersDialog::del() model->removeRows(listView->currentIndex().row(), 1); QStringList TeamLeadersDialog::leaders() const return model->stringList();

Directory viewer

Directory viewer - konstruktor DirectoryViewer::DirectoryViewer(QWidget *parent) : QDialog(parent) { model = new QDirModel; model->setReadOnly(false); model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name); treeView = new QTreeView; treeView->setModel(model); treeView->header()->setStretchLastSection(true); treeView->header()->setSortIndicator(0, Qt::AscendingOrder); treeView->header()->setSortIndicatorShown(true); treeView->header()->setClickable(true); QModelIndex index = model->index(QDir::currentPath()); treeView->expand(index); treeView->scrollTo(index); treeView->resizeColumnToContents(0); ... }

void DirectoryViewer::createDirectory() { QModelIndex index = treeView->currentIndex(); if (!index.isValid()) return; QString dirName = QInputDialog::getText(this, tr("Create Directory"), tr("Directory name")); if (!dirName.isEmpty()) { if (!model->mkdir(index, dirName).isValid()) QMessageBox::information(this, tr("Create Directory"), tr("Failed to create the directory")); }

void DirectoryViewer::remove() { QModelIndex index = treeView->currentIndex(); if (!index.isValid()) return; bool ok; if (model->fileInfo(index).isDir()) { ok = model->rmdir(index); } else { ok = model->remove(index); if (!ok) QMessageBox::information(this, tr("Remove"), tr("Failed to remove %1").arg(model->fileName(index)));

Color names dialog

Color names dialog - konstruktor ColorNamesDialog::ColorNamesDialog(QWidget *parent) : QDialog(parent) { sourceModel = new QStringListModel(this); sourceModel->setStringList(QColor::colorNames()); proxyModel = new QSortFilterProxyModel(this); proxyModel->setSourceModel(sourceModel); proxyModel->setFilterKeyColumn(0); listView = new QListView; listView->setModel(proxyModel); ... syntaxComboBox = new QComboBox; syntaxComboBox->addItem(tr("Regular expression"), QRegExp::RegExp); syntaxComboBox->addItem(tr("Wildcard"), QRegExp::Wildcard); syntaxComboBox->addItem(tr("Fixed string"), QRegExp::FixedString); }

void ColorNamesDialog::reapplyFilter() { QRegExp::PatternSyntax syntax = QRegExp::PatternSyntax(syntaxComboBox->itemData( syntaxComboBox->currentIndex()).toInt()); QRegExp regExp(filterLineEdit->text(), Qt::CaseInsensitive, syntax); proxyModel->setFilterRegExp(regExp); }

Tworzenie własnych modeli wykorzystujemy jedną z klas bazowych: QAbstractListModel QAbstractTableModel QAbstractItemModel w zależności od potrzeb implementujemy na nowo metody takie jak: row(), column(), rowCount(), columnCount(), data()…

Waluty

QMap<QString, double> currencyMap; currencyMap.insert("AUD", 1.3259); currencyMap.insert("CHF", 1.2970); ... currencyMap.insert("SGD", 1.6901); currencyMap.insert("USD", 1.0000); CurrencyModel currencyModel; currencyModel.setCurrencyMap(currencyMap); QTableView tableView; tableView.setModel(&currencyModel); tableView.setAlternatingRowColors(true);

Waluty - model class CurrencyModel : public QAbstractTableModel { }; CurrencyModel(QObject *parent = 0); void setCurrencyMap(const QMap<QString, double> &map); int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; private: QString currencyAt(int offset) const; QMap<QString, double> currencyMap; };

int CurrencyModel::rowCount(const QModelIndex & /* parent */) const { return currencyMap.count(); } int CurrencyModel::columnCount(const QModelIndex & /* parent */) const

QVariant CurrencyModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (role == Qt::TextAlignmentRole) { return int(Qt::AlignRight | Qt::AlignVCenter); } else if (role == Qt::DisplayRole) { QString rowCurrency = currencyAt(index.row()); QString columnCurrency = currencyAt(index.column()); if (currencyMap.value(rowCurrency) == 0.0) return "####"; double amount = currencyMap.value(columnCurrency) / currencyMap.value(rowCurrency); return QString("%1").arg(amount, 0, 'f', 4); returnQVariant();

QVariant CurrencyModel::headerData(int section,. Qt::Orientation / QVariant CurrencyModel::headerData(int section, Qt::Orientation /* orientation */, int role) const { if (role != Qt::DisplayRole) return QVariant(); return currencyAt(section); }

QString CurrencyModel::currencyAt(int offset) const void CurrencyModel::setCurrencyMap(const QMap<QString, double> &map) { currencyMap = map; reset(); } QString CurrencyModel::currencyAt(int offset) const return (currencyMap.begin() + offset).key();

Miasta

QStringList cities; cities << "Arvika" << "Boden" << "Eskilstuna" << "Falun" << "Filipstad" << "Halmstad" << "Helsingborg" << "Karlstad" << "Kiruna" << "Kramfors" << "Motala" << "Sandviken" << "Skara" << "Stockholm" << "Sundsvall" << "Trelleborg"; CityModel cityModel; cityModel.setCities(cities); QTableView tableView; tableView.setModel(&cityModel); tableView.setAlternatingRowColors(true);

class CityModel : public QAbstractTableModel { Q_OBJECT public: CityModel(QObject *parent = 0); void setCities(const QStringList &cityNames); int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; bool setData(const QModelIndex &index, const QVariant &value, int role); QVariant headerData(int section, Qt::Orientation orientation, int role) const; Qt::ItemFlags flags(const QModelIndex &index) const; private: int offsetOf(int row, int column) const; QStringList cities; QVector<int> distances; };

QVariant CityModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); if (role == Qt::TextAlignmentRole) { return int(Qt::AlignRight | Qt::AlignVCenter); } else if (role == Qt::DisplayRole) { if (index.row() == index.column()) return 0; int offset = offsetOf(index.row(), index.column()); return distances[offset];

bool CityModel::setData(const QModelIndex &index, { const QVariant &value, int role) { if (index.isValid() && index.row() != index.column() && role == Qt::EditRole) { int offset = offsetOf(index.row(), index.column()); distances[offset] = value.toInt(); QModelIndex transposedIndex = createIndex(index.column(), index.row()); emit dataChanged(index, index); emit dataChanged(transposedIndex, transposedIndex); return true; } return false;

Qt::ItemFlags CityModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); if (index.row() != index.column()) flags |= Qt::ItemIsEditable; return flags; }

void CityModel::setCities(const QStringList &cityNames) { cities = cityNames; distances.resize(cities.count() * (cities.count() - 1) / 2); distances.fill(0); reset(); }

int CityModel::offsetOf(int row, int column) const { if (row < column) qSwap(row, column); return (row * (row - 1) / 2) + column; }

Własne delegaty Delegaty to elementy odpowiedzialne za wyświetlanie i edycję elementów modelu Normalnie wystarczają domyślne delegaty dla danego widoku, ale dla uzyskania większej kontroli możemy stworzyć własne

Track editor

class Track { public: Track(const QString &title = "", int duration = 0); QString title; int duration; };

TrackEditor::TrackEditor(QList<Track> *tracks, QWidget *parent) : QDialog(parent) { this->tracks = tracks; tableWidget = new QTableWidget(tracks->count(), 2); tableWidget->setItemDelegate(new TrackDelegate(1)); tableWidget->setHorizontalHeaderLabels( QStringList() << tr("Track") << tr("Duration")); for (int row = 0; row < tracks->count(); ++row) { Track track = tracks->at(row); QTableWidgetItem *item0 = new QTableWidgetItem(track.title); tableWidget->setItem(row, 0, item0); QTableWidgetItem *item1 = new QTableWidgetItem(QString::number(track.duration)); item1->setTextAlignment(Qt::AlignRight); tableWidget->setItem(row, 1, item1); } ...

class TrackDelegate : public QItemDelegate { Q_OBJECT public: TrackDelegate(int durationColumn, QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, private slots: void commitAndCloseEditor(); private: int durationColumn; };

void TrackDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.column() == durationColumn) { int secs = index.model()->data(index, Qt::DisplayRole).toInt(); QString text = QString("%1:%2") .arg(secs / 60, 2, 10, QChar('0')) .arg(secs % 60, 2, 10, QChar('0')); QStyleOptionViewItem myOption = option; myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter; drawDisplay(painter, myOption, myOption.rect, text); drawFocus(painter, myOption, myOption.rect); } else{ QItemDelegate::paint(painter, option, index);

QWidget *TrackDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (index.column() == durationColumn) { QTimeEdit *timeEdit = new QTimeEdit(parent); timeEdit->setDisplayFormat("mm:ss"); connect(timeEdit, SIGNAL(editingFinished()), this, SLOT(commitAndCloseEditor())); return timeEdit; } else { return QItemDelegate::createEditor(parent, option, index);

void TrackDelegate::commitAndCloseEditor() { QTimeEdit *editor = qobject_cast<QTimeEdit*>(sender()); emit commitData(editor); emit closeEditor(editor); }

void TrackDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { if (index.column() == durationColumn) { int secs = index.model()->data(index, Qt::DisplayRole).toInt(); QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor); timeEdit->setTime(QTime(0, secs / 60, secs % 60)); } else { QItemDelegate::setEditorData(editor, index); }

void TrackDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { if (index.column() == durationColumn) { QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor); QTime time = timeEdit->time(); int secs = (time.minute() * 60) + time.second(); model->setData(index, secs); } else { QItemDelegate::setModelData(editor, model, index);

class TrackDelegate : public QItemDelegate { Q_OBJECT public: TrackDelegate(int durationColumn, QObject *parent = 0); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, private slots: void commitAndCloseEditor(); private: int durationColumn; };