QTday5

day5

事件与绘图

参考https://www.kancloud.cn/kancloud/qt-study-road-2/99458

c++知识点:虚函数-virtual-关键字,它在父类声明,在子类实现。实现动态绑定。

QWidget里面有一些虚函数声明,我们的widget继承了QWidget,所以我们在widget里实现自己的虚函数,参数返回值权限不能改变。

关闭程序时,弹出对话框提示用户是否保存文本

//widget.h
protected:
void closeEvent(QCloseEvent *event);
//widget.cpp
void Widget::closeEvent(QCloseEvent *event)
{
    if(QMessageBox::No==QMessageBox::question(this,"退出question","是否保存"))
    {//是关闭事件吗?
        event->ignore();//忽略关闭事件
        qDebug()<<"testing close event";
    }
    event->accept();//接受关闭事件
}

鼠标事件,点击左键右键,拖动或跟踪

//widget.h
protected:
void mousePressEvent(QMouseEvent *event);
//widget.cpp
void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
        qDebug()<<"testing mouse left event";
    else if(event->button()==Qt::RightButton)
        qDebug()<<"testing mouse right event";
    qDebug()<<event->x()<<","<<event->y()<<"."<<endl;
}

//widget.h
void mouseMoveEvent(QMouseEvent *event);//鼠标拖动
//widget.cpp
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    QDebug()<<"testing mouse move";
}
//鼠标跟踪
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
    //startTimer(10);
    setMouseTracking(true);//鼠标跟踪功能//不用拖动也能触发mouse move event
}

键盘事件

//widget.h
protected:
void keyPressEvent(QKeyEvent *event);
//widget.cpp
void Widget::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
        case Qt::Key_A:
            qDebug()<<"mouse left event";
            break;
        case Qt::Key_D:
            qDebug()<<"mouse right event";
            break;
    default:
        QWidget::keyPressEvent(event);
    }
}

定时器事件

//widget.h
protected:
void timerEvent(QTimerEvent*);
//widget.cpp
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
    startTimer(10);
}

void Widget::timerEvent(QTimerEvent *)
{
    qDebug()<<"定时...";
}

绘图

//widget.h
protected:
void paintEvent(QPaintEvent*);
//widget.cpp
void Widget::paintEvent(QPaintEvent *)
{
    //将窗口部件绘制出来,一开始.show()时肯定会调用
    //qDebug()<<"paintEvent";
    //最小化隐藏后再次展示,就会再次调用这个事件

    QPainter painter(this);//产生画笔
    painter.setPen(Qt::red);
    painter.drawLine(10,10,200,200);//画一条直线
}

鼠标点击的地方画点。

这时,在鼠标点击的事件里画点报错,于是我们在鼠标点击的事件记录坐标,然后在绘图事件里根据坐标画点。

    //void Widget::mousePressEvent(QMouseEvent *event)
    /*
    x_pos=event->x();//在widiget上画点
    y_pos=event->y();
    update();//强制重新绘制窗口
    */

    //void Widget::paintEvent(QPaintEvent *)
    QPainter painter(this);//产生画笔,在widget上画
    /*
    painter.setPen(Qt::red);
    painter.drawLine(10,10,200,200);//画一条直线
    */
    //painter.drawPoint(x_pos,y_pos);//只画了一个点,画完会清零

以上做法都是纯新手,在显存上画图,并且在鼠标拖动的事件里画。下面介绍双缓存,内存pixmap->显存widget

//头文件里声明pixmap,鼠标拖动事件,也声明两个坐标量用于mousemove事件和mousepress事件和paint事件
void mouseMoveEvent(QMouseEvent *event);//鼠标拖动
QPixmap pixmap;//图片缓存区,没有*号
int x,y;

//源文件构造函数里声明pixmap
//Widget::Widget(QWidget *parent)
: QWidget(parent)
pixmap=QPixmap(size());//产生一个窗口大小的空间,转换为Qpixmap类型
pixmap.fill(Qt::white);

//void Widget::paintEvent(QPaintEvent *)
QPainter painter(this);//产生画笔
//把pixmap画的图片搬到widget上
painter.drawPixmap(0,0,pixmap);//从(0,0)点开始画

//void Widget::mouseMoveEvent(QMouseEvent *event)
QPainter painter(&pixmap);
painter.setPen(Qt::red);
//painter.drawPoint(event->x(),event->y());//画点会断断续续
painter.drawLine(x,y,event->x(),event->y());
x=event->x();
y=event->y();//更新坐标
update();

//void Widget::mousePressEvent(QMouseEvent *event)
//在一开始鼠标点击的事件里记录坐标初值,传参给paintEvent
x=event->x();
y=event->y();

练习,按下S键绘制正弦曲线,空格键清空窗口

        case Qt::Key_S:
            double y;
            for(int i;i<=360;i++)
            {
                y=150-100*(qSin(i*pi/180));//坐标系处理
                painter.drawPoint(i,y);
            }

            //QPainter painter(&pixmap);//构造和析构函数不可跳过。如果没按s键,就只析构不构造了
            //painter.drawLine(10,10,300,300);

            update();
            break;
        case Qt::Key_Space:
            pixmap.fill();
            update();
            break;

登录界面

UI设计如图

ui界面

ui设计好后,转到槽,先做注册功能。需要按下按钮,打开一个文件,把两个lineedit的用户和密码输出到文件中。

//注册-把用户名和密码保存到一个文件password.dat里
QFile file("password.dat");//创建文件类对象
//QFilename *filename=get_openfilename();
if(!file.open(QIODevice::ReadWrite))//以读写模式打开
{
    QMessageBox::warning(this,"regester","open password err");
    return ;
}

QDataStream out(&file);//绑定到数据流out上
QString username,password;
while(!out.atEnd())
{
    out>>username>>password;
    if(username==ui->lineEdit->text()&&password==ui->lineEdit_2->text())
        QMessageBox::warning(this,"regester","you had regestered");
    return ;
}

//qDebug()<<"testing register";

//QTextStream out(&file);//文本流,字符连在一起,没有格式

//QDataStream out(&file);//数据流
out<<ui->lineEdit->text()<<ui->lineEdit_2->text();
QMessageBox::information(this,"regester","regester success");

实现登录功能。需要读取注册时保存的文件“password.dat”,与当前lineedit用户输入的字符比较,登录成功弹出对话框。

//登录
QFile file("password.dat");
if(!file.open(QIODevice::ReadOnly))
{
    QMessageBox::warning(this,"error","open password err");
    return ;
}
QDataStream in(&file);
QString username,password;
while(!in.atEnd())
{
    in>>username>>password;
    if(username==ui->lineEdit->text()&&password==ui->lineEdit_2->text())
    {
        QMessageBox::information(this,"login","login success");
        /*MainWindow *w=new MainWindow;
        w->show();
        close();*/
        accept();
        return ;
    }
}
QMessageBox::information(this,"login","login fail");

登录成功后,点击关闭对话框,发出accept信号,然后进入另一个mainwindow窗口

方法1:

在登录函数,判断密码正确的语句后加上accept(),在main.cpp的main()里将原来的非阻塞w.show改成事件循环,并判断接收到的信号是accept()才执行下一句,下一句就是转到另一个mainwindow窗口。

方法2:

登录触发的函数中,注释语句换成注释accept

        /*MainWindow *w=new MainWindow;
        w->show();
        close();*/
        accept();

main函数中注释的语句换成注释后面三句话
/* w.show();*/

if (w.exec()==QDialog::Rejected)//这里是事件循环,等待对话框正常关闭发出accepted信号,才执行下一步展示mainwindow
{
    return 0;
}
MainWindow m;
m.show();

实验感受

  1. 改了dialog的名字后出错,非法使用Ui::Dialog,新名字login_obj。注意创建的对象名与操作要匹配。

拓展知识

事件过滤器
https://www.kancloud.cn/kancloud/qt-study-road-2/99460

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值