QT时钟

使用QT框架的数字钟
最终成品
设置闹钟时的界面
时间设置,可以设置年月日,时分秒
具体实现方式:
1、由于要使用QSound类,需要在.pro文件中添加
QT+=muitimedia这一行代码
2、整个工程项目如下:
在这里插入图片描述
3、时钟的具体实现方法:
(1)头文件:

#ifndef MYCLOCK_H
#define MYCLOCK_H

#include <QObject>
#include<QVector>
#include<QSound>

class MyClock : public QObject
{
    Q_OBJECT
public:
    explicit MyClock(QObject *parent = nullptr);
    void reset(int year1,int month1,int day1,int hour1,int min1,int second1);
    void setRing(int hour_t,int min_t);
    void Ring();
    QVector<int> get_time();
    void count();

private:
    int hour;
    int min;
    int second;
    int day;
    int month;
    int year;
    int ringhour;
    int ringmin;

signals:

};

#endif // MYCLOCK_H

(2)各个类的方法的具体实现

#include "myclock.h"
#include<QDebug>

MyClock::MyClock(QObject *parent) : QObject(parent)
{
    year=2021;
    month=3;
    day=31;
    hour=23;
    min=59;
    second=55;
}

void MyClock::setRing(int hour_t, int min_t)
{
    ringhour=hour_t;
    ringmin=min_t;
}

void MyClock::Ring()
{
    if((hour==ringhour)&(min==ringmin)&(second==0))
    {
        QSound *sound1=new QSound(":/calling.wav");
        sound1->play();
    }
}

QVector<int> MyClock::get_time()
{
    QVector<int> t;
    t.push_back(year);
    t.push_back(month);
    t.push_back(day);
    t.push_back(hour);
    t.push_back(min);
    t.push_back(second);
    return t;
}

void MyClock::count()
{
    second++;
    if(second==60)
    {
        second=0;
        min++;
        if(min==60)
        {
            min=0;
            hour++;
            if(hour==24)
            {
                hour=0;
                day++;
                if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&(day==32))
                {
                    day=1;
                    month+=1;
                }
                if((month==4||month==6||month==9||month==10||month==11)&&(day==31))
                {
                    day=1;
                    month+=1;
                }
                if(year%4==0&&month==2&&month==30)
                {
                    day=1;
                    month+=1;
                }
                if(year%4!=0&&month==2&&month==29)
                {
                    day=1;
                    month+=1;
                }
                if(month==13)
                {
                    month=1;
                    day=1;
                    hour=0;
                    min=0;
                    second=0;
                }
            }
        }
    }
    if(((hour==0)&(min==0)&(second==0))||((hour!=0)&(min==0)&(second==0)))
    {
        QSound *sound=new QSound(":/LevelWinSound.wav");
        sound->play();
    }
    Ring();
}

void MyClock::reset(int year1, int month1, int day1, int hour1, int min1, int second1)
{
    year=year1;
    month=month1;
    day=day1;
    hour=hour1;
    min=min1;
    second=second1;
}


4、秒表
(1)头文件

#ifndef MINCLOCK_H
#define MINCLOCK_H

#include <QObject>
#include<QVector>

class MinClock : public QObject
{
    Q_OBJECT
public:
    explicit MinClock(QObject *parent = nullptr);
    QVector<int> get_time();
    void count();
    void reset();

private:
    int second;
    int minsecond;
signals:

};

#endif // MINCLOCK_H

(2)实现

#include "minclock.h"

MinClock::MinClock(QObject *parent) : QObject(parent)
{
    second=0;
    minsecond=0;
}

void MinClock::count()
{
    minsecond++;
    if(minsecond==1000)
    {
        second++;
        minsecond=0;
    }
}

void MinClock::reset()
{
    second=0;
    minsecond=0;
}

QVector<int> MinClock::get_time()
{
    QVector<int> t;
    t.push_back(second);
    t.push_back(minsecond);
    return t;
}

5、年月日,时分秒的设置对话框
(1)

#ifndef TIMESET_H
#define TIMESET_H

#include <QMainWindow>
#include<QVector>

class TimeSet : public QMainWindow
{
    Q_OBJECT
public:
    explicit TimeSet(QWidget *parent = nullptr);
    QVector<int> vector;
    QVector<int> Return();

signals:
    void set();

};

#endif // TIMESET_H

(2)

#include "timeset.h"

#include<QMessageBox>
#include<QLineEdit>
#include<QPushButton>
#include<QLabel>
#include<QString>

TimeSet::TimeSet(QWidget *parent) : QMainWindow(parent)
{
    this->setFixedSize(450,300);
    QLabel *label1=new QLabel(this);
    label1->setText("年");
    QLineEdit *edit1=new QLineEdit(this);
    edit1->move(150,0);
    QLabel *label2=new QLabel(this);
    label2->setText("月");
    label2->move(0,40);
    QLineEdit *edit2=new QLineEdit(this);
    edit2->move(150,40);
    QLabel *label3=new QLabel(this);
    label3->setText("日");
    label3->move(0,80);
    QLineEdit *edit3=new QLineEdit(this);
    edit3->move(150,80);
    QLabel *label4=new QLabel(this);
    label4->setText("时");
    label4->move(0,120);
    QLineEdit *edit4=new QLineEdit(this);
    edit4->move(150,120);
    QLabel *label5=new QLabel(this);
    label5->setText("分");
    label5->move(0,160);
    QLineEdit *edit5=new QLineEdit(this);
    edit5->move(150,160);
    QLabel *label6=new QLabel(this);
    label6->setText("秒");
    label6->move(0,200);
    QLineEdit *edit6=new QLineEdit(this);
    edit6->move(150,200);
    QPushButton *btn=new QPushButton(this);
    btn->setText("确定");
    btn->move(350,210);
    connect(btn,&QPushButton::clicked,this,[=](){
        QString string1=edit1->text();
        QString string2=edit2->text();
        QString string3=edit3->text();
        QString string4=edit4->text();
        QString string5=edit5->text();
        QString string6=edit6->text();
        int val1,val2,val3,val4,val5,val6;
        val1=string1.toInt();
        val2=string2.toInt();
        val3=string3.toInt();
        val4=string4.toInt();
        val5=string5.toInt();
        val6=string6.toInt();
        if((val1<0)|(val2<0|val2>12)|((val1%4==0)&(val2==2)&(val3>29))|((val1%4!=0)&(val2==2)&(val3>28))|((val2==1|val2==3|val2==5|val2==7|val2==8|val2==10|val2==12)&(val3>31))|(((val2==4)|(val2==6)|(val2==9)|(val2=11))&(val3>30))|(val4<0|val4>24)|(val5<0|val5>60)|(val6<0|val6>60))
        {
                QMessageBox::critical(this,"错误","数据输入错误");
        }
        else
        {
            vector.push_back(string1.toInt());
            vector.push_back(string2.toInt());
            vector.push_back(string3.toInt());
            vector.push_back(string4.toInt());
            vector.push_back(string5.toInt());
            vector.push_back(string6.toInt());
            QMessageBox::information(this,"已设置","完成");
            emit set();
        }
    });
}

QVector<int> TimeSet::Return()
{
    return vector;
}

6、设置闹钟
(1)

#ifndef SETCLOCK_H
#define SETCLOCK_H

#include <QMainWindow>
#include<QVector>
\
class SetClock : public QMainWindow
{
    Q_OBJECT
public:
    explicit SetClock(QWidget *parent = nullptr);
    QVector<int> returnsetting();
    QVector<int> vector;

signals:
    void setting();

};

#endif // SETCLOCK_H

(2)

#include "setclock.h"
#include<QPushButton>
#include<QLabel>
#include<QLineEdit>
#include<QVector>
#include<QMessageBox>
#include<QDebug>

SetClock::SetClock(QWidget *parent) : QMainWindow(parent)
{
    this->setFixedSize(400,330);
    QLabel *label1=new QLabel(this);
    label1->setText("时");
    QLineEdit *edit1=new QLineEdit(this);
    edit1->move(120,0);
    QLabel *label2=new QLabel(this);
    label2->setText("分");
    QLineEdit *edit2=new QLineEdit(this);
    label2->move(0,50);
    edit2->move(120,50);
    QPushButton *btn=new QPushButton(this);
    btn->setText("确认");
    btn->move(200,150);
    connect(btn,&QPushButton::clicked,this,[=](){
        QString str1=edit1->text();
        QString str2=edit2->text();
        if((str1.toDouble()<=23&str1.toDouble()>=0)&(str2.toDouble()>=0&str2.toDouble()<60))
        {
            int val1=str1.toInt();
            int val2=str2.toInt();
            vector.push_back(val1);
            vector.push_back(val2);
            QMessageBox::information(this,"已设置","OK");
            emit setting();
        }
        else
        {
            QMessageBox::critical(this,"错误","hour应该设置到0到24,min应该设置到0到60");
        }
    });
}

QVector<int> SetClock::returnsetting()
{
    return vector;
}

7、搞笑担当(汤家凤老师放过我)
(1)

#ifndef TANGGOD_H
#define TANGGOD_H

#include <QMainWindow>

class TangGod : public QMainWindow
{
    Q_OBJECT
public:
    explicit TangGod(QWidget *parent = nullptr);
    void paintEvent(QPaintEvent*);

signals:

};

#endif // TANGGOD_H

(2)

#include "tanggod.h"

#include<QPainter>
#include<QPixmap>
#include<QSound>
#include<QPushButton>

TangGod::TangGod(QWidget *parent) : QMainWindow(parent)
{
    this->setFixedSize(300,200);
    QSound *sound=new QSound(":/calling.wav");
    sound->play();
    QPushButton *btn=new QPushButton(this);
    btn->setText("老师我错了,别念了");
    btn->resize(160,30);
    connect(btn,&QPushButton::clicked,this,[=](){
        sound->stop();
    });
}

void TangGod::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/sleep.jpg");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);
}

8、主界面
(1)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QLabel>
#include<QPushButton>
#include<QTimer>

#include"myclock.h"
#include"minclock.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void paintEvent(QPaintEvent*);
    void CalcPostion();
    void drawClockDial(QPainter *painter);
    float radious;
    int xSecond,ySecond,xHour,yHour,xMinute,yMinute;
    int xCenter,yCenter;
    int second,minute,hour;

signals:

private:
    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H

(2)

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"setclock.h"
#include"timeset.h"
#include"tanggod.h"

#include<QPushButton>
#include<QLabel>
#include<QPixmap>
#include<QPainter>
#include<qmath.h>

#define PI 3.14159265

int flag=0,flag1=0;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setFixedSize(676,412);
    this->setWindowTitle("Clock");
    radious=120;
    xCenter=150;
    yCenter=150;
    QTimer *timer=new QTimer(this);
    MyClock *clock=new MyClock(this);
    connect(ui->actionquite,&QAction::triggered,this,&QMainWindow::close);
    connect(ui->actiongod,&QAction::triggered,this,[=](){
        TangGod *god=new TangGod(this);
        god->show();
    });
    clock->setRing(0,1);
    timer->start(1000);
    connect(timer,&QTimer::timeout,this,[=](){
        clock->count();
        QVector<int> t=clock->get_time();
        hour=t[3];
        minute=t[4];
        second=t[5];
        CalcPostion();
        update();
        ui->label->setText(QString::number(t[0]));
        ui->label_2->setText(QString::number(t[1]));
        ui->label_3->setText(QString::number(t[2]));
        ui->label_4->setText(QString::number(t[3]));
        ui->label_5->setText(QString::number(t[4]));
        ui->label_6->setText(QString::number(t[5]));
    });
    QPushButton *btn=new QPushButton(this);
    btn->setText("关闭闹钟(已设时间)");
    btn->move(355,160);
    QPushButton *btn1=new QPushButton(this);
    btn1->setText("设置闹钟");
    btn1->move(465,160);
    QPushButton *btn2=new QPushButton(this);
    btn2->setText("设置时间");
    btn2->move(575,160);
    connect(btn,&QPushButton::clicked,this,[=](){
        clock->setRing(25,65);
    });
    connect(btn1,&QPushButton::clicked,this,[=](){
        SetClock *dialog=new SetClock(this);
        dialog->show();
        connect(dialog,&SetClock::setting,this,[=](){
            QVector<int> t=dialog->returnsetting();
            clock->setRing(t[0],t[1]);
            QTimer::singleShot(250,this,[=](){
                dialog->close();
                delete dialog;
            });
        });
    });
    connect(btn2,&QPushButton::clicked,this,[=](){
        TimeSet *timeset=new TimeSet(this);
        timeset->show();
        connect(timeset,&TimeSet::set,this,[=](){
            QVector<int> t1=timeset->Return();
            clock->reset(t1[0],t1[1],t1[2],t1[3],t1[4],t1[5]);
            QTimer::singleShot(250,this,[=](){
                timeset->close();
                delete timeset;
            });
        });
    });
    connect(ui->pushButton,&QPushButton::clicked,this,[=](){
        ui->pushButton->setEnabled(false);
        QTimer *timer1=new QTimer(this);
        MinClock *minclock=new MinClock(this);
        timer1->start(1);
        connect(timer1,&QTimer::timeout,this,[=](){
            minclock->count();
            QVector<int> t1=minclock->get_time();
            ui->label_7->setText(QString::number(t1[0]));
            ui->label_8->setText(QString::number(t1[1]));
        });
        connect(ui->pushButton_2,&QPushButton::clicked,this,[=](){
           if(flag%2==0)
           {
               timer1->stop();
               ui->pushButton_2->setText("继续");
           }
           else
           {
               timer1->start(1);
               ui->pushButton_2->setText("暂停");
           }
           flag++;
        });

    });
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPen pen;
    painter.drawEllipse(QPointF(150.0,150.0),radious,radious);
    painter.drawLine(xCenter,yCenter,xSecond,ySecond);
    pen.setWidth(2);
    painter.setPen(pen);
    painter.drawLine(xCenter,yCenter,xMinute,yMinute);
    pen.setWidth(4);
    painter.setPen(pen);
    painter.drawLine(xCenter,yCenter,xHour,yHour);
}

void MainWindow::CalcPostion()
{
    double minuteHandLen,secondHandLen,hourHandLen;
    secondHandLen=radious*0.75;
    minuteHandLen=radious*0.55;
    hourHandLen=radious*0.25;
    xSecond=xCenter+secondHandLen*cos(second*PI/30-PI/2);
    ySecond=yCenter+secondHandLen*sin(second*PI/30-PI/2);
    xMinute=xCenter+minuteHandLen*cos(minute*PI/30-PI/2);
    yMinute=yCenter+minuteHandLen*sin(minute*PI/30-PI/2);
    xHour=xCenter+hourHandLen*cos((hour+1.0*minute/60)*PI/6-PI/2);
    yHour=yCenter+hourHandLen*sin((hour+1.0*minute/60)*PI/6-PI/2);
}

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


9、主函数(QT的千篇一律,没什么好说的)

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

10、文件打包,发布
在界面中选择版本从debug改为realease版本,之后在文件夹内shift+鼠标右键
选中在此处打开Powershell
之后输入如下指令:
windeployqt.exe clock.exe(我所写的最后的可执行文件名为clock,根据各自的命名输入指令)
打包完成时的界面
11、完整发布:
使用HM NIS edit完成
(1)软件界面
在这里插入图片描述
(2)创建脚本
在这里插入图片描述
(3)
在这里插入图片描述

(4)

(5)选选择语言,简体中文为SimplChinese
在这里插入图片描述
(6)

注意授权文件一定要存在,否则无法生成安装脚本
如果授权文件不存在
则会出现如下错误
在这里插入图片描述

(7)
选择好对应文件
在这里插入图片描述
(8)
选下一步即可
在这里插入图片描述
(9)
依旧是下一步
在这里插入图片描述
(10)
在这里插入图片描述
(11)
按照如下方式设置
在这里插入图片描述
(12)
另存
在这里插入图片描述
(13)
编译
在这里插入图片描述
写在最后:
文章中所用到的资源百度云链接:
链接: https://pan.baidu.com/s/1AoKdgyKmct7D_Cw3bLBt_A 提取码: ai6u 复制这段内容后打开百度网盘手机App,操作更方便哦

05-23 16:00:49.311 25132-25512 A0c0d0/JSAPP I result {"code":200,"msg":"操作成功","data":[{"id":1,"name":"华为Mate 60 Pro","model":"ALN-AL80","imageUrl":"https://img.alicdn.com/imgextra/i3/2213047591560/O1CN01QNx6eB1NOWu3oeUfn_!!2213047591560.jpg_q50.jpg_.webp","shortDescription":"麒麟9000S 卫星通信","price":6999.00,"subsidizedPrice":6499.00,"sales":15000,"rating":4.90,"stock":500,"isAvailable":0,"brand":"华为"},{"id":2,"name":"华为P60 Art","model":"NOH-AN80","imageUrl":"https://img.alicdn.com/imgextra/i4/2609173245/O1CN011h2L1I1ZqGCdlsYlJ_!!2609173245.jpg_q50.jpg_.webp","shortDescription":"超聚光XMAGE影像","price":7988.00,"subsidizedPrice":7588.00,"sales":12000,"rating":4.80,"stock":300,"isAvailable":0,"brand":"华为"},{"id":3,"name":"华为nova 12","model":"BAC-AL00","imageUrl":"https://picasso.alicdn.com/imgextra/O1CNA1bnbda21Vuba4TjLYB_!!2838892713-0-psf.jpg_.webp","shortDescription":"前置双摄人像","price":2999.00,"subsidizedPrice":2699.00,"sales":50000,"rating":4.70,"stock":1000,"isAvailable":0,"brand":"华为"},{"id":4,"name":"荣耀Magic6 Pro","model":"PGT-AN30","imageUrl":"https://img.alicdn.com/imgextra/i2/263726286/O1CN01ko93gt1wJ2hQAORAB_!!4611686018427380942-0-item_pic.jpg_.webp","shortDescription":"骁龙8 Gen3 青海湖电池","price":5699.00,"subsidizedPrice":5399.00,"sales":25000,"rating":4.80,"stock":600,"isAvailable":0,"brand":"荣耀"},{"id":5,"name":"荣耀X50 GT","model":"ANY-AN00","imageUrl":"https://img.alicdn.com/imgextra/i3/3851598352/O1CN01UHPfyv2BZGwPnHUlx_!!0-item_pic.jpg_q50.jpg_.webp","shortDescription":"1.5K护眼曲屏","price":1999.00,"subsidizedPrice":1799.00,"sales":80000,"rating":4.60,"stock":1500,"isAvailable":0,"brand":"荣耀"},{"id":6,"name":"荣耀90 Pro","model":"REA-AN20","imageUrl":"https://img.alicdn.com/imgextra/i3/1114511827/O1CN01r3ngr41PMof7MhFhY_!!4611686018427386323-0-item_pic.jpg_q50.jpg_.webp","shortDescription":"2亿像素写真相机","price":3299.00,"subsidizedPrice":2999.00,"sales":40000,"rating":4.70,"stock":800,"isAvailable":0,"brand":"荣耀"},{"id":7,"name":"荣耀Play7T Pro","model":"CMA-AN40","imageUrl":"https://img.alicdn.com/imgextra/i1/1907069314/O1CN019jd3kt2IfrnZ6J0AH_!!1907069314.jpg_q50.jpg_.webp","shortDescription":"40W快充 OLED屏","price":1799.00,"subsidizedPrice":1599.00,"sales":120000,"rating":4.50,"stock":2000,"isAvailable":0,"brand":"荣耀"},{"id":8,"name":"华为畅享70 Pro","model":"CMA-AN70","imageUrl":"https://android-api.oss-cn-beijing.aliyuncs.com/logo.jpg","shortDescription":"7000mAh长续航","price":1599.00,"subsidizedPrice":1399.00,"sales":150000,"rating":4.40,"stock":3000,"isAvailable":0,"brand":"华为"},{"id":9,"name":"华为Mate X5","model":"TET-AN80","imageUrl":"https://android-api.oss-cn-beijing.aliyuncs.com/logo.jpg","shortDescription":"折叠屏 玄武钢化","price":12999.00,"subsidizedPrice":12499.00,"sales":5000,"rating":4.90,"stock":100,"isAvailable":0,"brand":"华为"},{"id":10,"name":"荣耀Magic Vs2","model":"CMA-AN80","imageUrl":"https://android-api.oss-cn-beijing.aliyuncs.com/logo.jpg","shortDescription":"轻薄折叠屏","price":8999.00,"subsidizedPrice":8499.00,"sales":10000,"rating":4.70,"stock":300,"isAvailable":0,"brand":"荣耀"},{"id":11,"name":"iPhone 15 Pro Max","model":"A3108","imageUrl":"https://android-api.oss-cn-beijing.aliyuncs.com/logo.jpg","shortDescription":"A17 Pro 钛金属","price":9999.00,"subsidizedPrice":null,"sales":80000,"rating":4.80,"stock":200,"isAvailable":0,"brand":"苹果"},{"id":12,"name":"iPhone 15","model":"A3092","imageUrl":"https://android-api.oss-cn-beijing.aliyuncs.com/logo.jpg","shortDescription":"A16芯片 灵动岛","price":5999.00,"subsidizedPrice":null,"sales":150000,"rating":4.80,"stock":5000,"isAvailable":0,"brand":"苹果"},{"id":13,"name":"iPhone 15 Plus","model":"A3096","imageUrl":"https://android-api.oss-cn-beijing.aliyuncs.com/logo.jpg","shortDescription":"6.7英寸大屏","price":6999.00,"subsidizedPrice":null,"sales":80000,"rating":4.70,"stock":3000,"isAvailable":0,"brand":"苹果"},{"id":14,"name":"iPhone SE 4","model":"A2785","imageUrl":"https://android-api.oss-cn-beijing.aliyun 05-23 16:00:49.311 25132-25512 A0c0d0/JSAPP I result [object Object] 05-23 16:00:49.359 25132-25512 C03f00/ArkCompiler E [ArkRuntime Log] TypeError: is not callable 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log]Lifetime: 0.000000s 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log]Js-Engine: ark 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log]page: pages/Index.js 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log]Error message: is not callable 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log]Stacktrace: 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at forEachUpdateFunction (/devcloud/slavespace/usr1/081f8aba80800f0f0fcec015bd66c7e0/harmony_code/codearts_workspace/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:4352:1) 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at anonymous (entry|entry|1.0.0|src/main/ets/pages/Index.ts:144:13) 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at updateFunc (/devcloud/slavespace/usr1/081f8aba80800f0f0fcec015bd66c7e0/harmony_code/codearts_workspace/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:6812:1) 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at UpdateElement (/devcloud/slavespace/usr1/081f8aba80800f0f0fcec015bd66c7e0/harmony_code/codearts_workspace/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:6514:1) 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at anonymous (/devcloud/slavespace/usr1/081f8aba80800f0f0fcec015bd66c7e0/harmony_code/codearts_workspace/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:6741:1) 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at updateDirtyElements (/devcloud/slavespace/usr1/081f8aba80800f0f0fcec015bd66c7e0/harmony_code/codearts_workspace/foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/engine/stateMgmt.js:6736:1) 05-23 16:00:49.361 25132-25512 C03900/Ace E [Engine Log] at rerender (entry|entry|1.0.0|src/main/ets/pages/Index.ts:152:9)
05-24
### 关于 HarmonyOS 或 ArkCompiler 中 'is not callable' 的 TypeError 问题 在 HarmonyOS 和 ArkCompiler 开发环境中遇到 `TypeError: is not callable` 错误通常表明尝试调用的对象并非函数或可调用对象。这种错误可能由多种原因引起,例如变量名冲突、未正确定义的回调函数或者对 `null` 值进行了不当操作。 #### 可能的原因分析 1. **变量覆盖了内置方法或函数** 如果开发者无意间将某些全局名称重新赋值为其他类型的值(如 `null`),可能会导致该错误。例如,在 JavaScript 环境下,如果重写了 `Array.prototype.map` 方法并将其设置为 `null`,那么后续对该方法的调用会失败[^4]。 2. **异步编程中的上下文丢失** 在使用箭头函数或其他形式绑定事件处理器时,如果没有正确处理 this 上下文,则可能导致原本期望作为函数执行的内容变成了 undefined 或 null。这种情况常见于 React 组件生命周期方法以及 Vue.js 自定义指令场景中[^5]。 3. **API 返回值异常** 当从外部服务获取数据时,若返回的结果不符合预期结构——比如应该是一个函数却实际接收到的是 null ——也会引发此类错误消息提示[^6]。 4. **Null 安全性问题** 类似于 MySQL 数据库设计里提到允许字段为空 (NULL)[^2], 在程序逻辑层面也需要考虑如何优雅地应对可能出现的 Null 情况。如果不小心试图直接调用了被赋予 Null 的属性或方法就会抛出类似的运行期错误。 #### 解决方案建议 针对以上几种可能性提供相应的解决方案如下: - #### 验证目标是否确实具备可调用特性 在每次准备调用前先验证其类型是否属于 Function 。可以利用 typeof 运算符来进行初步判断。 ```javascript const maybeFunction = someCondition ? () => {} : null; if(typeof maybeFunction === 'function') { maybeFunction(); } ``` - #### 使用 Optional Chaining 提高健壮性 ES2020 引入了一个新功能叫做 optional chaining (`?.`) ,它可以帮助我们更简洁安全地访问深层嵌套对象而不用担心中间环节存在 null/undefined 导致崩溃风险。 ```javascript let result = possiblyUndefinedObject ?. methodToCall(); // 不会报错即使object不存在 ``` - #### 明确区分命名空间内的同名实体 尽量避免自定义标识符与框架内部保留字发生碰撞;另外通过模块化组织代码也能有效减少这类隐患的发生几率。 - #### 调试工具辅助定位具体位置 利用断点调试技术逐步跟踪哪一部分代码最终触发了这个特定异常,并针对性修复源头问题所在之处。 ```javascript try{ potentiallyProblematicCode(); }catch(e){ console.error('Error occurred:', e); } ``` ### 总结 通过对 HarmonyOS / ArkCompiler 平台开发过程中常见的 “not callable” 类型错误现象剖析可知,这往往涉及到基本概念理解偏差或者是编码习惯上的疏漏所致。采取适当预防措施加上良好实践能够显著降低遭遇这些问题的概率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值