Adressbuch
Das Adressbuch-Beispiel zeigt, wie man Proxy-Modelle verwendet, um verschiedene Ansichten auf Daten aus einem einzigen Modell darzustellen.

Dieses Beispiel stellt ein Adressbuch bereit, in dem Kontakte alphabetisch in 9 Gruppen unterteilt werden können: ABC, DEF, GHI, …, VW, …, XYZ. Dies wird durch die Verwendung mehrerer Ansichten desselben Modells erreicht, von denen jede mithilfe einer Instanz der Klasse „ QSortFilterProxyModel “ gefiltert wird.
Übersicht
Das Adressbuch enthält vier Klassen: ` MainWindow`, ` AddressWidget`, ` NewAddressTab ` und ` AddDialog`. Die Klasse ` MainWindow ` verwendet ` AddressWidget ` als zentrales Widget und stellt die Menüs „ File “ und „ Tools “ bereit.

Die Klasse „ AddressWidget “ ist eine Unterklasse von „ QTabWidget “, die zur Bearbeitung der im Beispiel angezeigten 10 Registerkarten dient: die 9 Registerkarten für die Buchstabengruppen sowie eine Instanz von „ NewAddressTab “. Die Klasse „ NewAddressTab “ ist eine Unterklasse von „ QWidget “, die nur verwendet wird, wenn das Adressbuch leer ist, und den Benutzer dazu auffordert, Kontakte hinzuzufügen. „ AddressWidget “ interagiert zudem mit einer Instanz von „ TableModel “, um Einträge im Adressbuch hinzuzufügen, zu bearbeiten und zu entfernen.
struct Contact speichert einen Kontakt und ermöglicht den Vergleich sowie die Serialisierung über „ QDataStream “:
struct Contact
{
private:
Q_GADGET
Q_PROPERTY(QString name MEMBER name)
Q_PROPERTY(QString address MEMBER address)
public:
QString name;
QString address;
friend bool comparesEqual(const Contact &lhs, const Contact &rhs) noexcept
{
return lhs.name == rhs.name && lhs.address == rhs.address;
}
friend Qt::strong_ordering compareThreeWay(const Contact &lhs, const Contact &rhs) noexcept
{
int cmp = lhs.name.compare(rhs.name);
if (cmp == 0)
cmp = lhs.address.compare(rhs.address);
return Qt::compareThreeWay(cmp, 0);
}
Q_DECLARE_STRONGLY_ORDERED(Contact)
};
inline QDataStream &operator<<(QDataStream &stream, const Contact &contact)
{
return stream << contact.name << contact.address;
}
inline QDataStream &operator>>(QDataStream &stream, Contact &contact)
{
return stream >> contact.name >> contact.address;
}TableModel ist eine Unterklasse von „ QAbstractTableModel “, die die Standard-Model/View-API für den Zugriff auf Daten bereitstellt. Sie enthält eine Liste der hinzugefügten Kontakte. Diese Daten sind jedoch nicht alle auf einer einzigen Registerkarte sichtbar. Stattdessen wird „ QTableView “ verwendet, um 9 verschiedene Ansichten derselben Daten entsprechend den alphabetischen Gruppen bereitzustellen.
QSortFilterProxyModel ist die Klasse, die für die Filterung der Kontakte für jede Kontaktgruppe zuständig ist. Jedes Proxy-Modell verwendet ein ` QRegularExpression `, um Kontakte herauszufiltern, die nicht zur entsprechenden alphabetischen Gruppe gehören. Die Klasse ` AddDialog ` wird verwendet, um Informationen vom Benutzer für das Adressbuch abzurufen. Diese Unterklasse von ` QDialog ` wird von ` NewAddressTab ` instanziiert, um Kontakte hinzuzufügen, und von ` AddressWidget `, um Kontakte hinzuzufügen und zu bearbeiten.
Definition der Klasse „AddressWidget“
Die Klasse „ AddressWidget “ ist technisch gesehen die Hauptklasse in diesem Beispiel, da sie Funktionen zum Hinzufügen, Bearbeiten und Löschen von Kontakten sowie zum Speichern der Kontakte in einer Datei und zum Laden aus einer Datei bereitstellt.
class AddressWidget : public QTabWidget
{
Q_OBJECT
public:
explicit AddressWidget(QWidget *parent = nullptr);
bool readFromFile();
bool writeToFile();
static QString fileName();
public slots:
void showAddEntryDialog();
void addEntry(const Contact &contact);
void editEntry();
void removeEntry();
signals:
void selectionChanged (const QItemSelection &selected);
private:
void setupTabs();
NewAddressTab *newAddressTab;
QList<Contact> contacts;
using Adapter = decltype(QRangeModelAdapter(std::ref(contacts)));
Adapter adapter;
};AddressWidget erweitert „ QTabWidget “, um 10 Registerkarten (NewAddressTab sowie die 9 Registerkarten für die alphabetischen Gruppen) zu verwalten, und arbeitet zudem mit „ table “, dem „ TableModel “-Objekt, „ proxyModel “, dem „ QSortFilterProxyModel “-Objekt, das wir zum Filtern der Einträge verwenden, sowie „ tableView “, dem „ QTableView “-Objekt.
Es speichert die Kontakte in einem „ QList “ und verwendet ein „ QRangeModelAdapter “, um darauf zuzugreifen.
Wir stellen die Werte der Zeilenüberschriften für „ struct Contact “ über eine Spezialisierung von „ QRangeModel::RowOptions “ bereit:
template <>
struct QRangeModel::RowOptions<Contact>
{
inline static QVariant headerData(int section, int role);
};
QVariant QRangeModel::RowOptions<Contact>::headerData(int section, int role)
{
if (role == Qt::DisplayRole) {
switch (section) {
case 0:
return AddressWidget::tr("Name");
case 1:
return AddressWidget::tr("Address");
default:
break;
}
}
return {};
}Implementierung der Klasse „AddressWidget“
Der Konstruktor von „ AddressWidget “ akzeptiert ein übergeordnetes Widget und instanziiert „ NewAddressTab “, „ TableModel “ und „ QSortFilterProxyModel “. Das „ NewAddressTab “-Objekt, das angibt, dass das Adressbuch leer ist, wird hinzugefügt, und die übrigen 9 Registerkarten werden mit „ setupTabs() “ eingerichtet.
AddressWidget::AddressWidget(QWidget *parent)
: QTabWidget(parent),
newAddressTab(new NewAddressTab(this)),
adapter(std::ref(contacts))
{
connect(newAddressTab, &NewAddressTab::triggered, this, &AddressWidget::showAddEntryDialog);
addTab(newAddressTab, tr("Address Book"));
setupTabs();
}Die Funktion ` setupTabs() ` wird verwendet, um die neun Registerkarten für die alphabetischen Gruppen, die Tabellenansichten und die Proxy-Modelle in ` AddressWidget` einzurichten. Jedes Proxy-Modell wird wiederum so konfiguriert, dass es Kontaktnamen anhand der jeweiligen alphabetischen Gruppe unter Verwendung eines Objekts ` QRegularExpression ` filtert, bei dem die Groß-/Kleinschreibung nicht berücksichtigt wird. Die Tabellenansichten werden zudem mithilfe der Funktion ` sort()` des entsprechenden Proxy-Modells in aufsteigender Reihenfolge sortiert.
Die Eigenschaft „ selectionMode “ jeder Tabellenansicht ist auf „ QAbstractItemView::SingleSelection “ gesetzt und „ selectionBehavior “ auf „ QAbstractItemView::SelectRows “, sodass der Benutzer alle Elemente einer Zeile gleichzeitig auswählen kann. Jedem „ QTableView “-Objekt wird automatisch ein „ QItemSelectionModel “ zugewiesen, das die ausgewählten Indizes verfolgt.
void AddressWidget::setupTabs()
{
const auto groups = { "ABC"_L1, "DEF"_L1, "GHI"_L1, "JKL"_L1, "MNO"_L1, "PQR"_L1,
"STU"_L1, "VW"_L1, "XYZ"_L1 };
for (QLatin1StringView str : groups) {
const auto regExp = QRegularExpression(QLatin1StringView("^[%1].*").arg(str),
QRegularExpression::CaseInsensitiveOption);
auto *proxyModel = new QSortFilterProxyModel(this);
proxyModel->setSourceModel(adapter.model());
proxyModel->setFilterRegularExpression(regExp);
proxyModel->setFilterKeyColumn(0);
auto *tableView = new QTableView;
tableView->setModel(proxyModel);
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
tableView->horizontalHeader()->setStretchLastSection(true);
tableView->verticalHeader()->hide();
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
tableView->setSortingEnabled(true);
connect(tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &AddressWidget::selectionChanged);
connect(this, &QTabWidget::currentChanged, this, [this, tableView](int tabIndex) {
if (widget(tabIndex) == tableView)
emit selectionChanged(tableView->selectionModel()->selection());
});
addTab(tableView, str);
}
}Die Klasse „ QItemSelectionModel “ stellt das Signal „ selectionChanged “ bereit, das mit dem Signal „ selectionChanged() “ von „ AddressWidget “ verbunden ist. Außerdem verbinden wir das Signal „ QTabWidget::currentChanged()“ mit dem Lambda-Ausdruck, der ebenfalls das Signal „ selectionChanged() “ von „ AddressWidget “ ausgibt. Diese Verbindungen sind erforderlich, um die Aktionen „ Edit Entry... “ und „ Remove Entry “ im Menü „Tools“ von „ MainWindow “ zu aktivieren. Dies wird in der Implementierung von „ MainWindow “ näher erläutert.
Jede Tabellenansicht im Adressbuch wird als Registerkarte zur Seite „ QTabWidget “ hinzugefügt, wobei die entsprechende Bezeichnung aus dem Feld „ QStringList “ der Gruppen übernommen wird.

Wir stellen zwei Funktionen von „ addEntry() “ bereit: eine, die zur Annahme von Benutzereingaben gedacht ist, und eine andere, die die eigentliche Aufgabe des Hinzufügens neuer Einträge zum Adressbuch übernimmt. Wir teilen die Verantwortung für das Hinzufügen von Einträgen in zwei Teile auf, damit „ newAddressTab “ Daten einfügen kann, ohne einen Dialog anzeigen zu müssen.
Die erste „ addEntry() “-Funktion ist ein Slot, der mit der Aktion „ Add Entry... “ des „ MainWindow “ verbunden ist. Diese Funktion erstellt ein „ AddDialog “-Objekt und ruft anschließend die zweite „ addEntry() “-Funktion auf, um den Kontakt tatsächlich zu „ table “ hinzuzufügen.
void AddressWidget::showAddEntryDialog()
{
AddDialog aDialog(this);
if (aDialog.exec() == QDialog::Accepted)
addEntry(aDialog.contact());
}Eine grundlegende Validierung erfolgt in der zweiten Funktion „ addEntry() “, um doppelte Einträge im Adressbuch zu verhindern. Wie bereits bei „ TableModel “ erwähnt, ist dies einer der Gründe, warum wir die Getter-Methode „ getContacts() “ benötigen.
void AddressWidget::addEntry(const Contact &contact)
{
if (contacts.contains(contact)) {
QMessageBox::information(this, tr("Duplicate Name"),
tr("The name \"%1\" already exists.").arg(contact.name));
return;
}
adapter.insertRow(adapter.rowCount(), contact);
removeTab(indexOf(newAddressTab));
const QChar firstChar = contact.name.at(0).toUpper();
for (int t = 0, tabCount = count(); t < tabCount; ++t) {
if (tabText(t).contains(firstChar)) {
setCurrentIndex(t);
break;
}
}
}Wenn das Modell noch keinen Eintrag mit demselben Namen enthält, rufen wir ` setData() ` auf, um den Namen und die Adresse in die erste bzw. zweite Spalte einzufügen. Andernfalls zeigen wir eine ` QMessageBox ` an, um den Benutzer darüber zu informieren.
Hinweis: Die Meldung „ newAddressTab “ wird entfernt, sobald ein Kontakt hinzugefügt wurde, da das Adressbuch dann nicht mehr leer ist.
Das Bearbeiten eines Eintrags dient ausschließlich der Aktualisierung der Adresse des Kontakts, da das Beispiel es dem Benutzer nicht erlaubt, den Namen eines bestehenden Kontakts zu ändern.
Zunächst rufen wir das ` QTableView `-Objekt der aktiven Registerkarte mithilfe von ` QTabWidget::currentWidget()` ab. Anschließend extrahieren wir die ` selectionModel ` aus dem ` tableView `, um die ausgewählten Indizes zu erhalten.
void AddressWidget::editEntry()
{
auto *tableView = static_cast<QTableView *>(currentWidget());
auto *proxy = static_cast<QSortFilterProxyModel *>(tableView->model());
QItemSelectionModel *selectionModel = tableView->selectionModel();
const QModelIndexList indexes = selectionModel->selectedRows();
if (indexes.isEmpty())
return;
const int row = proxy->mapToSource(indexes.constFirst()).row();
const Contact contact = contacts.at(row);Anschließend extrahieren wir Daten aus der Zeile, die der Benutzer bearbeiten möchte. Diese Daten werden in einer Instanz von „ AddDialog “ mit einem anderen Fenstertitel angezeigt. Die „ table “ wird nur aktualisiert, wenn Änderungen an den Daten in „ aDialog “ vorgenommen wurden.
AddDialog aDialog(this);
aDialog.setWindowTitle(tr("Edit a Contact"));
aDialog.editAddress(contact);
if (aDialog.exec() == QDialog::Accepted) {
const Contact newContact = aDialog.contact();
if (newContact != contact)
adapter[row] = newContact;
}
}
Einträge werden mithilfe der Funktion „ removeEntry() “ entfernt. Die ausgewählte Zeile wird entfernt, indem über das „ QItemSelectionModel “-Objekt auf sie zugegriffen wird: „ selectionModel “. Die „ newAddressTab “ wird erst dann wieder zur „ AddressWidget “ hinzugefügt, wenn der Benutzer alle Kontakte aus dem Adressbuch entfernt hat.
void AddressWidget::removeEntry()
{
auto *tableView = static_cast<QTableView *>(currentWidget());
auto *proxy = static_cast<QSortFilterProxyModel *>(tableView->model());
QItemSelectionModel *selectionModel = tableView->selectionModel();
const QModelIndexList indexes = selectionModel->selectedRows();
if (indexes.isEmpty())
return;
const int row = proxy->mapToSource(indexes.constFirst()).row();
adapter.removeRow(row);
if (adapter.rowCount() == 0)
insertTab(0, newAddressTab, tr("Address Book"));
}Die Funktion „ writeToFile() “ dient zum Speichern einer Datei, die alle Kontakte im Adressbuch enthält. Die Datei wird in einem benutzerdefinierten Format „ .dat “ gespeichert. Der Inhalt der Kontaktliste wird mithilfe von „ QDataStream “ in die Datei „ file “ geschrieben. Wenn die Datei nicht geöffnet werden kann, wird ein „ QMessageBox “ mit der entsprechenden Fehlermeldung angezeigt.
bool AddressWidget::writeToFile()
{
QFile file(fileName());
if (!file.open(QIODevice::WriteOnly)) {
QMessageBox::information(this, tr("Unable to open file"),
tr("Cannot write to %1: %2").arg(QDir::toNativeSeparators(fileName()),
file.errorString()));
return false;
}
auto sortedContacts = contacts;
std::sort(sortedContacts.begin(), sortedContacts.end());
QDataStream out(&file);
out << sortedContacts;
return true;
}Die Funktion „ readFromFile() “ lädt eine Datei, die alle Kontakte des Adressbuchs enthält und zuvor mit „ writeToFile() “ gespeichert wurde. Mit „ QDataStream “ wird der Inhalt einer „ .dat “-Datei in eine Kontaktliste eingelesen, und jeder dieser Kontakte wird mit „ addEntry() “ hinzugefügt.
bool AddressWidget::readFromFile()
{
QFile file(fileName());
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::information(this, tr("Unable to open file"),
tr("Cannot open %1: %2").arg(QDir::toNativeSeparators(fileName()),
file.errorString()));
return false;
}
QList<Contact> contactsIn;
QDataStream in(&file);
in >> contactsIn;
if (contactsIn.isEmpty()) {
QMessageBox::information(this, tr("No contacts in file"),
tr("The file you are attempting to open contains no contacts."));
}
for (const auto &contact : std::as_const(contactsIn))
addEntry(contact);
return true;
}Klassendefinition von „NewAddressTab“
Die Klasse „ NewAddressTab “ stellt eine informative Registerkarte bereit, die den Benutzer darüber informiert, dass das Adressbuch leer ist. Sie wird je nach Inhalt des Adressbuchs ein- und ausgeblendet, wie in der Implementierung von „ AddressWidget “ beschrieben.

Die Klasse „ NewAddressTab “ erweitert „ QWidget “ und enthält die Methoden „ QLabel “ und „ QPushButton “.
class NewAddressTab : public QWidget
{
Q_OBJECT
public:
explicit NewAddressTab(QWidget *parent = nullptr);
signals:
void triggered();
};Implementierung der Klasse „NewAddressTab“
Der Konstruktor instanziiert die Klassen „ addButton “ und „ descriptionLabel “ und verbindet das Signal von „ addButton “ mit dem Signal „ triggered() “.
NewAddressTab::NewAddressTab(QWidget *parent)
: QWidget(parent)
{
auto *descriptionLabel = new QLabel(tr("There are currently no contacts in your address book. "
"\nClick Add to add new contacts."));
auto *addButton = new QPushButton(tr("Add"));
connect(addButton, &QAbstractButton::clicked, this, &NewAddressTab::triggered);
auto *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(descriptionLabel, 0, Qt::AlignCenter);
mainLayout->addWidget(addButton, 0, Qt::AlignCenter);
}
Definition der Klasse „AddDialog“
Die Klasse „ AddDialog “ erweitet die Klasse „ QDialog “ und stellt dem Benutzer ein „ QLineEdit “ sowie ein „ QTextEdit “ zur Eingabe von Daten in das Adressbuch bereit.
class AddDialog : public QDialog
{
Q_OBJECT
public:
explicit AddDialog(QWidget *parent = nullptr);
Contact contact() const;
void setContact(const Contact &c);
void editAddress(const Contact &c);
private slots:
void updateEnabled();
private:
QDialogButtonBox *buttonBox;
QLineEdit *nameText;
QPlainTextEdit *addressText;
};
Implementierung der Klasse „AddDialog“
Der Konstruktor von „ AddDialog “ richtet die Benutzeroberfläche ein, indem er die erforderlichen Widgets erstellt und diese in Layouts platziert.
AddDialog::AddDialog(QWidget *parent)
: QDialog(parent),
buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this)),
nameText(new QLineEdit),
addressText(new QPlainTextEdit)
{
auto *formLayout = new QFormLayout;
formLayout->addRow(tr("Name"), nameText);
formLayout->addRow(tr("Address"), addressText);
auto *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(formLayout);
mainLayout->addWidget(buttonBox);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(nameText, &QLineEdit::textChanged, this, &AddDialog::updateEnabled);
connect(addressText, &QPlainTextEdit::textChanged, this, &AddDialog::updateEnabled);
setWindowTitle(tr("Add a Contact"));
updateEnabled();
}
void AddDialog::updateEnabled()
{
Contact c = contact();
const bool valid = !c.name.isEmpty() && c.name.front().isLetter() && !c.address.isEmpty();
buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid);
}
Contact AddDialog::contact() const
{
return { nameText->text().trimmed(), addressText->toPlainText().trimmed() };
}
void AddDialog::setContact(const Contact &c)
{
nameText->setText(c.name);
addressText->setPlainText(c.address);
updateEnabled();
}
void AddDialog::editAddress(const Contact &c)
{
nameText->setReadOnly(true);
setContact(c);
}Um dem Dialog das gewünschte Verhalten zu verleihen, verbinden wir die Schaltflächen „ OK “ und „ Cancel “ mit den Slots „ accept()“ und „ reject()“ des Dialogs. Da der Dialog lediglich als Container für Namens- und Adressinformationen dient, müssen wir keine weiteren Funktionen dafür implementieren.
Definition der Klasse „MainWindow“
Die Klasse „ MainWindow “ erbt von „ QMainWindow “ und implementiert die Menüs und Aktionen, die zur Bearbeitung des Adressbuchs erforderlich sind.
![]() | ![]() |
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
private slots:
void updateActions(const QItemSelection &selection);
void openFile();
void saveFile();
private:
void createMenus();
AddressWidget *addressWidget;
QAction *editAct;
QAction *removeAct;
};Die Klasse „ MainWindow “ verwendet ein „ AddressWidget “ als zentrales Widget und stellt im Menü „Datei“ die Aktionen „ Open “, „ Close “ und „ Exit “ sowie im Menü „ Tools “ die Aktionen „ Add Entry... “, „ Edit Entry... “ und „ Remove Entry “ bereit.
Implementierung der Klasse „MainWindow“
Der Konstruktor von ` MainWindow ` instanziiert `AddressWidget`, legt es als zentrales Widget fest und ruft die Funktion ` createMenus() ` auf.
MainWindow::MainWindow()
: QMainWindow(),
addressWidget(new AddressWidget)
{
setCentralWidget(addressWidget);
createMenus();
setWindowTitle(tr("Address Book"));
}Die Funktion „ createMenus() “ richtet die Menüs „ File “ und „ Tools “ ein und verknüpft die Aktionen mit den entsprechenden Slots. Sowohl die Aktion „ Edit Entry... “ als auch die Aktion „ Remove Entry “ sind standardmäßig deaktiviert, da solche Aktionen bei einem leeren Adressbuch nicht ausgeführt werden können. Sie werden erst aktiviert, wenn ein oder mehrere Kontakte hinzugefügt wurden.
void MainWindow::createMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
auto *openAct = new QAction(QIcon::fromTheme(QIcon::ThemeIcon::DocumentOpen),
tr("&Open..."), this);
openAct->setShortcut(QKeySequence(QKeySequence::Open));
fileMenu->addAction(openAct);
connect(openAct, &QAction::triggered, this, &MainWindow::openFile);
...
editAct = new QAction(tr("&Edit Entry..."), this);
editAct->setEnabled(false);
toolMenu->addAction(editAct);
connect(editAct, &QAction::triggered, addressWidget, &AddressWidget::editEntry);
toolMenu->addSeparator();
removeAct = new QAction(tr("&Remove Entry"), this);
removeAct->setEnabled(false);
toolMenu->addAction(removeAct);
connect(removeAct, &QAction::triggered, addressWidget, &AddressWidget::removeEntry);
connect(addressWidget, &AddressWidget::selectionChanged,
this, &MainWindow::updateActions);
}Neben der Verknüpfung aller Aktionssignale mit den entsprechenden Slots verknüpfen wir auch das Signal „ selectionChanged() “ von „ AddressWidget “ mit dessen Slot „ updateActions() “.
Die Funktion „ openFile() “ öffnet eine benutzerdefinierte „ addressbook.dat “-Datei, die die Kontakte des Adressbuchs enthält. Diese Funktion ist ein Slot, der im Menü „ File “ mit „ openAct “ verbunden ist.
void MainWindow::openFile()
{
if (addressWidget->readFromFile())
statusBar()->showMessage(tr("Read %1").arg(QDir::toNativeSeparators(AddressWidget::fileName())));
}Die Funktion „ saveFile() “ speichert eine benutzerdefinierte „ addressbook.dat “-Datei, die die Kontakte aus dem Adressbuch enthält. Diese Funktion ist ein Slot, der mit „ saveAct “ im Menü „ File “ verknüpft ist.
void MainWindow::saveFile()
{
if (addressWidget->writeToFile())
statusBar()->showMessage(tr("Wrote %1").arg(QDir::toNativeSeparators(AddressWidget::fileName())));
}Die Funktion „ updateActions() “ aktiviert und deaktiviert „ Edit Entry... “ und „ Remove Entry “ je nach Inhalt des Adressbuchs. Ist das Adressbuch leer, sind diese Aktionen deaktiviert; andernfalls sind sie aktiviert. Diese Funktion ist ein Slot, der mit dem Signal „ selectionChanged() “ des „ AddressWidget “ verbunden ist.
void MainWindow::updateActions(const QItemSelection &selection)
{
const QModelIndexList indexes = selection.indexes();
removeAct->setEnabled(!indexes.isEmpty());
editAct->setEnabled(!indexes.isEmpty());
}main()-Funktion
Die Hauptfunktion für das Adressbuch instanziiert „ QApplication “ und öffnet „ MainWindow “, bevor die Ereignisschleife ausgeführt wird.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mw;
const auto availableGeometry = mw.screen()->availableGeometry();
mw.resize(availableGeometry.width() / 3, availableGeometry.height() / 3);
mw.show();
return QApplication::exec();
}© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.

