Qt 学习(一) addressbook

news2024/11/20 16:33:09

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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1866819.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20240626(周三)AH股行情总结:沪指午后大反弹,港股震荡走高,AIGC、短剧概念走强,低价可转债触底反弹

内容提要 上证指数午后大反弹&#xff0c;创业板指涨近2%。港股震荡走高&#xff0c;恒生科技指数涨近1%。AIGC概念领涨&#xff0c;ST股、贵金属板块领跌。低价可转债集体大涨&#xff0c;广汇转债涨20%触发临停&#xff0c;广汇汽车今日上演地天板。 周三&#xff0c;A股午…

【BUG记录】条件查询没有查询结果 || MybatisPlus打印查询语句

结论 先说结论&#xff0c;查询没有结果&#xff0c;可能是数据库连接&#xff0c;数据问题之类&#xff0c;最有可能的根本原因是查询语句问题&#xff0c;需要想办法检查查询语句&#xff0c;使用mybatisPlus等自动生成查询语句的框架不能直接看语句&#xff0c;可以依靠日志…

Python期末模拟题库[python123题库]

期末模拟题库 一、单项选择题 1、下列关于Python语言的特点的说法中&#xff0c;错误的是()‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‪‬‪‬‪‬‪…

高效运维:标准化与智能化的运维流程管理实践

高效运维&#xff1a;标准化与智能化的运维流程管理实践 在信息化建设日益深化的今天&#xff0c;运维流程管理已成为企业确保其信息系统稳定、高效运行的关键手段。通过系统化、标准化的运维流程管理&#xff0c;企业能够有效预防系统故障&#xff0c;提升服务质量&#xff0…

数据结构 —— 二叉树

1.树的概念及结构 1.1树的概念 树是一种非线性的数据结构&#xff0c;它有着多分支&#xff0c;层次性的特点。 由于其形态类似于自然界中倒过来的数&#xff0c;所以我们将这种数据结构称为“树形结构” 注意&#xff1a; 树形结构中&#xff0c;子树之间不能有交集&#x…

一加全机型TWRP合集/橙狐recovery下载-20240603更新-支持一加12/Ace3V手机

TWRP是目前安卓平台的刷机神器&#xff0c;可快速刷写第三方ROM或官方系统&#xff0c;刷入TWRP之前需要解锁BL&#xff0c;目前已适配一加多个机型。ROM乐园小编20240603整理&#xff0c;涵盖一加1到一加Ace3V多机型专用TWRP文件&#xff0c;个人机型橙狐recovery适配相对完整…

MySQL 8 命令安装卸载教程

一、下载MySQL8 下载连接 MySQL :: Download MySQL Community Server 我下载的是当前最新版8.4 二、安装 1.解压 解压到需要安装的位置&#xff0c;例如我的位置&#xff1a; 2.创建配置文件 新建文本文档&#xff0c;复制下面配置文件&#xff08;注意修改路经&#xff09;…

DPDK使用make编译并运行示例程序

环境&#xff1a; VMware Workstation 16 Pro 16.2.4 虚拟机系统&#xff1a;Centos 8 DPDK版本&#xff1a;stable-20.11.10 下载源码后&#xff0c;使用meson和ninja编译完成、配置并挂载大页、内核和VFIO设置完成&#xff0c;在dpdk源码目录下的build/…

小程序 UI 风格,引人入胜

小程序 UI 风格&#xff0c;引人入胜

OceanBase 4.X-2F1A 仲裁高可用方案初探

作者&#xff1a;郑增权&#xff0c;爱可生 DBA 团队成员&#xff0c;OceanBase 和 MySQL 数据库技术爱好者。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 本文约 1500 字&#xff0c;预计阅读需要 5 分钟。 背景 对…

10个国内免费AI绘画网站汇总【2024最新】

迎战MidJourney和Stable Diffusion&#xff1a;10款国产AI绘画神器&#xff0c;让你轻松创作出超凡艺术品&#xff01;不论你是初学者还是资深艺术家&#xff0c;这些AI绘画平台都能帮你轻松入门。快来探索这些AI绘画网站&#xff0c;释放你的创意潜能&#xff01; 1、AI绘画创…

Linux系统之nice命令的基本使用

Linux系统之nice命令的基本使用 一、nice命令介绍1.1 nice命令简介1.2 进程优先级介绍 二、nice命令基本语法2.1 nice命令的help帮助信息2.2 nice命令选项解释 三、nice命令的基本使用3.1 查看进程优先级3.2 使用nice启动进程3.3 提高优先级 四、注意事项 一、nice命令介绍 1.…

YCSB基准测试

1、Redis: 下载成功后&#xff0c;加载数据&#xff0c;运行 启动redis: /usr/local/redis/bin/redis-server ./bin/ycsb load redis -P workloads/workloade -p redis.hostlocalhost -p redis.port6379 -p recordcount10000 -p operationcount10000 -threads 32 ./bin/y…

Vue3-尚硅谷笔记

1. Vue3简介 2020年9月18日&#xff0c;Vue.js发布版3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;n 经历了&#xff1a;4800次提交、40个RFC、600次PR、300贡献者 官方发版地址&#xff1a;Release v3.0.0 One Piece vuejs/core 截止2023年10月&#xff0c;最…

简述RocketMQ从了解到使用

概念篇 背景: 随着队列和虚拟主题使用的增加,ActiveMQ IO模块达到了一个瓶颈。我们尽力通过节流、断路器或降级来解决这个问题,但效果并不理想。于是我们尝试了流行的消息传递解决方案Kafka。不幸的是,Kafka不能满足我们的要求,其尤其表现在低延迟和高可靠性方面,详见下…

后端之路第三站(Mybatis)——入门配置

一、Mybatis是啥&#xff1f; 就是一个用java来操控数据库的框架语言 之前学的datagrip或者navicat这些软件里我们操作数据库&#xff0c;原理是我们编写完的操作语句发送到服务器传送到数据库系统&#xff0c;然后数据库执行完之后再发送给服务器返回给datagrip或者navicat显…

服务器数据恢复—用raid6阵列磁盘组建raid5阵列如何恢复原raid数据?

服务器存储数据恢复环境&#xff1a; 华为OceanStor 5800存储&#xff0c;该存储中有一组由10块硬盘组建的raid6磁盘阵列&#xff0c;供企业内部使用&#xff0c;服务器安装linux操作系统EXT3文件系统&#xff0c;划分2个lun。 服务器存储故障&#xff1a; 管理员发现存储中rai…

多家国产大模型提供OpenAI API服务替代方案,谷歌将推出明星网红AI聊天机器人

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 1、OpenAI终止对中国提供服务 6月25日凌晨&#xff0c;多个用户收到OpenAI的推送邮件&#xff0c;信中称&#xff0c;自今年7月9日起&#xff0c;将开始阻止来自非支持国家和地区的API&#xff08;应…

pythons工具——裁剪labelme的json不规则多边形标签保存成矩形图像

原图labelme标注 使用以下程序&#xff0c;裁剪labelme的json不规则多边形标签保存成矩形图像 import os import cv2 import math import json import numpy as np from PIL import Image, ImageDrawdef calculate_bounding_box(points):"""计算多边形的最小外…

高校心理咨询管理系统

摘 要 随着高校学生心理问题的增多&#xff0c;心理咨询服务在高校中的重要性日益凸显。然而&#xff0c;传统的心理咨询管理方式存在着诸多问题&#xff0c;如信息不透明、咨询师资源不足等。为了解决这些问题&#xff0c;本文设计并实现了一种基于Java Web的高校心理咨询管理…