QT-全键盘支持中英文

  • 前言
  • 一、效果演示
  • 二、环境配置
  • 三、关键程序
    • 1.SoftKeyBoard.h
    • 2.SoftKeyBoard.cpp
  • 四、程序链接

前言

自定义全键盘功能,支持中英文切换,使用的开发环境为qt+vs的方式,独立封装成类,如果开发环境不同,拷贝类再导入自己的项目再次编译即可。


一、效果演示

二、环境配置

1、vs配置,见下图:

2、修改样式


3、qss样式代码

QWidget#SoftKeyBoard
{background-color:#5b9bd5;border-radius:20px
}.QPushButton,
.QToolButton
{border-style:solid;border:1.5px solid #215171;color:#386487;padding:0px; border-radius:7px;font: normal bold 20px;background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6);
}.QPushButton:hover,
.QToolButton:hover
{background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #F2F9FF,stop:1 #DAEFFF);
}.QPushButton:pressed,
.QToolButton:pressed
{ background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:1,stop:0 #DEF0FE,stop:1 #C0DEF6);
}.QToolButton:checked
{ background:qlineargradient(spread:pad,x1:0,y1:0,x2:0,y2:100,stop:0 #DEF00f,stop:10 #C0DEF6);
}

三、关键程序

1.SoftKeyBoard.h


#ifndef SOFTKEYBOARD_H
#define SOFTKEYBOARD_H#include <QtGui>
#include <QtCore>
#include <QPoint>
#include <QPushButton>
#include <map>
#include <vector>
#include "ui_SoftKeyBoard.h"
#include <QDialog>
class SoftKeyBoard : public QDialog
{Q_OBJECTpublic:SoftKeyBoard(QWidget * parent = 0);QString getValue();void setValue(QString text);
public slots:void OnfocusIn();
signals:void characterGenerated(int character);protected:bool event(QEvent *e);void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void paintEvent(QPaintEvent *);private slots:void saveFocusWidget(QWidget *oldFocus, QWidget *newFocus);void buttonClicked(QWidget *w);void on_btn_language__clicked();void on_btn_caplock__clicked();void on_btn_next__clicked();void on_btn_last__clicked();void on_btn_shift__clicked();void on_btn_backspace__clicked();void on_btn_close__clicked();void on_btn_enter__clicked();private://初始化字库bool InitChinese();bool GetBtnText(QWidget * widget,QString & text,int start,int count);void ShowChinese(QString str,int page,int pos);private:Ui::SoftKeyBoard ui;QWidget * m_lastFocusedWidget_;QSignalMapper m_signalMapper_;QPushButton * m_btns_[65];QPoint m_ptPress_;      //用于拖动窗口bool m_bLeftBtnPress_;bool m_bIsChinese_;     //语言,false:英文,true:中文bool m_bIsUppercase_;bool m_bShiftPressed_;std::map<QString,std::vector<QString> >m_map_;   //汉字库 key:拼音 value:字QString m_strPingying_;  //拼音int m_currentPos_;       //选中的文字位置int m_currentPage_;      //当前页
};
#endif

2.SoftKeyBoard.cpp

data = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())#include <QStyleOption>
#include <QPainter>
#include <QLineEdit>
#include <QFile>
#include <QDateTime>
#include <QMessageBox>
#include <QDesktopWidget>
#include "SoftKeyBoard.h"
#define KeyboardWidth 1280  //键盘宽度
#define KeyboardHeightEnglish 450   //英文键盘高度
#define KeyboardHeightChinese 550   //中文键盘高度
#define btnWidth 70         //按钮宽度
#define btnHeight 70        //按钮高度
#define FatherWidth 1280    //主窗口宽度
#define FatherHeight 800    //主窗口高度
SoftKeyBoard::SoftKeyBoard(QWidget * parent): QDialog(parent),m_lastFocusedWidget_(0)
{ui.setupUi(this);this->setObjectName("SoftKeyBoard");this->resize(KeyboardWidth,KeyboardHeightEnglish);this->setWindowFlags(Qt::Tool| Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);hide();m_bIsChinese_ = true;m_bIsUppercase_ = false;m_bShiftPressed_ = false;m_currentPos_ = 0;m_currentPage_ = 0;on_btn_language__clicked();m_btns_[0] = ui.char_a_;m_btns_[1] = ui.char_b_;m_btns_[2] = ui.char_c_;m_btns_[3] = ui.char_d_;m_btns_[4] = ui.char_e_;m_btns_[5] = ui.char_f_;m_btns_[6] = ui.char_g_;m_btns_[7] = ui.char_h_;m_btns_[8] = ui.char_i_;m_btns_[9] = ui.char_j_;m_btns_[10] = ui.char_k_;m_btns_[11] = ui.char_l_;m_btns_[12] = ui.char_m_;m_btns_[13] = ui.char_n_;m_btns_[14] = ui.char_o_;m_btns_[15] = ui.char_p_;m_btns_[16] = ui.char_q_;m_btns_[17] = ui.char_r_;m_btns_[18] = ui.char_s_;m_btns_[19] = ui.char_t_;m_btns_[20] = ui.char_u_;m_btns_[21] = ui.char_v_;m_btns_[22] = ui.char_w_;m_btns_[23] = ui.char_x_;m_btns_[24] = ui.char_y_;m_btns_[25] = ui.char_z_;            //字母m_btns_[26] = ui.num_0_;m_btns_[27] = ui.num_1_;m_btns_[28] = ui.num_2_;m_btns_[29] = ui.num_3_;m_btns_[30] = ui.num_4_;m_btns_[31] = ui.num_5_;m_btns_[32] = ui.num_6_;m_btns_[33] = ui.num_8_;m_btns_[34] = ui.num_9_;             //数字m_btns_[35] = ui.btn_left_bracket_;  //左括号m_btns_[36] = ui.btn_right_bracket_; //右括号m_btns_[37] = ui.btn_slash_;         //斜杠m_btns_[38] = ui.btn_quota_;         //引号m_btns_[39] = ui.btn_semicolon_;     //分号m_btns_[40] = ui.btn_backslash_;     //反斜杠m_btns_[41] = ui.btn_comma_;         //逗号m_btns_[42] = ui.btn_dot_;           //点m_btns_[43] = ui.btn_add_;           //加m_btns_[44] = ui.btn_dec_;           //减m_btns_[45] = ui.num_7_;             //7特殊处理,因为包含&m_btns_[46] = ui.word_0_;m_btns_[47] = ui.word_1_;m_btns_[48] = ui.word_2_;m_btns_[49] = ui.word_3_;m_btns_[50] = ui.word_4_;m_btns_[51] = ui.word_5_;m_btns_[52] = ui.word_6_;m_btns_[53] = ui.word_7_;m_btns_[54] = ui.word_8_;m_btns_[55] = ui.word_9_;m_btns_[56] = ui.word_10_;m_btns_[57] = ui.word_11_;           //汉字m_btns_[58] = ui.btn_up_;m_btns_[59] = ui.btn_down_;m_btns_[60] = ui.btn_left_;m_btns_[61] = ui.btn_right_;         //上下左右m_btns_[62] = ui.btn_enter_;         //回车m_btns_[63] = ui.btn_backspace_;     //退格m_btns_[64] = ui.btn_space_;         //空格for(int i = 0;i < 65;++i){m_signalMapper_.setMapping(m_btns_[i],m_btns_[i]);m_btns_[i]->setFixedHeight(btnHeight);//m_btns_[i]->setFixedWidth(btnWidth);connect(m_btns_[i],SIGNAL(clicked()),&m_signalMapper_,SLOT(map()));}connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)),this, SLOT(saveFocusWidget(QWidget*,QWidget*)));connect(&m_signalMapper_, SIGNAL(mapped(QWidget*)),this, SLOT(buttonClicked(QWidget*)));connect(ui.wordShow,SIGNAL(focusIn()),this,SLOT(OnfocusIn()));   //设置光标进入 否则进入页面无法wordShow 无法获取光标ui.btn_close_->setFixedHeight(btnHeight);ui.btn_caplock_->setFixedHeight(btnHeight);ui.btn_language_->setFixedHeight(btnHeight);ui.btn_shift_->setFixedHeight(btnHeight);InitChinese();
}bool SoftKeyBoard::event(QEvent *e)
{QKeyEvent *keyEvent = static_cast<QKeyEvent*>(e);if (keyEvent && keyEvent->key() == Qt::Key_Escape){this->close();return true;}switch (e->type()){case QEvent::WindowActivate:if (m_lastFocusedWidget_)m_lastFocusedWidget_->activateWindow();break;case QEvent::Show:{QDesktopWidget* desktop = QApplication::desktop(); // =qApp->desktop();也可以int centerHeight = (desktop->height() - FatherHeight)/2 + FatherHeight;this->move((desktop->width() - this->width())/2,m_bIsChinese_ ? centerHeight-KeyboardHeightChinese : centerHeight-KeyboardHeightEnglish);break;}default:break;}return QWidget::event(e);
}void SoftKeyBoard::saveFocusWidget(QWidget * /*oldFocus*/, QWidget *newFocus)
{if (newFocus != 0 && !this->isAncestorOf(newFocus))m_lastFocusedWidget_ = newFocus;
}void SoftKeyBoard::buttonClicked(QWidget *w)
{if(!w)return;QString text;QString word = "";  //中文int key = -1;if(!m_bIsChinese_)                //英文{if(GetBtnText(w,text,0,26) && text.size() > 0)//英文 字母{key = m_bShiftPressed_ ? (text[0] >= 'A' && text[0] <= 'Z' ? text[0].toLower().unicode() : text[0].toUpper().unicode()) : text[0].unicode();//按下shifttext = text[0];}else if(m_bShiftPressed_ && GetBtnText(w,text,26,20) && text.size() > 0){key = text[0].unicode();text = text[0];}else if(!m_bShiftPressed_ && GetBtnText(w,text,26,19) && text.size() > 0){text = text[2];key = text[2].unicode();}else if(!m_bShiftPressed_ && GetBtnText(w,text,45,1) && text.size() > 0){text = text[3];key = text[3].unicode();}else if(w == m_btns_[58])key = Qt::Key_Up;else if(w == m_btns_[59])key = Qt::Key_Down;else if(w == m_btns_[60])key = Qt::Key_Left;else if(w == m_btns_[61])key = Qt::Key_Right;else if(w == m_btns_[62])key = Qt::Key_Enter;else if(w == m_btns_[63])key = Qt::Key_Backspace;else if(w == m_btns_[64]){text = " ";key = Qt::Key_Space;}//        qDebug()<<__PRETTY_FUNCTION__<<text<<key;//        emit characterGenerated(key);}else                              //中文{if(GetBtnText(w,text,0,26) && text.size() > 0)//字母ShowChinese(m_strPingying_ + text[0].toLower(),0,0);else if(GetBtnText(w,text,46,12) && text.size() > 0) //选中文字{key = text[0].unicode();ShowChinese("",0,0);word = text[0];}else if(m_bShiftPressed_ && GetBtnText(w,text,26,20) && text.size() > 0){key = text[0].unicode();}else if(!m_bShiftPressed_ && GetBtnText(w,text,26,19) && text.size() > 0){key = text[2].unicode();}else if(!m_bShiftPressed_ && GetBtnText(w,text,45,1) && text.size() > 0){key = text[3].unicode();}if(!m_strPingying_.isEmpty())   //有拼音就操作拼音{if(w == m_btns_[58])        //上一页on_btn_last__clicked();else if(w == m_btns_[59])   //下一页on_btn_next__clicked();else if(w == m_btns_[60] && m_currentPos_ > 0)   //上一个,选中ShowChinese(m_strPingying_,m_currentPage_,m_currentPos_ - 1);else if(w == m_btns_[61] && m_currentPos_ < 11)   //下一个,选中ShowChinese(m_strPingying_,m_currentPage_,m_currentPos_ + 1);else if((w == m_btns_[62] || w == m_btns_[64]) && m_currentPos_ >= 0 && m_currentPos_ <= 11)   //enter、空格输入{text = m_btns_[m_currentPos_ + 46]->text();if(text.size() > 0)key = text[0].unicode();ShowChinese("",0,0);}else if(w == m_btns_[63])   //删除一个拼音ShowChinese(m_strPingying_.left(m_strPingying_.size() - 1),0,0);}else                            //没有拼音就直接输入{if(w == m_btns_[58])key = Qt::Key_Up;else if(w == m_btns_[59])key = Qt::Key_Down;else if(w == m_btns_[60])key = Qt::Key_Left;else if(w == m_btns_[61])key = Qt::Key_Right;else if(w == m_btns_[62])key = Qt::Key_Enter;else if(w == m_btns_[63])key = Qt::Key_Backspace;else if(w == m_btns_[64]){text = " ";key = Qt::Key_Space;}}}QString lineText = ui.wordShow->text();int selectStart = ui.wordShow->selectionStart();QString selectText = ui.wordShow->selectedText();const QRegExpValidator* reaExp = static_cast<const QRegExpValidator *>(ui.wordShow->validator());if(m_bIsChinese_)text = word;if(selectStart >=0){lineText = lineText.replace(selectStart,selectText.size(),text);if(reaExp != NULL){//qDebug() << "lineText" << lineText << reaExp->regExp().indexIn(lineText);if(reaExp->regExp().indexIn(lineText) == 0){ui.wordShow->setText(lineText);}else if(lineText == "-");elsereturn;}ui.wordShow->setText(lineText);}else{int cursorPos = ui.wordShow->cursorPosition();lineText = lineText.insert(cursorPos,text);if(reaExp != NULL){//qDebug() << "lineText" << lineText << reaExp->regExp().indexIn(lineText);if(reaExp->regExp().indexIn(lineText) == 0)ui.wordShow->setText(lineText);else if(lineText == "-");   //运行输入负数elsereturn;}ui.wordShow->setText(lineText);ui.wordShow->setCursorPosition(cursorPos+1);}
}void SoftKeyBoard::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){m_ptPress_ = event->globalPos();        //记录按下位置m_bLeftBtnPress_ = true;}event->ignore();
}void SoftKeyBoard::mouseMoveEvent(QMouseEvent *event)
{if(m_bLeftBtnPress_)                        //移动窗口{move(pos() + event->globalPos() - m_ptPress_);  //移动窗口m_ptPress_ = event->globalPos();}event->ignore();
}void SoftKeyBoard::mouseReleaseEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton)m_bLeftBtnPress_ = false;event->ignore();
}void SoftKeyBoard::paintEvent(QPaintEvent *)
{QPainter p(this);p.fillRect(rect(), QColor(153, 153, 153,127));
}void SoftKeyBoard::on_btn_language__clicked()
{static bool bFirstInit = true;if(m_bIsUppercase_)on_btn_caplock__clicked();m_bIsChinese_ = !m_bIsChinese_;if( bFirstInit && m_bIsChinese_)qDebug()<<"on_btn_language__clicked"<<"open chinese.txt failed.";ui.btn_language_->setText(m_bIsChinese_ ? u8"中文/英文" : u8"英文/中文");m_bIsChinese_  ? ui.widget_chinese_->show() : ui.widget_chinese_->hide();//ui.widget_keyboard_->move(0,m_bIsChinese_ ? 100 : 2);resize(KeyboardWidth,m_bIsChinese_ ? KeyboardHeightChinese : KeyboardHeightEnglish);QDesktopWidget* desktop = QApplication::desktop(); // =qApp->desktop();也可以int centerHeight = (desktop->height() - FatherHeight)/2 + FatherHeight;this->move((desktop->width() - this->width())/2,m_bIsChinese_ ? centerHeight-KeyboardHeightChinese : centerHeight-KeyboardHeightEnglish);
}void SoftKeyBoard::on_btn_caplock__clicked()
{m_bIsUppercase_ = !m_bIsUppercase_;//ui.btn_caplock_->setStyleSheet(QString("#btn_caplock_{color: rgb(255,255,255);background-color:") + (m_bIsUppercase_ ? "rgb(127,122,117)" : "rgb(67,63,59)") + ";border-radius: 7px;}#btn_caplock_:pressed{background-color: rgb(33,30,27);}");for(int i = 0;i < 26;++i)m_btns_[i]->setText(QString(m_bIsUppercase_ ? 'A' + i : 'a' + i ));
}void SoftKeyBoard::on_btn_next__clicked()
{ShowChinese(m_strPingying_,m_currentPage_ + 1,0);
}void SoftKeyBoard::on_btn_last__clicked()
{ShowChinese(m_strPingying_,m_currentPage_ - 1,0);
}void SoftKeyBoard::on_btn_shift__clicked()
{m_bShiftPressed_ = !m_bShiftPressed_;qDebug() << "on_btn_shift__clicked" << m_bShiftPressed_;
}bool SoftKeyBoard::InitChinese()
{QFile file(":/FontLibrary.txt");int i = 0;if(file.open(QIODevice::ReadOnly)){QString str;QString key;while (true){str = file.readLine();if(str.size() < 4)break;key = str.mid(2,str.size() - 3).replace("\r","");m_map_[key].push_back(str.left(1));++i;}file.close();return true;}return false;
}bool SoftKeyBoard::GetBtnText(QWidget *widget, QString &text, int start, int count)
{text = "";for(int i = start;i < start + count;++i){if(widget == m_btns_[i]){text = m_btns_[i]->text();return true;}}return true;
}void SoftKeyBoard::ShowChinese(QString str,int page,int pos)
{qDebug()<<"ShowChinese"<<str<<page<<pos<<"current"<<m_strPingying_<<m_currentPage_<<m_currentPos_;if(page < 0)page = 0;if(pos < 0 || pos > 11)pos = 0;std::map<QString,std::vector<QString> >::iterator it = m_map_.find(str);ui.lab_pinying_->setText(str);if(it != m_map_.end() && it->second.size() < page * 12)//没有下一页return;for(int i = 0;i < 12;++i){qDebug() << (it != m_map_.end()) << m_map_.size();m_btns_[46 + i]->setText(it != m_map_.end() && it->second.size() > page * 12 + i ? it->second[page * 12 + i] : "");//qDebug()<<"on_btn_language__clicked"<<m_btns_[46 + i]->text()<<i;}if(m_btns_[46 + pos]->text().isEmpty())pos = m_currentPos_;m_strPingying_ = str;m_currentPage_ = page;m_currentPos_ = pos;
}void SoftKeyBoard::on_btn_backspace__clicked()
{QString lineText = ui.wordShow->text();int cursorPos = ui.wordShow->cursorPosition();if(cursorPos>0)lineText.remove(cursorPos-1,1);ui.wordShow->setText(lineText);if(cursorPos-2 >= 0)ui.wordShow->setCursorPosition(cursorPos-2);
}void SoftKeyBoard::on_btn_close__clicked()
{qDebug() << "Cancel" ;done(QMessageBox::Cancel);close();
}void SoftKeyBoard::on_btn_enter__clicked()
{qDebug() << "Ok" ;done(QMessageBox::Ok);close();
}QString SoftKeyBoard::getValue()
{return ui.wordShow->text();
}void SoftKeyBoard::setValue(QString text)
{ui.wordShow->setText(text);ui.wordShow->setFocus();
}void SoftKeyBoard::OnfocusIn()
{qDebug() << "OnfocusIn";// MyCommon::WaitForAMoment(100);ui.wordShow->setCursorPosition(ui.wordShow->text().size());ui.wordShow->activateWindow();ui.wordShow->setFocus();// this->activateWindow();
}

四、程序链接

https://download.csdn.net/download/u013083044/87517353?spm=1001.2014.3001.5503

QT-全键盘支持中英文相关推荐

  1. QT全平台支持——开始学习

    跨平台特性将来方便移植到嵌入式, 学过c过度到c++比较容易, Qt是诺基亚开发的一个跨平台的C++图形用户界面应用程序框架.它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能.Qt是完全面 ...

  2. Qt虚拟键盘更新,支持手写识别功能

    Qt官方博客发布消息称,新版本的Qt虚拟键盘支持手书写识别功能(HWR).性能改进.Nuance T9书写一体化,并支持繁体中文! Qt虚拟键盘日前发布了新功能和版本控制方案的更新.作为最近的许可变更 ...

  3. java 校验姓名只能包含中英文_java代码验证用户名,支持中英文(包括全角字符)、数字、下划线和减号 (全角及汉字算两位),长度为4-20位,中文按二位计数...

    package com.sangedabuliu.www; import java.util.regex.Matcher; import java.util.regex.Pattern; public ...

  4. Qt软键盘使用和修改软键盘参数 支持中文

    Qt软键盘使用和修改软键盘参数 概述 效果预览 一.修改pro文件,添加软键盘模块 二.修改main.cpp文件,加载软键盘 三.代码没有写错但是软键盘显示不出来问题 四. 修改软件盘的尺寸 1.下载 ...

  5. linux电脑支持5g吗,支持5G的全键盘掌上电脑设备Astro Slide

    在触屏智能手机大为流行的二十一世纪,市场偶尔会时不时吹来一阵"复古"风气,2018 年由 Planet Computers 推出的 Gemini PDA 就是一个例子.这款搭载 5 ...

  6. vue 管理后台 使用虚拟键盘组件 支持中英文切换

    前言:在大型触屏设备(如双屏设备)中,就没有键盘去操作,而且在触屏input或者textarea的输入时候就无法去输入值,没办法触发输入框enter事件,所以就需要去建立一个虚拟键盘去操作 就想着找一 ...

  7. ubuntu下qt模拟键盘按键按下_基于QT的跨平台虚拟键盘设计与实现

    摘  要: 针对QT在Windows.Linux.以及嵌入式Linux-arm等不同平台下没有开源.高效的虚拟键盘(包含中文输入法),以及QT版本升级造成代码不兼容等问题,设计并实现了一个跨平台的虚拟 ...

  8. 五笔字型键盘字根图_手机输入法的派别之争:九宫格和全键盘,哪个更科学?...

    本       文       约 3376 字 阅       读       需       要 10 min 有人的地方,就有江湖.而在手机输入法的江湖里,也分为两个派别.一个是九宫格输入法,另 ...

  9. Qt虚拟键盘相关内容

    收集一些关于Qt虚拟键盘的内容,仅供参考.   商业版什么时候就有? Qt虚拟键盘(1.0版本)最早出现在Qt Enterprise Embedded 5.3.0中(2014-05-22)   开源版 ...

最新文章

  1. PCL调错:(3)error C2589“(“:“::“右边的非法标记
  2. python 导入包的路径_关于Python包导入的知识点你知道吗?
  3. chrome更新flash player失败
  4. IOS基础之毛毛虫案例-重力
  5. Linux 命令之 let -- bash 中用于计算的工具,用于执行一个或多个表达式
  6. 深度学习修炼(六)——神经网络分类问题
  7. 工业机械类企业官网织梦模板源码
  8. android编辑配置文件,如何在android studio中修改配置文件
  9. SQL SERVER 2005无法远程连接
  10. AMD,CMD,UMD,CommonJS
  11. java内网环境使用代理访问外网api
  12. t分布 u分布 卡方分布_t分布曲线和正太分布,和z分布,和卡方分布,和方差分析的f分布曲线有什么区别?...
  13. 数据库系统的结构/三级模式结构
  14. C#开发串口调试助手的详细教程
  15. php 方差函数,PHP应用:PHP基于方差和标准差计算学生成绩的稳定性示例
  16. 【最新Unity3D—Particle System粒子系统】最新Unity2017.2018.2019.2020均适用且超详细
  17. slot 游戏 demo
  18. (转载)基于sklearn的iris数据集及简介
  19. ios获取系统自带的文字蓝色色值
  20. vue antd table customRender 自定义标签

热门文章

  1. 基于51单片机的计算器设计
  2. 一位中学教师plus 大咖的分享
  3. 广告系统简易流程与架构
  4. 列车厢调度(C语言)
  5. Failed to load ‘Assets/Plugins/******.dll‘ with error ‘找不到指定的模块。
  6. 使用 frp配置内网映射
  7. breed web控制台——新路由3 newifi-d2 刷breed web控制台教程
  8. lvgl8.2 img 图片显示
  9. 图片五子棋PHP接口,原生JS+Canvas实现五子棋游戏实例
  10. php考试系统 公众号,基于微信公众平台的在线考试系统.pdf