Qt 学习(一) addressbook

Qt Demo: addressbook
(1)创建项目:选择不创建界面,即UI,此时会自动生成的文件如图所示:
在这里插入图片描述
QApplication:
MainWindow 继承自 QMainWindow,根据需要设计的界面样式。

(2)确定MainWindow 的成员变量
在这里插入图片描述
首先,从此张界面图推断出 MainWindow 的组成:

  1. 一个QTabWidget;
  2. 两个QMenu: Files Tools;点击之后弹出的选项为:QAction;QAction 绑定槽函数
    MainWindow 包含的成员对象:
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow();
private slots:
    void updateActions(const QItemSelection &selection);
    void openFile();
    void saveFile();
private:
    void createMenus();

    AddressWidget *addressWidget;
    QMenu *fileMenu;
    QMenu *toolMenu;
    QAction *openAct;
    QAction *saveAct;
    QAction *exitAct;
    QAction *addAct;
    QAction *editAct;
    QAction *removeAct;
};

(3)在MainWindow中设置 centralwidget 以及 title, 并添加menu 以及 action,再绑定槽函数

setCentralWidget
setWindowTitle
fileMenu = menuBar()->addMenu(tr("&File"));
openAct = new QAction(tr("&Open"),this);
fileMenu->addAction(openAct);
connect(openAct,&QAction::triggered,this,&MainWindow::open_file);

为两个menu 添加了三个可点击的控件,对应的槽函数需要根据代码架构来设计。

// Open file
QString file_name = QFileDialog().getOpenFileName(this);
// Save file
QString file_name = QFileDialog().getSaveFileName(this);

(4)QTabWidget
添加tab: QtableView、 QWidget

QTableView* tableview = new QtableView();
// QTableView 设置一系列属性
// int addTab(QWidget* widget, const QString&);
addTab(tableview, str); 

model-view
QAbstractListModel QAbstractTableModel
索引:QModelIndex
role: ItemDataRole
实现自己的model类:

class tableModel : public QAbstractTableModel
{
public:
    tableModel(QObject* parent = nullptr);

// virtual function
//  must override this 3 funciton when use QAbstractTableModel
    int rowCount(const QModelIndex &parent) const override;
    int columnCount(const QModelIndex &parent) const override;
    QVariant data(const QModelIndex &index, int role) const override;

//  must override this 2 funciton when edit data
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;

//  must override this 2 funciton when change rows
    bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
    bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;

//  must override this 1 funciton when use table header
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

    const QVector<Contact> &getContacts() const;

private:
    QVector<Contact> _contacts;
};

(5) 槽函数:添加,修改,删除
每一个{name, address} 都是通过一个 QDialog 添加;
此界面包含的控件:QLineEdit;QTextEdit;QLabel;QPushButton
layout:QGridLayout;QHBoxLayout;QVBoxLayout
在这里插入图片描述

addDialog::addDialog(QWidget* parent)
{
    _name = new QLineEdit();
    _address = new QTextEdit();
    auto nameLabel = new QLabel("Name");
    auto addressLabel = new QLabel("Address");

    auto layout = new QGridLayout();
    layout->setColumnStretch(1,2);

    layout->addWidget(nameLabel,0,0);
    layout->addWidget(_name,0,1);
    layout->addWidget(addressLabel,1,0,Qt::AlignLeft|Qt::AlignTop);
    layout->addWidget(_address,1,1,Qt::AlignLeft);

    auto okBtn = new QPushButton("OK");
    auto cancelBtn = new QPushButton("Cancel");

    auto btnLayout = new QHBoxLayout;
    btnLayout->addWidget(okBtn);
    btnLayout->addWidget(cancelBtn);
    layout->addLayout(btnLayout,2,1,Qt::AlignRight);

    auto mainLayout = new QVBoxLayout;
    mainLayout->addLayout(layout);
    setLayout(mainLayout);
    setWindowTitle("Add a Contact");

    connect(okBtn,&QAbstractButton::clicked,this,&QDialog::accept);
    connect(cancelBtn, &QAbstractButton::clicked, this, &QDialog::reject);
}

添加:

void addressWidget::show_add_entry_dialog()
{
    qDebug()<<"show_add_entry_dialog"<<endl;
    addDialog add_dialog;
    if(add_dialog.exec())
    {
        qDebug()<<"add_dialog.exec()"<<endl;
        add_entry(add_dialog.name(),add_dialog.address());
    }
}
void addressWidget::add_entry(const QString& name, const QString& address)
{
    qDebug()<<"add_entry"<<"name:"<<name<<"address:"<<address<<endl;
    if(!_table_model->getContacts().contains({name,address}))
    {
        _table_model->insertRows(0,1,QModelIndex());
        QModelIndex index = _table_model->index(0,0,QModelIndex());
        _table_model->setData(index,name,Qt::EditRole);

        index = _table_model->index(0,1,QModelIndex());
        _table_model->setData(index,address);
        removeTab(indexOf(_new_address_tab));
    }
    else
    {
        qDebug()<<"duplicate name"<<endl;
    }
}

修改

void AddressWidget::editEntry()
{
    QTableView *temp = static_cast<QTableView*>(currentWidget());
    QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
    QItemSelectionModel *selectionModel = temp->selectionModel();

    const QModelIndexList indexes = selectionModel->selectedRows();
    QString name;
    QString address;
    int row = -1;

    for (const QModelIndex &index : indexes) {
        row = proxy->mapToSource(index).row();
        QModelIndex nameIndex = table->index(row, 0, QModelIndex());
        QVariant varName = table->data(nameIndex, Qt::DisplayRole);
        name = varName.toString();

        QModelIndex addressIndex = table->index(row, 1, QModelIndex());
        QVariant varAddr = table->data(addressIndex, Qt::DisplayRole);
        address = varAddr.toString();
    }
    AddDialog aDialog;
    aDialog.setWindowTitle(tr("Edit a Contact"));
    aDialog.editAddress(name, address);

    if (aDialog.exec()) {
        const QString newAddress = aDialog.address();
        if (newAddress != address) {
            const QModelIndex index = table->index(row, 1, QModelIndex());
            table->setData(index, newAddress, Qt::EditRole);
        }
    }
}

删除

void AddressWidget::removeEntry()
{
    QTableView *temp = static_cast<QTableView*>(currentWidget());
    QSortFilterProxyModel *proxy = static_cast<QSortFilterProxyModel*>(temp->model());
    QItemSelectionModel *selectionModel = temp->selectionModel();

    const QModelIndexList indexes = selectionModel->selectedRows();

    for (QModelIndex index : indexes) {
        int row = proxy->mapToSource(index).row();
        table->removeRows(row, 1, QModelIndex());
    }

    if (table->rowCount(QModelIndex()) == 0)
        insertTab(0, newAddressTab, tr("Address Book"));
}

(6)存储数据

void AddressWidget::writeToFile(const QString &fileName)
{
    QFile file(fileName);

    if (!file.open(QIODevice::WriteOnly)) {
        QMessageBox::information(this, tr("Unable to open file"), file.errorString());
        return;
    }

    QDataStream out(&file);
    out << table->getContacts();
}

读取数据:

void AddressWidget::readFromFile(const QString &fileName)
{
    QFile file(fileName);

    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::information(this, tr("Unable to open file"),
            file.errorString());
        return;
    }

    QVector<Contact> contacts;
    QDataStream in(&file);
    in >> contacts;
    if (contacts.isEmpty()) {
        QMessageBox::information(this, tr("No contacts in file"),
                                 tr("The file you are attempting to open contains no contacts."));
    } else {
        for (const auto &contact: qAsConst(contacts))
            addEntry(contact.name, contact.address);
    }
}

Contacts 需要重载流运算符

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值