【Qt】实验 多窗口 模态非模态 信号槽 对话框 文档菜单 鼠标操作 按键操作 绘图 定时器 各部件(pushbutton,LineEdit SpinBox,滑动条,CheckBox,ComBox)

文章目录

  • * Qt_LAB
    • Lab5
      • 1.窗口与子部件
      • 2.模态和非模态对话框
      • 3.Qt一般框架
      • 4.信号槽机制
      • 5.标准对话框
    • Lab6
      • 1.布局设计
      • 2.数据界面互动
      • 3.多窗口切换
    • Lab7
      • 1.PushButton按钮组件
      • 2.LineEdit单行输入组件
      • 3.简易登录界面
      • 4.SpinBox组件
      • 5.HorizontalSlider 滑块条组件
      • 6.数码表与LCD屏幕
      • 7.CheckBox 多选框
      • 8.ComBox 下拉框组件
      • 9.ProgressBar 进度条与定时器
      • 10.DateTime 日期与时间组件
      • 11.PlainTextEdit 多行文本框
      • 12.RadioButton 单选框分组
    • Lab8
      • 1.处理文档菜单
    • Lab9
      • 1.鼠标键盘事件练习
      • 2.定时器和随机数
    • Lab10
      • 1.鼠标绘图 按键缩放移动
      • 2.按键绘图 按键变色
    • Lab11
      • 1.布局设计
      • 2.菜单

* Qt_LAB

Lab5

1.窗口与子部件

  • 窗口:没有父部件。
  • 子部件:非窗口部件。
题目要求:窗口与子部件的区别
(1)新建一个空的Qt项目:Project_1;
(2)在main函数中新建三个部件:一个widget,两个label。其中,一个label为子部件,即它的父对象为那个widget。分别设置它们的标题及文本。
(3)显示窗口:widget以及那个非子部件的label
#include

int main(int argc, char *argv[])
{
    //应用程序类
    //处理应用程序初始化和结束,事件处理调度。
    QApplication a(argc, argv);

    //新建QWidget类对象,默认parent参数nullptr,所以它是个窗口
    QWidget*widget=new QWidget();

    //设置窗口标题
    widget->setWindowTitle(QObject::tr("我是widget"));

    //新建QLabel对象,默认parent参数是nullptr,所以它是个窗口
    QLabel *label=new QLabel();
    label->setWindowTitle(QObject::tr("我是label"));
    label->setText(QObject::tr("label:我是个窗口"));
    label->resize(180,20);

    //label2指定父窗口为widget,所以不是窗口
    QLabel * label2=new QLabel(widget);
    label2->setText(QObject::tr("label2:不是独立窗口,只是widget的子部件"));
    label2->resize(250,20);

    label->show();
    widget->show();
    int ret=a.exec();
    delete label;
    delete widget;

    return ret;
}

2.模态和非模态对话框

  • 模态:打开后不能与其他窗口交互。
  • 非模态:打开后还能与其他窗口交互。
题目要求:熟悉模态和非模态对话框
(1)新建一个Qt Widget Application项目:Project_2
(2)在主窗口类的构造函数中,设置主窗口的标题为:I’m the main window
(3)在主窗口类的构造函数中,定义一个基本对话框对象,设置其标题为:I’m a dialog
(4)在主窗口类的构造函数中,以模态形式显示(3)中定义的对话框
(5)撤消(4)操作,在主窗口类的构造函数中,以非模态形式显示(3)中定义的对话框
(6)分析比较模态和非模态对话框的行为
  • main.cpp

    #include "widget.h"
    
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        //主窗口
        Widget w;
        w.setWindowTitle("I'm the main Window");
        w.show();
        return a.exec();
    }
    
  • widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include "QDialog"
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        //非模态对话框
        QDialog dialog(this);
        dialog.setWindowTitle("I'm a dialog");
        dialog.resize(800,800);
        dialog.exec();
    
    //    //模式对话框
    //    QDialog *dialog=new QDialog(this);
    //    dialog->setModal(true);
    //    dialog->setWindowTitle("I'm a dialog");
    //    dialog->resize(900,900);
    //    dialog->show();
    
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    

3.Qt一般框架

题目要求:一个Qt界面程序的一般框架结构。通常,为程序的主窗口定义一个类,并在这个类中完成主窗口中的子部件的创建以及信号的处理。这样,程序的GUI部分全部放在主窗口中实现,便于管理和维护
(1)新建一个空的Qt项目:Project_3
(2)新建一个主窗口类,继承于Widget
(3)在main函数中定义一个主窗口实例,并显示。
(4)运行程序
(5)在主窗口中添加一个PushButton。注意:在主窗口类的构造函数中完成该操作,不要在main函数中。运行程序。
(6)通过Qt Designer在主窗口放置一个label标签,位置与(5)中的PushButton不要重叠,并设置其文本为:I’m a label。运行程序。
(7)尝试在主窗口类的构造函数中修改(6)中label的文本为:access from code。运行程序。
  • widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
    #include "QPushButton"
    #include "QLabel"
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        QPushButton * Button=new QPushButton(this);
    
        QLabel*label=new QLabel("I'm a label",this);
        label->move(50,50);
        label->setText("access from code");
    
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    

4.信号槽机制

  • 一般

    connect(button,&QPushButton::clicked,this,&Widget::changeLabelText);
    
  • 传参

    connect(button,&QPushButton::clicked,[=](){changeLabelText(label);});
    
    这句话是一个信号槽连接的语句,用于将一个按钮的点击事件(clicked)与一个槽函数(changeLabelText)连接起来,并在点击按钮时执行该槽函数。具体来说:
    
    1.button 是一个 QPushButton 类型的对象指针,表示一个按钮对象。
    2.&QPushButton::clicked 是一个信号,表示按钮被点击时发出的信号。
    3.[=]() 是一个 lambda 表达式,用于指定信号响应时要执行的槽函数。[=] 表示将当前作用域中的所有变量以值传递方式传入 lambda 表达式中,() 表示该 lambda 表达式不接受任何参数。
    4.changeLabelText 是一个槽函数,表示要执行的函数名。这个函数应该在当前类或者其父类中实现。
    5.label 是一个 QLabel 类型的对象指针,表示一个标签对象。
    
    因此,这句话的意思是:当按钮被点击时,执行 changeLabelText 函数,并将其中的 label 指针传递给该函数。在 changeLabelText 函数中可以通过 label 指针来操作标签对象。
    
题目要求:熟悉信号槽机制。该题目在上面的Project_3上继续完成。
(1)在主窗口类中定义一个slot槽函数changeLabelText()。
(2)在主窗口类中把主窗口中PushButton的clicked信号与槽changeLabelText ()关联在一起. 
(3)在showDlg()完成如下处理:如果主窗口中的label的文本为: access from code,则修改其文本为:I’m a label;反之,则修改为:access from code。提示:字符串比较,可以用QString中的compare函数。
#include "widget.h"
#include "ui_widget.h"
#include "QPushButton"
#include "QLabel"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton * button=new QPushButton("Change Label",this);
    QLabel * label=new QLabel("I'm a label",this);
    label->move(50,50);
    label->setFixedSize(200,200);

    connect(button,&QPushButton::clicked,[=](){changeLabelText(label);});
}

Widget::~Widget()
{
    delete ui;
}

void Widget::changeLabelText(QLabel *label)
{
    if(label->text().compare("access from code")==0)
    {
        label->setText("I'm a label");
    }
    else
    {
        label->setText("access from code");
    }
}
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    void changeLabelText(QLabel *label);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

5.标准对话框

题目要求:熟悉标准对话框
(1)新建一个空的Qt项目:Project_4
(2)新建一个主窗口类,继承于Widget
(3)在Qt Designer中编辑主窗口界面,放置如教材中图3-11所示的按钮
(4)增加并关联每个按钮单击的信号槽
(5)在每个按钮对应的槽函数中,显示对应的标准对话框。
#include "widget.h"
#include "ui_widget.h"

#include "QDebug"
#include "QColorDialog"
#include "QFileDialog"
#include "QFontDialog"
#include "QLineEdit"
#include "QInputDialog"
#include "QMessageBox"
#include "QProgressDialog"
#include "QErrorMessage"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    errordlg=new QErrorMessage(this);
}

Widget::~Widget()
{
    delete ui;
}

//颜色对话框
void Widget::on_pushButton_clicked()
{
    QColor color=QColorDialog::getColor(Qt::red,this,tr("颜色对话框"));
    qDebug()<<"color:"<pushButton_3->setFont(font);
    }
    else
    {
        qDebug()<setWindowTitle(tr("错误信息对话框"));
    errordlg->showMessage(tr("这里是出错信息!"));
}

//3个向导页面
QWizardPage *Widget::createPage1()
{
    QWizardPage *page=new QWizardPage;
    page->setTitle(tr("介绍"));
    return page;
}
QWizardPage *Widget::createPage2()
{
    QWizardPage *page=new QWizardPage;
    page->setTitle(tr("用户信息选择"));
    return page;
}
QWizardPage *Widget::createPage3()
{
    QWizardPage *page=new QWizardPage;
    page->setTitle(tr("结束"));
    return page;
}
//向导对话框
void Widget::on_pushButton_8_clicked()
{
    QWizard wizard(this);
    wizard.setWindowTitle(tr("向导对话框"));
    wizard.addPage(createPage1());//添加向导页面
    wizard.addPage(createPage2());
    wizard.addPage(createPage3());
    wizard.exec();
}
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget;class QErrorMessage; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

    void on_pushButton_5_clicked();

    void on_pushButton_6_clicked();

    void on_pushButton_7_clicked();

    void on_pushButton_8_clicked();

private:
    Ui::Widget *ui;

    QErrorMessage *errordlg;//错误消息对话框

    //向导对话框
    QWizardPage *createPage1();
    QWizardPage *createPage2();
    QWizardPage *createPage3();
};
#endif // WIDGET_H

Lab6

1.布局设计

 二、使用Designer进行布局设计
(1) 建立一个以QWidget为窗口的项目Project_1
(2) 在Designer中,设计教材图4-2(旧版4-3)所示的界面
(3) 定义如图中所示的热键(提示:要设定Buddy关系);确定每个部件的Tab order
(4) 性别下拉框中,加入“男”,“女”两项
(5) 年龄范围设为(10-60),步长为1
(6) PushButton的文本改为“保存”
(7) 为“保存”按钮定义一个单击槽函数,处理如下事情:1. 检查姓名、邮箱项是否为空,如果是空的,弹出一个对话框,提示哪项不能为空;2. 如果检查通过了,则根据姓名、性别、年龄和邮箱生成一个数据,保存到一个链表list中。同时,利用qDebug函数输出该数据,看看是否正确。提示: 可以定义一个结构体DataItem, 再使用std::list定义一个链表. std::list为C++标准库中的链表实现, 为一个模板类, 使用时需要#include 
#include "widget.h"
#include "ui_widget.h"
#include "QShortcut"
#include "QMessageBox"
#include "QDebug"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //连接保存按钮
    connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(on_saveButton_clicked()));

    //设置性别下拉框内容
    ui->sexComboBox->addItem("男");
    ui->sexComboBox->addItem("女");

    //设置年龄滑动条范围和步长
    ui->ageSlider->setRange(10,60);
    ui->ageSlider->setSingleStep(1);

    //创建快捷键
    QShortcut *nameShortcut=new QShortcut(QKeySequence("Ctrl+N"),this);
    connect(nameShortcut,SIGNAL(activated()),ui->nameEdit,SLOT(setFocus()));

    QShortcut* sexShortcut = new QShortcut(QKeySequence("Ctrl+S"), this);
    connect(sexShortcut, SIGNAL(activated()), ui->sexComboBox, SLOT(setFocus()));

    QShortcut* ageShortcut = new QShortcut(QKeySequence("Ctrl+A"), this);
    connect(ageShortcut, SIGNAL(activated()), ui->ageSlider, SLOT(setFocus()));

    QShortcut* emailShortcut = new QShortcut(QKeySequence("Ctrl+E"), this);
    connect(emailShortcut, SIGNAL(activated()), ui->emailEdit, SLOT(setFocus()));

    //部件跳转
    //以便用户可以方便地从一个组件跳转到另一个组件,并且键盘输入的焦点将正确地移动到下一个组件。
    ui->label_name->setBuddy(ui->nameEdit);
    ui->label_sex->setBuddy(ui->sexComboBox);
    ui->label_age->setBuddy(ui->ageSlider);
    ui->label_email->setBuddy(ui->emailEdit);

    //tab切换顺序
    //确保在按下Tab键时,焦点将正确地移动到下一个组件。
    QWidget::setTabOrder(ui->nameEdit, ui->sexComboBox);
    QWidget::setTabOrder(ui->sexComboBox, ui->ageSlider);
    QWidget::setTabOrder(ui->ageSlider, ui->emailEdit);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_saveButton_clicked()
{
    //获取输入数据
    QString name=ui->nameEdit->text();
    QString sex=ui->sexComboBox->currentText();
    int age =ui->ageSlider->value();
    QString email=ui->emailEdit->text();

    //检查数据是否为空
    if(name.isEmpty())
    {
        QMessageBox::warning(this,"提示","姓名不能为空");
        return;
    }
    if(email.isEmpty())
    {
        QMessageBox::warning(this,"提示","邮箱不能为空");
        return;
    }

    //保存数据到链表
    DataItem item={name,sex,age,email};
    dataList.push_back(item);

    //输出
    qDebug()<<"姓名:"<
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

struct DataItem{
    QString name;
    QString sex;
    int age;
    QString emainl;
};

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_saveButton_clicked();

private:
    Ui::Widget *ui;
    std::list  dataList;
};
#endif // WIDGET_H

2.数据界面互动

三、数据与界面互动:扩展Project_1的功能
(1) 把窗口最下面的LineEdit替换为两个按钮:Pre, Next.
(2) 按下Pre键,窗口显示list中的上一条记录,按下Next键显示list中的下一条记录。
#include "widget.h"
#include "ui_widget.h"
#include "QMessageBox"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->spinBox_age->setRange(10,60);
    ui->spinBox_age->setSingleStep(1);

    connect(ui->pushButton_Pre,SIGNAL(clicked()),this,SLOT(on_Prebutton_Clicked()));
    connect(ui->pushButton_next,SIGNAL(clicked()),this,SLOT(on_Nextbutton_Clicked()));
    connect(ui->pushButton_save,SIGNAL(clicked()),this,SLOT(on_Savebutton_Clicked()));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_Savebutton_Clicked()
{
    QString name=ui->lineEdit_name->text();
    int age=ui->spinBox_age->value();

    if(name.isEmpty())
    {
        QMessageBox::warning(this,"提示","姓名不能为空");
        return;
    }

    DataItem item={name,age};
    dataList.push_back(item);
    currentData++;
    allData++;
}

void Widget::updateData()
{
    ui->lineEdit_name->setText(dataList[currentData].name);
    ui->spinBox_age->setValue(dataList[currentData].age);
}

void Widget::on_Prebutton_Clicked()
{
    if(currentData>0)
    {
        currentData--;
        updateData();
    }
}

void Widget::on_Nextbutton_Clicked()
{
    if(currentData
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

struct DataItem{
    QString name;
    int age;
};

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;
    int allData=-1;
    int currentData=-1;
    QList dataList;
    void updateData();

private slots:
    void on_Prebutton_Clicked();
    void on_Nextbutton_Clicked();
    void on_Savebutton_Clicked();

};
#endif // WIDGET_H

3.多窗口切换

四、做一基于QWidget的程序,上面有一个QTextEdit,还有两个按钮“登录”“更改密码”,请注意以上三个部件要求使用合理布局。当点击登录时,跳出登录界面如图所示用户能输入用户名、密码.
当用户输入用户名和密码后,点击登录,登录窗口关闭,如果用户名密码正确,程序提示,登陆成功,并在主窗口QTextEdit钟显示“{用户名}登陆成功!”如果用户输入用户密码错误时,在窗口的中心部件提示提示用户输入错误,请重新输入。
#include "widget.h"
#include "ui_widget.h"

#include "QDialog"
#include "QLabel"
#include "QLineEdit"
#include "QPushButton"
#include "QHBoxLayout"
#include "QVBoxLayout"
#include "QMessageBox"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //点击登录按钮
    connect(ui->pushButton_log,SIGNAL(clicked()),this,SLOT(on_Login_Button_Clicked()));
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_Login_Button_Clicked()
{
    //创建新界面
    QDialog loginDialog(this);
    loginDialog.setWindowTitle("Login");

    //新建界面
    QLabel *usernameLabel=new QLabel("Username:");
    QLineEdit *usernameLineEdit=new QLineEdit;
    QLabel *passwordLabel=new QLabel("Password:");
    QLineEdit *passwordLineEdit=new QLineEdit;
    //setEchoMode 是 Qt 框架中 QLineEdit 类的一个函数,用于设置文本框中输入的内容是否回显。
    //它有以下几种模式:
    //QLineEdit.Normal:默认模式,输入的字符将会回显。
    //QLineEdit.NoEcho:输入的字符将不会回显,常用于密码等敏感信息的输入。
    //QLineEdit.Password:输入的字符将会被掩盖,以密文形式显示。
    //QLineEdit.PasswordEchoOnEdit:输入的字符在编辑时将会被掩盖,但在输入完成后会以密文形式显示。
    passwordLineEdit->setEchoMode(QLineEdit::Password);

    QPushButton *loginButton=new QPushButton("Login");
    QPushButton *cancelButton=new QPushButton("Cancel");

    //QHBoxLayout 是 Qt 框架中的一个布局类,用于水平排列子部件。
    //它将子部件按照左到右的方向依次排列,并且会自动调整子部件的大小和位置以适应布局
    QHBoxLayout *buttonLayout=new QHBoxLayout;//创建水平布局
    buttonLayout->addWidget(loginButton);//加入水平布局
    buttonLayout->addWidget(cancelButton);

    //QVBoxLayout 是 Qt 框架中的一个布局类,用于垂直排列子部件。
    //它将子部件按照上到下的方向依次排列,并且会自动调整子部件的大小和位置以适应布局。
    QVBoxLayout *mainLayout=new QVBoxLayout;//创建垂直布局
    mainLayout->addWidget(usernameLabel);//加入垂直布局
    mainLayout->addWidget(usernameLineEdit);
    mainLayout->addWidget(passwordLabel);
    mainLayout->addWidget(passwordLineEdit);
    mainLayout->addLayout(buttonLayout);//水平和垂直布局结合

    //布局加入主界面
    loginDialog.setLayout(mainLayout);

    //实现登录按钮功能
    connect(loginButton,&QPushButton::clicked,[&](){
        QString username=usernameLineEdit->text();
        QString password=passwordLineEdit->text();
        if(username=="zyy"&&password=="666")
        {
            loginDialog.accept();
        }
        else
        {
            QMessageBox::warning(&loginDialog,"Error","Invalid username or password. Please try again.");
        }
    });
    loginDialog.setModal(true);//设置模态窗口
    loginDialog.exec();
}
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_Login_Button_Clicked();

private:
    Ui::Widget *ui;
    QTextEdit *textEdit;
};
#endif // WIDGET_H

Lab7

1.PushButton按钮组件

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 

// 设置函数,用于绑定事件
void Print()
{
    std::cout << "hello lyshark" << std::endl;
}

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 创建[退出]按钮
    QPushButton * btn = new QPushButton;   // 创建一个按钮
    // btn->show();                        // 用顶层方法弹出按钮
    btn->setParent(this);                  // 设置父窗体(将btn内嵌到主窗体中)
    btn->setText("退出");                   // 设置按钮text显示
    btn->move(100,200);                    // 移动按钮位置
    btn->resize(100,50);                   // 设置按钮大小
    btn->setEnabled(true);                 // 设置是否可被点击

    // 创建[触发信号]按钮
    QPushButton * btn2 = new QPushButton("触发信号",this);
    btn2->setParent(this);
    btn2->move(100,100);
    btn2->resize(100,50);

    // 设置主窗体常用属性
    this->resize(500,400);            // 重置窗口大小,调整主窗口大小
    this->setWindowTitle("我的窗体");  // 重置主窗体的名字
    this->setFixedSize(1024,300);     // 固定窗体大小(不让其修改)
    // this->showFullScreen();        // 设置窗体全屏显示

    // 设置主窗体特殊属性
    // setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); // 隐藏标题栏

    // 为按钮绑定事件 connect(信号的发送者,发送的信号,信号的接受者,处理的函数(槽函数))
    connect(btn,&QPushButton::clicked,this,&QWidget::close);

    // 将窗体中的 [触发信号] 按钮,连接到Print函数中.
    connect(btn2,&QPushButton::clicked,this,&Print);
}

MainWindow::~MainWindow()
{
    delete ui;
}

2.LineEdit单行输入组件

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 设置计算和编辑框不可修改
    ui->NumberSum->setEnabled(false);
    ui->lineEdit_hex->setEnabled(false);
    ui->lineEdit_bin->setEnabled(false);

    // 设置为密码输入
    ui->NumberSum->setEchoMode(QLineEdit::Password);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 当点击计算按钮后完成计算
void MainWindow::on_pushButton_clicked()
{
    // 得到两个编辑框的数据
    QString string_total;
    QString Number_One = ui->numberA->text();
    QString Number_Two = ui->NumberB->text();

    if(Number_One.length() == 0 || Number_Two.length() == 0)
    {
        ui->label_3->setText("参数不能为空");
    }
    else
    {
        // 类型转换并赋值
        int number_int = Number_One.toInt();
        float number_float = Number_Two.toFloat();

        // 计算结果并放入到第三个编辑框中
        float total = number_int * number_float;

        string_total = string_total.sprintf("%.2f",total);
        ui->NumberSum->setText(string_total);
    }
}

// 当点击进制转换按钮后触发事件
void MainWindow::on_pushButton_2_clicked()
{
    QString str = ui->lineEdit->text();
    int value = str.toUInt();

    // 转十六进制
    str = str.setNum(value,16);     // 转为16进制
    str = str.toUpper();            // 变为大写
    ui->lineEdit_hex->setText(str); // 设置hex编辑框

    // 转二进制
    str = str.setNum(value,2);        // 第一种方式转换
    str = QString::number(value,2);   // 第二种方式转换
    ui->lineEdit_bin->setText(str);   // 设置bin编辑框
}

3.简易登录界面

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 
#include 

QString m_user="admin";   // 初始化用户名
QString m_pswd="12345";   // 初始化密码
int m_tryCount=0;         // 试错次数

// 字符串MD5算法加密
QString MainWindow::encrypt(const QString &str)
{
    QByteArray btArray;
    btArray.append(str);                               // 加入原始字符串
    QCryptographicHash hash(QCryptographicHash::Md5);  // Md5加密算法

    hash.addData(btArray);                             // 添加数据到加密哈希值
    QByteArray resultArray =hash.result();             // 返回最终的哈希值
    QString md5 =resultArray.toHex();                  // 转换为16进制字符串
    return  md5;
}

// 读取用户名密码
void MainWindow::ReadString()
{
    QString organization="UserDataBase";           // 注册表
    QString appName="onley";                       // HKEY_CURRENT_USER/Software/UserDataBase/onley
    QSettings settings(organization,appName);      // 创建key-value

    bool saved=settings.value("saved",false).toBool();       // 读取 saved键的值
    m_user=settings.value("Username", "admin").toString();   // 读取 Username 键的值,缺省为admin
    QString defaultPSWD=encrypt("12345");                    // 缺省密码 12345 加密后的数据
    m_pswd=settings.value("PSWD",defaultPSWD).toString();    // 读取PSWD键的值

    if (saved)
    {
        ui->lineEdit_Username->setText(m_user);
    }
    ui->checkBox->setChecked(saved);
}

// 保存用户名密码设置
void MainWindow::WriteString()
{
    QSettings settings("UserDataBase","onley"); // 注册表键组
    settings.setValue("Username",m_user);       // 用户名
    settings.setValue("PSWD",m_pswd);           // 经过加密的密码
    settings.setValue("saved",ui->checkBox->isChecked());
}

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setFixedSize(this->width(), this->height());             // 窗口不可调节
    ui->lineEdit_Password->setEchoMode(QLineEdit::Password); // 密码输入
    ReadString();
}

MainWindow::~MainWindow()
{
    delete ui;
}

// login
void MainWindow::on_pushButton_clicked()
{
    QString user=ui->lineEdit_Username->text().trimmed();//输入用户名
    QString pswd=ui->lineEdit_Password->text().trimmed(); //输入密码

    QString encrptPSWD=encrypt(pswd); //对输入密码进行加密

    if ((user==m_user)&&(encrptPSWD==m_pswd)) //如果用户名和密码正确
    {
        WriteString();
        QMessageBox::critical(this,"成功","已登录");
    }
    else
    {
        m_tryCount++; //错误次数
        if (m_tryCount>3)
        {
            QMessageBox::critical(this, "错误", "输入错误次数太多,强行退出");
            this->close();
        }
        else
        {
            QMessageBox::warning(this, "错误提示", "用户名或密码错误");
        }

    }
}

4.SpinBox组件

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->doubleSpinBox->setEnabled(false);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 实现精度计算功能
void MainWindow::on_pushButton_3_clicked()
{
    int x = ui->spinBox->value();
    int y = ui->spinBox_2->value();

    double total = x+y;
    ui->doubleSpinBox->setValue(total);   // 设置SpinBox数值(设置时无需转换)

    QString label_value = ui->label_10->text();  // 获取字符串
    ui->label_10->setNum(total);                 // 设置label标签为数字
}
  • 自动触发运算
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->doubleSpinBox->setEnabled(false);

    // 将数量和单价两个SpinBox的valueChanged()信号与on_pushButton_clicked()槽关联
    // 只要spinBox中的内容发生变化,则立即触发按钮完成计算
    QObject::connect(ui->spinBox,SIGNAL(valueChanged(int)),this,SLOT(on_pushButton_clicked()));
    QObject::connect(ui->spinBox_2,SIGNAL(valueChanged(int)),this,SLOT(on_pushButton_clicked()));
    QObject::connect(ui->doubleSpinBox,SIGNAL(valueChanged(double)),this,SLOT(on_pushButton_clicked()));
}

// By : LyShark
// https://www.cnblogs.com/lyshark
MainWindow::~MainWindow()
{
    delete ui;
}

// 实现精度计算功能
void MainWindow::on_pushButton_clicked()
{
    int x = ui->spinBox->value();
    int y = ui->spinBox_2->value();

    double total = x+y;
    ui->doubleSpinBox->setValue(total);   // 设置SpinBox数值(设置时无需转换)

    QString label_value = ui->label_10->text();  // 获取字符串
    ui->label_10->setNum(total);                 // 设置label标签为数字
}

5.HorizontalSlider 滑块条组件

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 将 SliderGreen,SliderBlue,SliderAlpha 与第一个滑块条 SliderRead 关联起来
    // 实现效果为,当其他三个选择条数值改变时,同样会触发on_SliderRed_valueChanged槽函数
    QObject::connect(ui->SliderRed,SIGNAL(valueChanged(int)),this,SLOT(on_SliderRed_valueChanged(int)));
    QObject::connect(ui->SliderGreen,SIGNAL(valueChanged(int)),this,SLOT(on_SliderRed_valueChanged(int)));
    QObject::connect(ui->SliderBlue,SIGNAL(valueChanged(int)),this,SLOT(on_SliderRed_valueChanged(int)));
    QObject::connect(ui->SliderAlpha,SIGNAL(valueChanged(int)),this,SLOT(on_SliderRed_valueChanged(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 当拖动SliderRed滑块条时设置TextEdit底色
void MainWindow::on_SliderRed_valueChanged(int value)
{
    Q_UNUSED(value);
    QColor  color;
    int R=ui->SliderRed->value();      // 读取SliderRed的当前值
    int G=ui->SliderGreen->value();    // 读取 SliderGreen 的当前值
    int B=ui->SliderBlue->value();     // 读取 SliderBlue 的当前值
    int alpha=ui->SliderAlpha->value();// 读取 SliderAlpha 的当前值
    color.setRgb(R,G,B,alpha);         // 使用QColor的setRgb()函数获得颜色

    QPalette pal=ui->textEdit->palette(); // 获取textEdit原有的 palette
    pal.setColor(QPalette::Base,color);   // 设置palette的基色(即背景色)
    ui->textEdit->setPalette(pal);        // 设置为textEdit的palette,改变textEdit的底色
}

6.数码表与LCD屏幕

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

// By : LyShark
// https://www.cnblogs.com/lyshark
MainWindow::~MainWindow()
{
    delete ui;
}


// 当圆形选择框数值改变时设置数码表显示
void MainWindow::on_dial_valueChanged(int value)
{
   ui->LCDDisplay->display(value);
}


// 选中时设置为十进制显示
void MainWindow::on_radioBtnDec_clicked()
{
    ui->LCDDisplay->setDigitCount(3);   // 设置位数
    ui->LCDDisplay->setDecMode();       // 十进制
}


// 选中设置为二进制显示
void MainWindow::on_radioBtnBin_clicked()
{
    ui->LCDDisplay->setDigitCount(8);
    ui->LCDDisplay->setBinMode();
}


// 选中设置为八进制显示
void MainWindow::on_radioBtnOct_clicked()
{
    ui->LCDDisplay->setDigitCount(5);
    ui->LCDDisplay->setOctMode();
}


// 选中设置为十六进制显示
void MainWindow::on_radioBtnHex_clicked()
{
    ui->LCDDisplay->setDigitCount(3);
    ui->LCDDisplay->setHexMode();
}

7.CheckBox 多选框

多选框CheckBox组件也是最常用的组件,多选框支持三态选择,选中半选中和未选中状态。

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->checkBox->setTristate();       // 启用三态选择框
    ui->checkBox->setEnabled(true);    // 设置为可选状态
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 三态选择框状态
void MainWindow::on_checkBox_stateChanged(int state)
{
    // 选中状态
    if (state == Qt::Checked)
    {
       ui->checkBox->setText("选中");
    }
    // 半选状态
    else if(state == Qt::PartiallyChecked)
    {
       ui->checkBox->setText("半选");
    }
    // 未选中
    else
    {
       ui->checkBox->setText("未选中");
    }
}

// 设置取消选中
void MainWindow::on_pushButton_clicked()
{
    int check = ui->checkBox->isCheckable();
    if(check == 1)
    {
        ui->checkBox->setChecked(false);
    }
}

// 关联式多选框
void MainWindow::on_checkBox_master_stateChanged(int state)
{
    // 选中所有子框
    if(state == Qt::Checked)
    {
        ui->checkBox_sub_a->setChecked(true);
        ui->checkBox_sub_b->setChecked(true);
    }
    // 取消子框全选状态
    if(state == Qt::Unchecked)
    {
        ui->checkBox_sub_a->setChecked(false);
        ui->checkBox_sub_b->setChecked(false);
    }
}

8.ComBox 下拉框组件

该组件提供了下拉列表供用户选择,ComBox组件除了可以显示下拉列表外,每个项还可以关联一个QVariant类型的变量用于存储不可见数据。

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 

// 定义为全局变量
QMap City_Zone;
QMap> map;
QList tmp;

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 循环方式添加元素
    ui->comboBox_main->clear();
    QIcon icon;
    icon.addFile(":/image/1.ico");
    for(int x=0;x<10;x++)
    {
        ui->comboBox_main->addItem(icon,QString::asprintf("元素_%d",x));
    }

    // 批量添加combox元素
    ui->comboBox_main->clear();
    QStringList str;
    str << "北京" << "上海" << "广州";

    ui->comboBox_main->addItems(str);
    ui->comboBox_main->setItemIcon(0,QIcon(":/image/1.ico"));
    ui->comboBox_main->setItemIcon(1,QIcon(":/image/2.ico"));
    ui->comboBox_main->setItemIcon(2,QIcon(":/image/3.ico"));

    // 实现combox联动效果
    ui->comboBox_main->clear();
    City_Zone.insert("请选择",0);
    City_Zone.insert("北京",1);
    City_Zone.insert("上海",2);
    City_Zone.insert("广州",3);

    // 循环填充一级菜单
    ui->comboBox_main->clear();
    foreach(const QString &str,City_Zone.keys())
    {
        ui->comboBox_main->addItem(QIcon(":/image/1.ico"),str,City_Zone.value(str));
    }

    // 插入二级菜单
    tmp.clear();
    tmp << "大兴区" << "昌平区" << "东城区";
    map["北京"] = tmp;

    tmp.clear();
    tmp << "黄浦区" << "徐汇区" << "长宁区" << "杨浦区";
    map["上海"] = tmp;

    tmp.clear();
    tmp << "荔湾区" << "越秀区";
    map["广州"] = tmp;

    // 设置默认选择第三个
    ui->comboBox_main->setCurrentIndex(3);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 获取当前选中的两级菜单内容
void MainWindow::on_pushButton_clicked()
{
    QString one = ui->comboBox_main->currentText();
    QString two = ui->comboBox_submain->currentText();
    std::cout << one.toStdString().data() << " | " << two.toStdString().data() << std::endl;
}

// 当主ComBox被选择时,自动的填充第2个ComBox中的数据.
void MainWindow::on_comboBox_main_currentTextChanged(const QString &arg1)
{
    ui->comboBox_submain->clear();
    QList qtmp;

    qtmp = map.value(arg1);
    for(int x=0;xcomboBox_submain->addItem(QIcon(":/image/2.ico"),qtmp[x]);
    }
}

9.ProgressBar 进度条与定时器

进度条ProgressBar组件通常会结合QTimer定时器组件共同使用,首先我们需要设置一个时钟周期,定时器每经过一定的时间周期则执行对变量或进度条的递增操作,由此实现进度条动态输出效果。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 

QTimer *my_timer;

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 初始化进度条数值
    ui->progressBar->setValue(0);
    ui->progressBar_2->setValue(100);


    // 声明定时器
    my_timer = new QTimer(this);

    // 绑定一个匿名函数
    connect(my_timer,&QTimer::timeout,[=]{
        static int x = 0;

        // 判断是否到达了进度条的最大值
        if(x != 100)
        {
            x++;
            ui->progressBar->setValue(x);
            ui->progressBar_2->setValue(int(100-x));
        }
        else
        {
            x=0;
            my_timer->stop();
        }
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 启动定时器,并设置周期为100毫秒
void MainWindow::on_pushButton_clicked()
{
    if(my_timer->isActive() == false)
    {
        my_timer->start(100);
    }
}

// 停止定时器
void MainWindow::on_pushButton_2_clicked()
{
    if(my_timer->isActive() == true)
    {
        my_timer->stop();
    }
}

// 将进度条置空
void MainWindow::on_pushButton_3_clicked()
{
    ui->progressBar->setValue(0);
    ui->progressBar_2->setValue(100);
}

10.DateTime 日期与时间组件

时间组件中包括了可以显示时间的QTime显示日期的QDate以及可同时显示时间与日期的QDateTime这三种组件,三种组件的使用上几乎一致,如下代码是开发中最常用的总结。

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 获取当前日期时间,并初始化到组件中
void MainWindow::on_pushButton_clicked()
{
     QDateTime curDateTime = QDateTime::currentDateTime();

     ui->timeEdit->setTime(curDateTime.time());
     ui->dateEdit->setDate(curDateTime.date());
     ui->dateTimeEdit->setDateTime(curDateTime);

     ui->lineEdit->setText(curDateTime.toString("yyyy-MM-dd hh:mm:ss"));
}

// 将字符串时间日期转换到时间日期组件中
void MainWindow::on_pushButton_2_clicked()
{
    QString str = ui->lineEdit_2->text();
    str = str.trimmed();
    if(!str.isEmpty())
    {
        QDateTime datetime = QDateTime::fromString(str,"yyyy-MM-dd hh:mm:ss");
        ui->dateTimeEdit_string_to_datetime->setDateTime(datetime);
    }
}

11.PlainTextEdit 多行文本框

多行文本编辑器,用于显示和编辑多行简单文本,如下代码左侧PlainTextEdit中输入数据(每行换行)点击按钮后自动将左侧数据放入右侧的listView组件中。

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 状态栏的创建
    QStatusBar * stBar = statusBar();
    setStatusBar(stBar);

    QLabel * label = new QLabel("左侧提示信息",this);
    stBar->addWidget(label);

    QLabel * label2 = new QLabel("右侧提示信息",this);
    stBar->addPermanentWidget(label2);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 点击按钮实现将 plainTextEdit 里面的数据逐行放入到右侧
void MainWindow::on_pushButton_clicked()
{
    QTextDocument* doc = ui->plainTextEdit->document ();  // 文本对象
    int count = doc->blockCount();                        // 定义回车为分隔符

    // 定义data,model用于存储每个文本
    QStringList data;
    QStringListModel *model;

    for(int x=0;x< count;x++)
    {
        QTextBlock textLine = doc->findBlockByNumber(x); // 每次取出plainTextEdit中的一行
        QString str = textLine.text();
        data << str;                                     // 放入链表中
    }

    // 显示到ListView中
    model = new QStringListModel(data);
    ui->listView->setModel(model);
}

12.RadioButton 单选框分组

单选框是最常用的组件,在一个界面中可以有多种单选框,每种单选框都会对应一个问题,此实我们需要使用ButtonGroup组件对单选框进行分组,并通过信号和槽函数相互绑定,从而实现对用户的多种选择进行判断。

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 

QButtonGroup *group_sex;
QButtonGroup *group_hobby;

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 将不同的RadioButton放入不同的ButtonGroup组中
    group_sex = new QButtonGroup(this);
    group_sex->addButton(ui->radioButton_male,0);
    group_sex->addButton(ui->radioButton_female,1);
    group_sex->addButton(ui->radioButton_unknown,2);
    ui->radioButton_unknown->setChecked(true);

    group_hobby = new QButtonGroup(this);
    group_hobby->addButton(ui->radioButton_eat,3);
    group_hobby->addButton(ui->radioButton_drink,4);
    group_hobby->addButton(ui->radioButton_sleep,5);
    ui->radioButton_eat->setChecked(true);

    // 绑定信号和槽
    connect(ui->radioButton_male,SIGNAL(clicked(bool)),this,SLOT(MySlots()));
    connect(ui->radioButton_female,SIGNAL(clicked(bool)),this,SLOT(MySlots()));
    connect(ui->radioButton_unknown,SIGNAL(clicked(bool)),this,SLOT(MySlots()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 手动创建一个槽函数,此处的槽函数声明需要加入到头文件private slots中
void MainWindow::MySlots()
{
    switch(group_sex->checkedId())
    {
    case 0:
        std::cout << "male" << std::endl;
        break;
    case 1:
        std::cout << "female" << std::endl;
        break;
    case 2:
        std::cout << "unknown" << std::endl;
        break;
    }
}

Lab8

1.处理文档菜单

用Qt做一个基于主窗口的程序,用于处理文档,要求如下:
1.要有菜单,其中至少有3个常用菜单项具有图标,快捷键,图标是基于qt资源的;
2.要有工具栏,工具栏中有主要菜单项的按钮;
3.状态栏,用于显示软件名称、作者,文档信息(字数或当前行列数,自定)
4.有“关于”菜单项,弹出关于对话框,显示软件作者姓名、软件名称、开发日期
5.软件“登录”菜单项,用于验证用户名、密码,点击登录菜单项后,弹出登录对话框,当用户输入用户名、密码点击确定,核对已有用户名和密码,核对通过则进入,否则提示错误,并且重试;当登陆成功后,登陆菜单项变为灰色;“退出当前用户”变为可用
6.当登陆成功后,状态栏显示临时信息“当前用户为***(你登陆的用户名)”
7.能够打开硬盘上已有记事本文档(使用标准对话框中的文件打开对话框)
8.能够保存窗口显示文字为txt文件
9.能够使用字体选择组合框更改显示字体
10.右键弹出式菜单,能够关闭程序和选择字体。
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_currentFile = "Project_2.txt";
    m_softwareName = "My Text Editor";
    m_author = "zyy";
    m_softwareName = "My Text Editor";
    m_developmentDate = "2023/05/28";

    createActions();//菜单
    createToolBars();//工具栏
    //createToolButtons();
    createStatusBar();//状态栏
    showContextMenu();//右键菜单

}

MainWindow::~MainWindow()
{
    delete ui;
}

//菜单初始状态
void MainWindow::createActions()
{
    //打开菜单项
    connect(ui->actionOpen_O,&QAction::triggered,this,&MainWindow::openFile);

    //保存菜单项
    connect(ui->actionSave_S,&QAction::triggered,this,&MainWindow::saveFile);

    //退出菜单项
    connect(ui->actionExit,&QAction::triggered,this,&MainWindow::close);

    //登录菜单项
    connect(ui->actionLogin_M,&QAction::triggered,this,&MainWindow::login);

    //退出登录菜单项
    connect(ui->actionLogout_N,&QAction::triggered,this,&MainWindow::logout);
    ui->actionLogout_N->setEnabled(false);//设为不可用

    //关于菜单项
    connect(ui->actionAbout_A,&QAction::triggered,this,&MainWindow::about);

    //字体选择组合框
    // 将QTextEdit的字体设置为QFontComboBox当前选择的字体
    connect(ui->fontComboBox, &QFontComboBox::currentFontChanged, this, &MainWindow::onFontChanged);
}

void MainWindow::openFile()
{
    //getOpenFileName打开一个对话框,让用户选择一个文件并返回它的文件名
    //QString QFileDialog::getOpenFileName(
    //QWidget *parent = nullptr, //对话框的父窗口
    //const QString &caption = QString(), //对话框的标题
    //const QString &dir = QString(), //对话框打开的初始目录
    //const QString &filter = QString(), //文件过滤器
    //QString *selectedFilter = nullptr, //用户选择的过滤器
    //Options options = Options()) //对话框的选项
    //该函数返回用户选择的文件名,如果用户取消选择则返回空字符串。
    QString fileName=QFileDialog::getOpenFileName(
                this,tr("Open File"),"",
                tr("Text Files(*.txt);;All Files(*)"));
    if (!fileName.isEmpty())
    {
        //根据路径读取文件
        QFile file(fileName);
        //以只读文本模式打开文件
        //QIODevice::ReadOnly表示以只读方式打开文件,
        //QIODevice::Text表示以文本模式打开文件
        if(file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            //创建一个QTextStream对象并将其与一个文件关联
            //则可用>><<进行读写操作
            QTextStream in(&file);
            ui->textEdit->setPlainText(in.readAll());//清空原有文本,写入新文本
            file.close();
            m_currentFile=fileName;
            setWindowTitle(m_currentFile + " - " + m_softwareName);
        }
        else
        {
            QMessageBox::warning(this,
                                 tr("Open File"),
                                 tr("Cannot open file: %1").arg(fileName)
                                 );
        }
    }
}

void MainWindow::saveFile()
{
    if (m_currentFile == "Project_2.txt")
    {
        QString fileName = QFileDialog::getSaveFileName(
                    this, tr("Save File"), "",
                    tr("Text Files (*.txt);;All Files (*)")
                    );
        if (!fileName.isEmpty())
        {
            m_currentFile = fileName;
            setWindowTitle(m_currentFile + " - " + m_softwareName);
        }
        else
        {
            return;
        }
    }
    QFile file(m_currentFile);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream out(&file);
        out << ui->textEdit->toPlainText();//写入文件
        file.close();
        QMessageBox::information(this, tr("Save File"), tr("File saved successfully."));
    }
    else
    {
        QMessageBox::warning(this,
                             tr("Save File"),
                             tr("Cannot save file: %1").arg(m_currentFile));
    }
}

void MainWindow::login()
{
    bool ok;
    QString username = QInputDialog::getText(this, tr("Login"), tr("Username:"),
                                             QLineEdit::Normal, "", &ok);
    if (ok && !username.isEmpty())
    {
        QString password = QInputDialog::getText(this, tr("Login"), tr("Password:"),
                                                 QLineEdit::Password, "", &ok);
        if (ok && !password.isEmpty())
        {
            if (username == "zyy" && password == "666")
            {
                m_username = username;
                ui->actionLogin_M->setEnabled(false);
                ui->actionLogout_N->setEnabled(true);
                QMessageBox::information(this, tr("Login"), tr("Login successfully."));
                updateStatus();//更新状态栏
            }
            else
            {
                QMessageBox::warning(
                            this, tr("Login"),
                            tr("Incorrect username or password.")
                            );
                login();
            }
        }
    }
}

void MainWindow::logout()
{
    m_username = "";
    ui->actionLogin_M->setEnabled(true);
    ui->actionLogout_N->setEnabled(false);
}

void MainWindow::about()
{
    QMessageBox::about(
                this, tr("About"),
                tr("%1\nVersion 1.0\n\nAuthor: %2\nDevelopment Date: %3")
                .arg(m_softwareName).arg(m_author).arg(m_developmentDate)
                );
}

//void MainWindow::createToolButtons()
//{
//    ui->toolBtn->setText(tr("File"));
//    ui->toolBtn->setFixedSize(100, 50);
//    ui->toolBtn->addAction(ui->actionOpen_O);
//    ui->toolBtn->addAction(ui->actionSave_S);
//    ui->toolBtn->addAction(ui->actionExit);

//    //设置弹出模式
//    ui->toolBtn->setPopupMode(QToolButton::MenuButtonPopup);
//}

void MainWindow::createToolBars()
{
    m_toolbar = addToolBar(tr("File"));
    m_toolbar->addAction(ui->actionOpen_O);
    m_toolbar->addAction(ui->actionSave_S);
    m_toolbar->addSeparator();
    m_toolbar->addAction(ui->actionExit);
}

void MainWindow::createStatusBar()
{
    ui->statusBar->showMessage(tr("Welcome ~"),20000);//停留时间20000
    //创建标签
    QLabel *permanent=new QLabel(this);
    //设置一个 QFrame 的边框样式为 Box 和 Sunken
    permanent->setFrameStyle(QFrame::Box|QFrame::Sunken);
    permanent->setText("wwwwwwww");
    ui->statusBar->addPermanentWidget(permanent);//加入状态栏
}

void MainWindow::updateStatus()
{
    QLabel *statusText=new QLabel(this);
    if (!m_username.isEmpty())
    {
        statusText->setText( tr("Current user is %1").arg(m_username));
    }
    ui->statusBar->clearMessage();//清空状态栏
    ui->statusBar->addPermanentWidget(statusText);//加入状态栏
}

void MainWindow::onFontChanged(const QFont &font)
{
    ui->textEdit->setFont(font);//设置新字体
}

void MainWindow::onChooseFont()
{
    bool ok;
    //用于打开一个字体选择对话框,让用户选择自己喜欢的字体。函数返回一个 QFont 对象,表示用户选择的字体
    QFont font=QFontDialog::getFont(&ok,ui->textEdit->font(),this);
    if(ok)
    {
        ui->textEdit->setFont(font);
    }
}

void MainWindow::onContextMenuRequested(const QPoint &pos)
{
    // 在位置弹出右键弹出式菜单
    m_menu->exec(ui->textEdit->mapToGlobal(pos));
}

void MainWindow::showContextMenu()
{
    // 给textEdit添加右键菜单
    ui->textEdit->setContextMenuPolicy(Qt::CustomContextMenu);//当该Widget接收到鼠标右键点击事件时,根据设置的策略来确定是否显示上下文菜单。
    connect(ui->textEdit, &QTextEdit::customContextMenuRequested, [=](const QPoint &pos){
        QMenu *menu = new QMenu(this);
        QAction *quitAction = new QAction("退出", this);
        connect(quitAction, &QAction::triggered, [=](){
            QApplication::quit();
        });
        menu->addAction(quitAction);
        QAction *fontAction = new QAction("字体", this);
        connect(fontAction, &QAction::triggered, [=](){
            bool ok;
            QFont selectedFont = QFontDialog::getFont(&ok, ui->textEdit->font(), this);
            if (ok) {
                ui->textEdit->setFont(selectedFont);
            }
        });
        menu->addAction(fontAction);
        menu->exec(ui->textEdit->mapToGlobal(pos));
        delete menu;
    });
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void openFile();
    void saveFile();
    void about();
    void login();
    void logout();


private:
    Ui::MainWindow *ui;

    QString m_currentFile;
    QString m_softwareName;
    QString m_author;
    QString m_developmentDate;
    QString m_username;
    QToolBar *m_toolbar;
    QMenu *m_menu;

    void createActions();//初始状态
    void createToolBars();//工具栏
    //void createToolButtons();
    void createStatusBar();//状态栏
    void updateStatus();//更新状态栏
    void createMenu();//创建右键弹出式菜单
    //字体选择组合框
    void onFontChanged(const QFont &font);//当字体选择组合框中的字体更改时,并设置为新字体
    void onChooseFont();//弹出字体选择对话框,并设置为所选字体
    void onContextMenuRequested(const QPoint &pos);//text位置弹出右键弹出式菜单
    //右键菜单
    void showContextMenu();
};
#endif // MAINWINDOW_H

Lab9

1.鼠标键盘事件练习

一、事件练习:
    做一窗口,上面有一按钮(1)按下鼠标左键并拖动鼠标,按钮随着鼠标的光标移动,同时在状态栏显示鼠标以用户区坐标系表示的位置坐标;(2) 当输入焦点在窗口上时,按下键盘上的Ctrl同时按下M的时候,窗口最大化显示;(3)做弹出式菜单“窗口”,下面三个菜单项“最大”“最小”“普通”,要求菜单项需要有图标,图标自定,要求使用qt的资源;实现三个菜单项对应的功能;(4)在工具栏上添加上述三个菜单项所对应的Action。(5)在窗口上双击鼠标左键,窗口最大化,双击右键,由最大化恢复。
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include 
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    createMenu();//创建菜单
    createToolBar();//创建工具栏

}

MainWindow::~MainWindow()
{
    delete ui;
}

//鼠标左键点哪里按钮就到哪里
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) //如果点击鼠标左键
    {
        ui->pushButton->move(event->pos());//按钮随鼠标移动
        //状态栏显示
        statusBar()->showMessage(QString("X: %1, Y: %2").arg(event->pos().x()).arg(event->pos().y()));
    }
}

//按下鼠标左键,按钮跟着鼠标动
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) //判断鼠标事件中是否包含左键按下的信号(判断是否拖拽鼠标左键)
    {
        ui->pushButton->move(event->pos());
        statusBar()->showMessage(QString("X: %1, Y: %2").arg(event->pos().x()).arg(event->pos().y()));
    }
}

void MainWindow::createMenu()
{
    // 添加菜单栏
    QMenu *windowMenu = new QMenu(tr("&Window"), this);
    menuBar()->addMenu(windowMenu);

    // 添加最大化菜单项
    maximizeAction = new QAction(QIcon(":/images/bear.jpg"), tr("&Maximize"), this);
    maximizeAction->setShortcut(tr("Ctrl+M"));
    windowMenu->addAction(maximizeAction);
    connect(maximizeAction, &QAction::triggered, this, &MainWindow::on_actionMaximize_triggered);

    // 添加最小化菜单项
    minimizeAction = new QAction(QIcon(":/images/car.jpg"), tr("&Minimize"), this);
    windowMenu->addAction(minimizeAction);
    connect(minimizeAction, &QAction::triggered, this, &MainWindow::on_actionMinimize_triggered);

    // 添加普通菜单项
    normalAction = new QAction(QIcon(":/images/cow.jpg"), tr("&Normal"), this);
    windowMenu->addAction(normalAction);
    connect(normalAction, &QAction::triggered, this, &MainWindow::on_actionNormal_triggered);

}

//实现窗口最大化
void MainWindow::on_actionMaximize_triggered()
{
    setWindowState(windowState() | Qt::WindowMaximized);
}

//实现窗口最小化
void MainWindow::on_actionMinimize_triggered()
{
    setWindowState(windowState() | Qt::WindowMinimized);
}

//正常窗口大小
void MainWindow::on_actionNormal_triggered()
{
    setWindowState(windowState() & ~(Qt::WindowMaximized | Qt::WindowMinimized));
}

//创建工具栏
void MainWindow::createToolBar()
{
    QToolBar *toolBar=new QToolBar(tr("Window"),this);//创建工具栏
    addToolBar(toolBar);//toolBar工具栏添加到当前窗口中
    toolBar->addAction(maximizeAction);//添加工具项
    toolBar->addAction(minimizeAction);
    toolBar->addAction(normalAction);
}

//双击鼠标左键,窗口最大化,双击右键,由最大化恢复
void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
            setWindowState(windowState() | Qt::WindowMaximized);
        } else if (event->button() == Qt::RightButton) {
            setWindowState(windowState() & ~Qt::WindowMaximized);
        }
}

//按下键盘上的Ctrl同时按下M的时候,窗口最大化显示
void MainWindow::keyPressEvent(QKeyEvent *event)
{
    //event->modifiers()用于获取用户按下的修饰键,Qt::ControlModifier表示"Ctrl"键。
    if (event->key() == Qt::Key_M && event->modifiers() == Qt::ControlModifier) {
           setWindowState(windowState() ^ Qt::WindowMaximized);//最大化显示
       }
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void mousePressEvent(QMouseEvent *event);//鼠标按下
    void mouseMoveEvent(QMouseEvent *event);//鼠标移动
    void keyPressEvent(QKeyEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *event);

private slots:
    void on_actionMaximize_triggered();
    void on_actionMinimize_triggered();
    void on_actionNormal_triggered();

private:
    Ui::MainWindow *ui;
    QAction *maximizeAction;//最大化菜单项
    QAction *minimizeAction;//最小化菜单项
    QAction *normalAction;//普通菜单项
    void createToolBar();//创建工具栏
    void createMenu();//创建菜单
};
#endif // MAINWINDOW_H

2.定时器和随机数

使用定时器可以在指定时间执行一些功能,而要实现随机效果就要使用随机数来实现。实验目标为新建程序实现电子时钟效果,并每隔一秒随机显示一张图片。
#include "widget.h"
#include "ui_widget.h"
#include 
#include 
#include 

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    timer = new QTimer(this);
    //关联定时器溢出信号和相应的槽函数
    connect(timer, &QTimer::timeout, this, &Widget::timerUpdate);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::timerUpdate()
{
    //获取系统现在的时间
    QDateTime time = QDateTime::currentDateTime();
    //设置系统时间显示格式
    QString str = time.toString("yyyy-MM-dd hh:mm:ss dddd");
    //在标签上显示时间
    ui->lineEdit->setText(str);
    int rand = QRandomGenerator::global()->bounded(5);  // 产生5以内随机整数即0-4
    //播放图片
    QPixmap pix = QPixmap(QString(":/images/%1.JPG").arg(rand));
    ui->label->setPixmap(pix.scaled(ui->label->size(), Qt::IgnoreAspectRatio));
}

//开始按钮
void Widget::on_pushButton_clicked()
{
    timer->start(1000);
}

//结束按钮
void Widget::on_pushButton_2_clicked()
{
    timer->stop();
}
#ifndef WIDGET_H
#define WIDGET_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; class QTimer;}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void timerUpdate();

    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    QTimer *timer;
};
#endif // WIDGET_H

Lab10

1.鼠标绘图 按键缩放移动

1.创建一个简单窗口, 按下鼠标左键,拖动鼠标,在用户区上画出一个矩形,矩形左上角以初始按下鼠标的点,右下角为鼠标当前位置,放开鼠标,窗口用户区显示一个最后的矩形。按下键盘的‘l’(英文字母L的小写),矩形放大,按下‘s’键,矩形缩小,并能用方向键实现所画矩形按相应方向移动。
  • override是C++11中的一个关键字,用于显式地指示一个虚函数是重写基类中的虚函数。它的作用是帮助程序员更好地理解代码。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //设置初始窗口
    setWindowTitle("Draw Rectangle");
    setFixedSize(999, 999);
}

MainWindow::~MainWindow()
{
    delete ui;
}

//鼠标点击
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
    {
        m_startPoint=event->pos();
        m_endPoint=m_startPoint;
        update();//更新绘图内容
    }
}

//鼠标移动
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton)
    {
        m_endPoint = event->pos();
        update();
    }
}

//鼠标释放
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_endPoint = event->pos();
        update();
    }
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_L)//l放大
    {
        m_startPoint.setX(m_startPoint.x() - 5);
        m_endPoint.setX(m_endPoint.x() + 5);
        m_startPoint.setY(m_startPoint.y() - 5);
        m_endPoint.setY(m_endPoint.y() + 5);
        update();
    }
    else if (event->key() == Qt::Key_S)//s缩小
    {
        m_startPoint.setX(m_startPoint.x() + 5);
        m_endPoint.setX(m_endPoint.x() - 5);
        m_startPoint.setY(m_startPoint.y() + 5);
        m_endPoint.setY(m_endPoint.y() - 5);
        update();
    }
    else if (event->key() == Qt::Key_Left)
    {
        m_startPoint.setX(m_startPoint.x() - 10);
        m_endPoint.setX(m_endPoint.x() - 10);
        update();
    }
    else if (event->key() == Qt::Key_Right)
    {
        m_startPoint.setX(m_startPoint.x() + 10);
        m_endPoint.setX(m_endPoint.x() + 10);
        update();
    }
    else if (event->key() == Qt::Key_Up)
    {
        m_startPoint.setY(m_startPoint.y() - 10);
        m_endPoint.setY(m_endPoint.y() - 10);
        update();
    }
    else if (event->key() == Qt::Key_Down)
    {
        m_startPoint.setY(m_startPoint.y() + 10);
        m_endPoint.setY(m_endPoint.y() + 10);
        update();
    }
}

//画图
void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);//定义画笔
    painter.setPen(Qt::black);//画笔颜色
    painter.drawRect(QRect(m_startPoint, m_endPoint).normalized());
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void mousePressEvent(QMouseEvent *event) override;//鼠标点击
    void mouseMoveEvent(QMouseEvent *event) override;//鼠标移动
    void mouseReleaseEvent(QMouseEvent *event) override;//鼠标释放
    void keyPressEvent(QKeyEvent *event) override;//按键
    void paintEvent(QPaintEvent *event) override;//画图

private:
    Ui::MainWindow *ui;
    QPoint m_startPoint;//鼠标开始位置指针
    QPoint m_endPoint;//鼠标结束位置指针
};
#endif // MAINWINDOW_H

2.按键绘图 按键变色

2.做一个简单的画图程序,基本功能:
1)按“L”后,用鼠标拖拽能在屏幕上画直线;
2)按“E”后,用鼠标托拽能在屏幕上画矩形
3)按“C”后,用鼠标拖拽能在屏幕上画圆
4)按“R”“G”“B”能够改变所画图形为红、绿、蓝色
5)对上述功能做菜单、工具栏和状态栏
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void mousePressEvent(QMouseEvent *event);// 鼠标按下事件
    void mouseMoveEvent(QMouseEvent *event);// 鼠标移动事件
    void mouseReleaseEvent(QMouseEvent *event);// 鼠标释放事件
    void paintEvent(QPaintEvent *event);// 绘图事件
    void keyPressEvent(QKeyEvent *event);// 键盘事件

private slots:
    void setLineColorRed();// 将线条颜色设置为红色
    void setLineColorGreen();// 将线条颜色设置为绿色
    void setLineColorBlue();// 将线条颜色设置为蓝色
    void PaintChoose();//形状选择

private:
    Ui::MainWindow *ui;
    enum ShapeType { Line, Rectangle, Ellipse };// 定义图形类型枚举类
    ShapeType currentShape;// 当前绘制的图形类型
    bool drawing;// 是否正在绘图
    QPoint startPoint;// 绘制开始点
    QPoint endPoint;// 绘制结束点
    QColor lineColor;// 线条颜色
    QMenuBar *menuBar;// 菜单栏
    QToolBar *toolBar;// 工具栏
    QStatusBar *statusBar;// 状态栏
    QLabel *statusLabel;// 状态栏标签
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setFixedSize(999, 999);

    currentShape = Line;
    drawing = false;
    lineColor = Qt::black;

    // 创建菜单栏
    menuBar = new QMenuBar(this);
    QMenu *fileMenu = menuBar->addMenu(tr("&File"));
    QAction *exitAction = fileMenu->addAction(tr("&Exit"), this, &QWidget::close);
    QMenu *shapeMenu = menuBar->addMenu(tr("&Shape"));
    QAction *lineAction = shapeMenu->addAction(tr("&Line"), [this]() {currentShape = Line;});
    QAction *rectAction = shapeMenu->addAction(tr("&Rectangle"), [this]() {currentShape = Rectangle;});
    QAction *ellipseAction = shapeMenu->addAction(tr("&Ellipse"), [this]() {currentShape = Ellipse;});

    // 创建工具栏
    toolBar = new QToolBar(this);
    toolBar->addAction(lineAction);
    toolBar->addAction(rectAction);
    toolBar->addAction(ellipseAction);

    // 创建状态栏
    statusBar = new QStatusBar(this);
    statusLabel = new QLabel(statusBar);
    statusLabel->setText(tr("Ready"));

    //加入主窗口
    setMenuBar(menuBar);
    addToolBar(toolBar);
    setStatusBar(statusBar);

    connect(exitAction, &QAction::triggered, this, &QWidget::close);   // 退出程序
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 鼠标按下事件
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
    {
        startPoint = event->pos();
        endPoint = event->pos();
        drawing = true;//按下后表示开始绘画
    }
}

// 鼠标移动事件
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if ((event->buttons() & Qt::LeftButton) && drawing) {
        endPoint = event->pos();
        update();   // 触发绘图事件
    }
}

// 鼠标释放事件
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton && drawing)
    {
        endPoint=event->pos();
        drawing=false;
        update();
    }
}

// 绘图事件
void MainWindow::paintEvent(QPaintEvent *event)
{
    //告诉编译器忽略未使用的变量或参数。
    //在这里,"event"是一个未使用的参数,在函数中没有被使用,但为了满足函数参数的要求而被保留。
    Q_UNUSED(event);

    QPainter painter(this);
    //设置画笔颜色、线宽和样式
    painter.setPen(QPen(lineColor,2,Qt::SolidLine,Qt::RoundCap));
    //选择图形
    switch(currentShape)
    {
    case Line:
        painter.drawLine(startPoint,endPoint);
        break;
    case Rectangle:
        painter.drawRect(QRect(startPoint,endPoint));
        break;
    case Ellipse:
        painter.drawEllipse(QRect(startPoint,endPoint));
        break;
    }
}

void MainWindow::PaintChoose()
{
    QPainter painter(this);
    painter.setPen(QPen(lineColor, 2, Qt::SolidLine, Qt::RoundCap));    // 设置画笔颜色、线宽和样式

    switch (currentShape) {
    case Line:
        painter.drawLine(startPoint, endPoint);     // 画直线
        break;
    case Rectangle:
        painter.drawRect(QRect(startPoint, endPoint));    // 画矩形
        break;
    case Ellipse:
        painter.drawEllipse(QRect(startPoint, endPoint)); // 画椭圆
        break;
    }
}

//改变状态栏
void MainWindow::setLineColorRed()
{
    lineColor = Qt::red;    // 将线条颜色设置为红色
    statusLabel->setText(tr("Red line"));  // 修改状态栏标签文本
}
void MainWindow::setLineColorGreen()
{
    lineColor = Qt::green;  // 将线条颜色设置为绿色
    statusLabel->setText(tr("Green line"));    // 修改状态栏标签文本
}
void MainWindow::setLineColorBlue()
{
    lineColor = Qt::blue;   // 将线条颜色设置为蓝色
    statusLabel->setText(tr("Blue line")); // 修改状态栏标签文本
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_R)
    {
        setLineColorRed();
        PaintChoose();
        update();
    }
    else if (event->key() == Qt::Key_G)
    {
        setLineColorGreen();
        PaintChoose();
        update();
    }
    else if (event->key() == Qt::Key_B)
    {
        setLineColorBlue();
        PaintChoose();
        update();
    }
    else if (event->key() == Qt::Key_L)
    {
        currentShape=Line;
        PaintChoose();
        update();
    }
    else if (event->key() == Qt::Key_E)
    {
        currentShape=Rectangle;
        PaintChoose();
        update();
    }
    else if (event->key() == Qt::Key_C)
    {
        currentShape=Ellipse;
        PaintChoose();
        update();
    }
}

Lab11

1.布局设计

Test3(30分)signer进行布局设计 
(3)定义一个名为Person的结构体, 包括以下几个成员: 
QString name, int sex, int age, QString description
要求:用户输入的年龄范围在(20-30)
(4)单击“Add”按钮,完成如下事情:1. 检查姓名、描述是否为空,如果是空的,弹出一个对话框,提示哪项不能为空;2. 如果检查通过了,则根据用户输入生成一个Person数据,保存到一个链表std::list中。(10分)
(5)单击“Show”按钮,完成如下事情:1. 弹出一个对话框,对话框与上图相同,只是按钮名分别为“Pre”和“Next”;2. 刚弹出时,对话框中显示存储在链表中的第一条记录;3. 按下“Pre”和“Next”按钮,对话框分别显示当前记录的前一条和后一条记录信息。(15分)
#include "widget.h"
#include "ui_widget.h"
#include 
#include //垂直布局
#include //水平布局

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_add_clicked()
{
    //获取数据
    QString name=ui->lineEdit_name->text();
    QString description=ui->lineEdit_desc->text();
    int sex=ui->comboBox_sex->currentIndex();//返回当前的标签索引值
    int age=ui->spinBoxage->value();

    if(name.isEmpty())
    {
        QMessageBox::warning(this,"Warning","Name can't be empty");
        return;
    }
    if(description.isEmpty())
    {
        QMessageBox::warning(this,"Warning","Description can't be empty");
        return;
    }
    //加入链表
    Person person={name,sex,age,description};
    m_personList.push_back(person);
    QMessageBox::information(this,"Information","Person added");
}

void Widget::on_pushButton_show_clicked()
{
    if(m_personList.empty())
    {
        QMessageBox::warning(this,"Warning","No person added.");
        return;
    }

    //创建新窗口
    QDialog *dialog=new QDialog(this);
    dialog->setWindowTitle("Person");
    nameLabel = new QLabel("Name:");
    sexLabel = new QLabel("Sex:");
    ageLabel = new QLabel("Age:");
    descriptionLabel = new QLabel("Description:");

    nameValueLabel = new QLabel();
    sexValueLabel = new QLabel();
    ageValueLabel = new QLabel();
    descriptionValueLabel = new QLabel();

    preButton = new QPushButton("Pre");
    nextButton = new QPushButton("Next");

    QHBoxLayout* nameLayout = new QHBoxLayout();
    nameLayout->addWidget(nameLabel);
    nameLayout->addWidget(nameValueLabel);

    QHBoxLayout* sexLayout = new QHBoxLayout();
    sexLayout->addWidget(sexLabel);
    sexLayout->addWidget(sexValueLabel);

    QHBoxLayout* ageLayout = new QHBoxLayout();
    ageLayout->addWidget(ageLabel);
    ageLayout->addWidget(ageValueLabel);

    QHBoxLayout* descriptionLayout = new QHBoxLayout();
    descriptionLayout->addWidget(descriptionLabel);
    descriptionLayout->addWidget(descriptionValueLabel);

    QHBoxLayout* buttonLayout = new QHBoxLayout();
    buttonLayout->addStretch();
    buttonLayout->addWidget(preButton);
    buttonLayout->addWidget(nextButton);

    QVBoxLayout* mainLayout = new QVBoxLayout();
    mainLayout->addLayout(nameLayout);
    mainLayout->addLayout(sexLayout);
    mainLayout->addLayout(ageLayout);
    mainLayout->addLayout(descriptionLayout);
    mainLayout->addLayout(buttonLayout);

    dialog->setLayout(mainLayout);

    m_currentPerson = m_personList.begin();//从第一条开始
    //设置文本
    nameValueLabel->setText(m_currentPerson->name);
    sexValueLabel->setText(m_currentPerson->sex == 0 ? "Male" : "Female");
    ageValueLabel->setText(QString::number(m_currentPerson->age));
    descriptionValueLabel->setText(m_currentPerson->description);

    //int current=std::distance(m_personList.begin(),m_currentPerson);
    if (m_personList.size() == 1) {
        preButton->setEnabled(false);
        nextButton->setEnabled(false);
    }
    else {
        preButton->setEnabled(false);
        nextButton->setEnabled(true);
    }

    connect(preButton, &QPushButton::clicked, this, &Widget::onPreButtonClicked);
    connect(nextButton, &QPushButton::clicked, this, &Widget::onNextButtonClicked);

    dialog->exec();
}

void Widget::onPreButtonClicked()
{
    m_currentPerson--;

    nameValueLabel->setText(m_currentPerson->name);
    sexValueLabel->setText(m_currentPerson->sex == 0 ? "Male" : "Female");
    ageValueLabel->setText(QString::number(m_currentPerson->age));
    descriptionValueLabel->setText(m_currentPerson->description);

    preButton->setEnabled(m_currentPerson != m_personList.begin());
    nextButton->setEnabled(true);
}

void Widget::onNextButtonClicked()
{
    m_currentPerson++;

    nameValueLabel->setText(m_currentPerson->name);
    sexValueLabel->setText(m_currentPerson->sex == 0 ? "Male" : "Female");
    ageValueLabel->setText(QString::number(m_currentPerson->age));
    descriptionValueLabel->setText(m_currentPerson->description);

    preButton->setEnabled(true);
    nextButton->setEnabled(m_currentPerson != --m_personList.end());
}
#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 
#include 

struct Person{
    QString name;
    int sex;
    int age;
    QString description;
};

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_add_clicked();
    void on_pushButton_show_clicked();
    void onPreButtonClicked();
    void onNextButtonClicked();

private:
    Ui::Widget *ui;
    QListm_personList;
    QList::iterator m_currentPerson;//迭代器
    //新界面变量
    QLabel* nameLabel;
    QLabel* sexLabel;
    QLabel* ageLabel;
    QLabel* descriptionLabel;
    QLabel* nameValueLabel;
    QLabel* sexValueLabel;
    QLabel* ageValueLabel;
    QLabel* descriptionValueLabel;
    QPushButton* preButton;
    QPushButton* nextButton;
};
#endif // WIDGET_H

2.菜单

Test4(20分) MainWindow与菜单 (20)
(6)建立一个以QMainWindow为窗口的项目Project_2
(7)在Designer中,增加一个菜单File,并在其中加入三个菜单项:New, Save, Exit;进一步,在工具栏中放入上述三个菜单项对应的Action (5分)
(8)在窗口中放入一个QPlainTextEdit部件
当单击New菜单时,清空QPlainTextEdit中的内容;当单击Save菜单时,把QPlainTextEdit中的内容保存到一个用户指定的文本文件中。(15分)
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 将槽函数与菜单项的点击事件关联
    connect(ui->actionNew, &QAction::triggered, this, &MainWindow::on_actionNew_triggered);
    connect(ui->actionSave, &QAction::triggered, this, &MainWindow::on_actionSave_triggered);
    connect(ui->actionExit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 槽函数,清空QPlainTextEdit中的内容
void MainWindow::on_actionNew_triggered()
{
    ui->plainTextEdit->clear();
}

// 槽函数,将QPlainTextEdit中的内容保存到用户指定的文本文件中
void MainWindow::on_actionSave_triggered()
{
    // 获取保存文件的路径
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Text Files (*.txt)"));
    // 如果用户选择了保存文件的路径,则执行保存操作
    if (fileName != "") {
        QFile file(fileName);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&file);
            stream << ui->plainTextEdit->toPlainText(); // 将QPlainTextEdit中的内容写入文件
            file.close();
        }
    }
}

// 槽函数,退出应用程序
void MainWindow::on_actionExit_triggered()
{
    QApplication::quit();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_actionNew_triggered();
    void on_actionSave_triggered();
    void on_actionExit_triggered();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

n>

struct Person{
QString name;
int sex;
int age;
QString description;
};

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void on_pushButton_add_clicked();
void on_pushButton_show_clicked();
void onPreButtonClicked();
void onNextButtonClicked();

private:
Ui::Widget ui;
QListm_personList;
QList::iterator m_currentPerson;//迭代器
//新界面变量
QLabel
nameLabel;
QLabel* sexLabel;
QLabel* ageLabel;
QLabel* descriptionLabel;
QLabel* nameValueLabel;
QLabel* sexValueLabel;
QLabel* ageValueLabel;
QLabel* descriptionValueLabel;
QPushButton* preButton;
QPushButton* nextButton;
};
#endif // WIDGET_H


### 2.菜单

Test4(20分) MainWindow与菜单 (20)
(6)建立一个以QMainWindow为窗口的项目Project_2
(7)在Designer中,增加一个菜单File,并在其中加入三个菜单项:New, Save, Exit;进一步,在工具栏中放入上述三个菜单项对应的Action (5分)
(8)在窗口中放入一个QPlainTextEdit部件
当单击New菜单时,清空QPlainTextEdit中的内容;当单击Save菜单时,把QPlainTextEdit中的内容保存到一个用户指定的文本文件中。(15分)


```c++
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
#include 

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 将槽函数与菜单项的点击事件关联
    connect(ui->actionNew, &QAction::triggered, this, &MainWindow::on_actionNew_triggered);
    connect(ui->actionSave, &QAction::triggered, this, &MainWindow::on_actionSave_triggered);
    connect(ui->actionExit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 槽函数,清空QPlainTextEdit中的内容
void MainWindow::on_actionNew_triggered()
{
    ui->plainTextEdit->clear();
}

// 槽函数,将QPlainTextEdit中的内容保存到用户指定的文本文件中
void MainWindow::on_actionSave_triggered()
{
    // 获取保存文件的路径
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", tr("Text Files (*.txt)"));
    // 如果用户选择了保存文件的路径,则执行保存操作
    if (fileName != "") {
        QFile file(fileName);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream stream(&file);
            stream << ui->plainTextEdit->toPlainText(); // 将QPlainTextEdit中的内容写入文件
            file.close();
        }
    }
}

// 槽函数,退出应用程序
void MainWindow::on_actionExit_triggered()
{
    QApplication::quit();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_actionNew_triggered();
    void on_actionSave_triggered();
    void on_actionExit_triggered();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

你可能感兴趣的:(Qt,qt,开发语言)