DialogSoftKeyboard.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. #include "DialogSoftKeyboard.h"
  2. #include "ui_DialogSoftKeyboard.h"
  3. #pragma execution_character_set("utf-8")
  4. #define TIMEMS QTime::currentTime().toString("HH:mm:ss zzz")
  5. DialogSoftKeyboard *DialogSoftKeyboard::self = NULL;
  6. DialogSoftKeyboard *DialogSoftKeyboard::Instance()
  7. {
  8. if (!self) {
  9. static QMutex mutex;
  10. QMutexLocker locker(&mutex);
  11. if (!self) {
  12. self = new DialogSoftKeyboard;
  13. }
  14. }
  15. return self;
  16. }
  17. DialogSoftKeyboard::DialogSoftKeyboard(QWidget *parent) : QWidget(parent), ui(new Ui::DialogSoftKeyboard)
  18. {
  19. ui->setupUi(this);
  20. this->initForm();
  21. QTimer::singleShot(100, this, SLOT(initData()));
  22. }
  23. DialogSoftKeyboard::~DialogSoftKeyboard()
  24. {
  25. delete ui;
  26. }
  27. void DialogSoftKeyboard::showEvent(QShowEvent *)
  28. {
  29. //主动刷新下防止部分嵌入式板子刷新不及时导致残影
  30. this->update();
  31. }
  32. bool DialogSoftKeyboard::eventFilter(QObject *watched, QEvent *event)
  33. {
  34. if (watched == this) {
  35. //处理自身拖动
  36. static QPoint mousePoint;
  37. static bool mousePressed = false;
  38. QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
  39. //按下的时候记住坐标,移动到鼠标松开的位置
  40. if (event->type() == QEvent::MouseButtonPress) {
  41. if (mouseEvent->button() == Qt::LeftButton) {
  42. mousePressed = true;
  43. mousePoint = mouseEvent->globalPos() - this->pos();
  44. return true;
  45. }
  46. } else if (event->type() == QEvent::MouseButtonRelease) {
  47. mousePressed = false;
  48. return true;
  49. } else if (event->type() == QEvent::MouseMove) {
  50. //bottom为固定的底部禁用拖动
  51. if (mousePressed && position != "bottom") {
  52. this->move(mouseEvent->globalPos() - mousePoint);
  53. this->update();
  54. return true;
  55. }
  56. }
  57. } else if (watched == ui->labMore) {
  58. //打开更多汉字候选面板
  59. if (event->type() == QEvent::MouseButtonPress) {
  60. //中文模式+非大写+有汉字 才能打开,否则打开没有意义是空的
  61. if (inputType == "chinese" && !upper && labCn.first()->isEnabled()) {
  62. setWidgetVisible(ui->widgetChinese->isVisible() ? 1 : 3);
  63. //重新设置图标
  64. QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
  65. ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
  66. return true;
  67. }
  68. }
  69. } else if (watched == ui->labType) {
  70. //中英模式切换,由于采用的标签所以在这里处理
  71. if (event->type() == QEvent::MouseButtonPress) {
  72. setInputType(inputType == "english" ? "chinese" : "english");
  73. }
  74. } else if (watched == ui->labType2) {
  75. //固定切换到英文模式
  76. if (event->type() == QEvent::MouseButtonPress) {
  77. setInputType("english");
  78. }
  79. } else if (watched == ui->widgetCn) {
  80. //没有汉字或者按下的地方没有汉字或者当前汉字标签个数过少都不用继续
  81. if (!labCn.first()->isEnabled() || lastText.isEmpty()) {
  82. return false;
  83. }
  84. //记住最后按下拖动的时间,过短则认为是滑动,启动滑动动画
  85. static bool pressed = false;
  86. static QPoint lastPos = QPoint();
  87. static QDateTime lastTime = QDateTime::currentDateTime();
  88. QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
  89. if (event->type() == QEvent::MouseButtonPress) {
  90. pressed = true;
  91. lastPos = mouseEvent->pos();
  92. animationCn->stop();
  93. lastTime = QDateTime::currentDateTime();
  94. } else if (event->type() == QEvent::MouseButtonRelease) {
  95. pressed = false;
  96. if (lastPos != mouseEvent->pos()) {
  97. //判断当前时间和鼠标按下事件比较,时间短则说明是滑动
  98. QDateTime now = QDateTime::currentDateTime();
  99. if (lastTime.msecsTo(now) < 600) {
  100. //可以改变下面的值来调整幅度
  101. bool moveleft = (mouseEvent->pos().x() - lastPos.x()) < 0;
  102. int offset = moveleft ? 350 : -350;
  103. int value = ui->scrollAreaCn->horizontalScrollBar()->value();
  104. animationCn->setStartValue(value);
  105. animationCn->setEndValue(value + offset);
  106. animationCn->start();
  107. }
  108. }
  109. } else if (event->type() == QEvent::MouseMove) {
  110. if (pressed && labCn.first()->isEnabled()) {
  111. //计算滑过的距离,可以改变下面的值来调整幅度
  112. bool moveleft = (mouseEvent->pos().x() - lastPos.x()) < 0;
  113. int offset = moveleft ? 5 : -5;
  114. int value = ui->scrollAreaCn->horizontalScrollBar()->value();
  115. ui->scrollAreaCn->horizontalScrollBar()->setValue(value + offset);
  116. return true;
  117. }
  118. }
  119. } else if (watched == ui->widgetMore) {
  120. //没有汉字或者按下的地方没有汉字或者当前汉字标签个数过少都不用继续
  121. if (!labMore.first()->isEnabled() || lastText.isEmpty()) {
  122. return false;
  123. }
  124. //记住最后按下拖动的时间,过短则认为是滑动,启动滑动动画
  125. static bool pressed = false;
  126. static QPoint lastPos = QPoint();
  127. static QDateTime lastTime = QDateTime::currentDateTime();
  128. QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
  129. if (event->type() == QEvent::MouseButtonPress) {
  130. pressed = true;
  131. lastPos = mouseEvent->pos();
  132. animationMore->stop();
  133. lastTime = QDateTime::currentDateTime();
  134. } else if (event->type() == QEvent::MouseButtonRelease) {
  135. pressed = false;
  136. if (lastPos != mouseEvent->pos()) {
  137. //判断当前时间和鼠标按下事件比较,时间短则说明是滑动
  138. QDateTime now = QDateTime::currentDateTime();
  139. if (lastTime.msecsTo(now) < 600) {
  140. //可以改变下面的值来调整幅度
  141. bool movebottom = (mouseEvent->pos().y() - lastPos.y()) < 0;
  142. int offset = movebottom ? 150 : -150;
  143. int value = ui->scrollAreaMore->verticalScrollBar()->value();
  144. animationMore->setStartValue(value);
  145. animationMore->setEndValue(value + offset);
  146. animationMore->start();
  147. }
  148. }
  149. } else if (event->type() == QEvent::MouseMove) {
  150. if (pressed && labMore.first()->isEnabled()) {
  151. //计算滑过的距离,可以改变下面的值来调整幅度
  152. bool movebottom = (mouseEvent->pos().y() - lastPos.y()) < 0;
  153. int offset = movebottom ? 5 : -5;
  154. int value = ui->scrollAreaMore->verticalScrollBar()->value();
  155. ui->scrollAreaMore->verticalScrollBar()->setValue(value + offset);
  156. return true;
  157. }
  158. }
  159. } else if (watched->inherits("QLabel")) {
  160. //单击的是汉字标签
  161. QLabel *lab = (QLabel *)watched;
  162. if (!upper && inputType == "chinese") {
  163. if (lab->property("labCn").toBool()) {
  164. //记住最后按下的滚动条位置,如果滚动条一直没有变化则认为单击了标签
  165. static int lastPosition = 0;
  166. if (event->type() == QEvent::MouseButtonPress) {
  167. lastPosition = ui->scrollAreaCn->horizontalScrollBar()->value();
  168. lastText = lab->text();
  169. } else if (event->type() == QEvent::MouseButtonRelease) {
  170. if (lastPosition == ui->scrollAreaCn->horizontalScrollBar()->value() && !lastText.isEmpty()) {
  171. insertValue(lab->text());
  172. pinyinHelper.clearChinese();
  173. }
  174. }
  175. } else if (lab->property("labMore").toBool()) {
  176. //记住最后按下的滚动条位置,如果滚动条一直没有变化则认为单击了标签
  177. static int lastPosition = 0;
  178. if (event->type() == QEvent::MouseButtonPress) {
  179. lastPosition = ui->scrollAreaMore->verticalScrollBar()->value();
  180. lastText = lab->text();
  181. } else if (event->type() == QEvent::MouseButtonRelease) {
  182. if (lastPosition == ui->scrollAreaMore->verticalScrollBar()->value() && !lastText.isEmpty()) {
  183. insertValue(lab->text());
  184. pinyinHelper.clearChinese();
  185. }
  186. }
  187. }
  188. }
  189. } else {
  190. if (event->type() == QEvent::MouseButtonPress) {
  191. //处理鼠标按下,如果是浏览器控件则弹出输入法
  192. if (currentWidget != 0) {
  193. if (!isVisible()) {
  194. if (!currentWidget->inherits("QWebView") && !currentWidget->inherits("QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget")) {
  195. showPanel();
  196. }
  197. }
  198. } else {
  199. if (isVisible()) {
  200. hidePanel();
  201. }
  202. }
  203. } else if (event->type() == QEvent::KeyPress) {
  204. //这里是实体键盘同步的代码 识别不同的按键映射到不同的按钮
  205. if (useHardKeyBoard) {
  206. bool doKey = true;
  207. QString labText = ui->labPinYin->text();
  208. QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
  209. if (keyEvent->key() == Qt::Key_Space) {
  210. ui->btnSpace->click();
  211. } else if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
  212. doKey = false;
  213. if (!labText.isEmpty()) {
  214. insertValue(labText);
  215. pinyinHelper.clearChinese();
  216. ui->labPinYin->clear();
  217. } else {
  218. //如果不需要回车隐藏则注释下面这句
  219. hidePanel();
  220. }
  221. } else if (keyEvent->key() == Qt::Key_Shift) {
  222. //shift按键用来切换中英
  223. sendEvent(0, "");
  224. } else if (keyEvent->key() == Qt::Key_Alt) {
  225. //alt按键用来切换数字
  226. ui->btnChar->isVisible() ? ui->btnChar->click() : ui->btnChar2->click();
  227. } else if (keyEvent->key() == Qt::Key_Escape) {
  228. //关闭窗体
  229. ui->btnClose->click();
  230. } else if (keyEvent->key() == Qt::Key_CapsLock) {
  231. //大小写切换
  232. ui->btnUpper->click();
  233. } else if (keyEvent->key() == Qt::Key_Backspace) {
  234. doKey = false;
  235. //中文模式下如果有输入字母则先挨个删除
  236. if (inputType == "chinese") {
  237. int len = labText.length();
  238. if (len > 0) {
  239. ui->labPinYin->setText(labText.left(len - 1));
  240. pinyinHelper.selectChinese(ui->labPinYin->text());
  241. doKey = true;
  242. }
  243. }
  244. } else if (keyEvent->text() == "+" || keyEvent->text() == "=") {
  245. //汉字翻页 下一页
  246. if (!labText.isEmpty()) {
  247. pinyinHelper.showNext();
  248. } else {
  249. doKey = false;
  250. }
  251. } else if (keyEvent->text() == "-" || keyEvent->text() == "_") {
  252. //汉字翻页 上一页
  253. if (!labText.isEmpty()) {
  254. pinyinHelper.showPrevious();
  255. } else {
  256. doKey = false;
  257. }
  258. } else {
  259. doKey = false;
  260. if (!isVisible()) {
  261. return false;
  262. }
  263. QString key = keyEvent->text();
  264. if (inputType == "english") {
  265. //key = upper ? key.toUpper() : key.toLower();
  266. }
  267. //限定单个字母而不是输入的汉字
  268. if (inputType == "chinese" && key.length() == 1) {
  269. QList<QPushButton *> btns = ui->widgetLetter->findChildren<QPushButton *>();
  270. foreach (QPushButton *btn, btns) {
  271. QString text = btn->text();
  272. if (!text.isEmpty() && text == key) {
  273. btn->click();
  274. doKey = true;
  275. break;
  276. }
  277. }
  278. //数字键选择汉字
  279. if (useHardKeyBoard) {
  280. int value = key.toInt();
  281. if (value >= 1 && value <= maxCountCh) {
  282. QString text = labCh.at(value - 1)->text();
  283. if (!text.isEmpty()) {
  284. lastText = text;
  285. insertValue(text);
  286. pinyinHelper.clearChinese();
  287. ui->labPinYin->clear();
  288. doKey = true;
  289. }
  290. }
  291. }
  292. }
  293. }
  294. if (doKey) {
  295. return true;
  296. }
  297. }
  298. } else if (event->type() == QEvent::RequestSoftwareInputPanel) {
  299. showPanel();
  300. } else if (event->type() == QEvent::CloseSoftwareInputPanel) {
  301. hidePanel();
  302. }
  303. }
  304. return QWidget::eventFilter(watched, event);
  305. }
  306. void DialogSoftKeyboard::initForm()
  307. {
  308. #if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
  309. setWindowFlags(Qt::Tool | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
  310. #else
  311. setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
  312. #endif
  313. upper = false;
  314. charType = 0;
  315. onlyControl = false;
  316. onlyTouch = false;
  317. #ifdef __arm__
  318. autoHide = false;
  319. #else
  320. autoHide = true;
  321. #endif
  322. currentWidget = 0;
  323. dbPath = qApp->applicationDirPath();
  324. //初始化按钮和属性
  325. initBtn();
  326. //初始化显示汉字的标签
  327. initLab();
  328. //初始化动画属性用来滑动选择
  329. initAnimation();
  330. //初始化数字键盘
  331. initInputNumber();
  332. //初始化友元类
  333. initClass();
  334. //输入法面板的字体名称和按钮字体大小即汉字区域字体大小
  335. setFontInfo(this->font().family(), 11, 10);
  336. //面板固定大小
  337. setFixedSize2(650, 280);
  338. //图标固定大小
  339. setIconSize(20, 20);
  340. //按钮之间的间隔
  341. setSpacing(6);
  342. //顶部汉字区域高度
  343. setTopHeight(40);
  344. //输入法面板的显示位置 control--显示在对应输入框的正下方 bottom--填充显示在底部 center--窗体居中显示
  345. setPosition("control");
  346. //输入法模式 english--英文模式 chinese--中文模式 char--字符模式
  347. setInputType("english");
  348. //输入法面板的样式 black--黑色 blue--淡蓝色 brown--灰黑色 gray--灰色 silvery--银色
  349. setStyleName("black");
  350. //是否启用硬键盘
  351. setUseHardKeyBoard(false);
  352. }
  353. void DialogSoftKeyboard::initBtn()
  354. {
  355. //绑定按钮到事件
  356. QList<QPushButton *> btns;
  357. btns << ui->widgetLetter->findChildren<QPushButton *>();
  358. btns << ui->widgetChar->findChildren<QPushButton *>();
  359. foreach (QPushButton *btn, btns) {
  360. btn->setProperty("btnInput", true);
  361. connect(btn, SIGNAL(clicked()), this, SLOT(btnClicked()));
  362. }
  363. //设置字母属性
  364. btns.clear();
  365. btns << ui->widgetLetter1->findChildren<QPushButton *>();
  366. btns << ui->widgetLetter2->findChildren<QPushButton *>();
  367. foreach (QPushButton *btn, btns) {
  368. btn->setProperty("btnLetter", true);
  369. }
  370. //设置所有按钮输入法不可用+长按自动重复事件
  371. btns.clear();
  372. btns << this->findChildren<QPushButton *>();
  373. initBtn(btns);
  374. }
  375. void DialogSoftKeyboard::initBtn(QList<QPushButton *> btns)
  376. {
  377. foreach (QPushButton *btn, btns) {
  378. btn->setFocusPolicy(Qt::NoFocus);
  379. btn->setProperty("noinput", true);
  380. //如果不需要自动重复可以设置 setAutoRepeat(false)
  381. btn->setAutoRepeat(true);
  382. btn->setAutoRepeatDelay(500);
  383. }
  384. }
  385. void DialogSoftKeyboard::initLab()
  386. {
  387. //实例化硬键盘使用的汉字标签
  388. maxCountCh = 6;
  389. for (int i = 0; i < maxCountCh; i++) {
  390. QLabel *lab = new QLabel;
  391. lab->setProperty("labCh", true);
  392. ui->layoutCh->addWidget(lab);
  393. labCh << lab;
  394. }
  395. //实例化横向的汉字标签,添加到顶部滚动区域中
  396. maxCountCn = 256;
  397. for (int i = 0; i < maxCountCn; i++) {
  398. QLabel *lab = new QLabel;
  399. lab->setProperty("labCn", true);
  400. lab->setAlignment(Qt::AlignCenter);
  401. ui->layoutCn->addWidget(lab);
  402. labCn << lab;
  403. }
  404. //实例化更多的汉字标签,添加到更多滚动区域中
  405. int row = 0;
  406. int column = 0;
  407. //列数,可自行调整
  408. columnCount = 8;
  409. for (int i = 0; i < maxCountCn; i++) {
  410. QLabel *lab = new QLabel;
  411. lab->setProperty("labMore", true);
  412. lab->setAlignment(Qt::AlignCenter);
  413. ui->layoutMore->addWidget(lab, row, column);
  414. labMore << lab;
  415. column++;
  416. if (column >= columnCount) {
  417. row++;
  418. column = 0;
  419. }
  420. }
  421. //末尾加个弹簧
  422. //QSpacerItem *hSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
  423. //ui->layoutCn->addItem(hSpacer);
  424. QSpacerItem *vSpacer = new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding);
  425. ui->layoutMore->addItem(vSpacer, row, 0);
  426. //lab1 lab2 空的占位置的标签 setEnabled(false)以后不会应用样式表
  427. ui->lab1->setEnabled(false);
  428. ui->lab2->setEnabled(false);
  429. ui->labPinYin->setEnabled(false);
  430. ui->labMore->setEnabled(false);
  431. }
  432. void DialogSoftKeyboard::initAnimation()
  433. {
  434. //定义动画产生平滑数值
  435. animationCn = new QPropertyAnimation(ui->scrollAreaCn->horizontalScrollBar(), "value");
  436. animationCn->setEasingCurve(QEasingCurve::OutCirc);
  437. animationCn->setDuration(500);
  438. animationMore = new QPropertyAnimation(ui->scrollAreaMore->verticalScrollBar(), "value");
  439. animationMore->setEasingCurve(QEasingCurve::OutCirc);
  440. animationMore->setDuration(500);
  441. }
  442. void DialogSoftKeyboard::initInputNumber()
  443. {
  444. QList<QPushButton *> btns;
  445. btns << ui->btnDelete << ui->btnSpace << ui->btnEnter << ui->btnClose;
  446. //char=共用一个面板切换到数字页面 number=独立的小数字面板
  447. numberType = "number";
  448. //数字键盘面板
  449. inputNumber = new DialogSoftKeyboardNumber;
  450. this->layout()->addWidget(inputNumber);
  451. inputNumber->setInput(this);
  452. inputNumber->setBtns(btns);
  453. inputNumber->initClicked();
  454. inputNumber->hide();
  455. }
  456. void DialogSoftKeyboard::initClass()
  457. {
  458. QList<QPushButton *> btns = ui->widgetChar->findChildren<QPushButton *>();
  459. pinyinChar.setInput(this);
  460. pinyinChar.setBtns(btns);
  461. pinyinHelper.setInput(this);
  462. pinyinHelper.setLabs(labCh, labCn, labMore);
  463. }
  464. void DialogSoftKeyboard::initData()
  465. {
  466. if (onlyControl) {
  467. this->installEventFilter(this);
  468. ui->labType->installEventFilter(this);
  469. ui->labType2->installEventFilter(this);
  470. ui->labMore->installEventFilter(this);
  471. ui->widgetCn->installEventFilter(this);
  472. ui->widgetMore->installEventFilter(this);
  473. foreach (QLabel *lab, labCh) {
  474. lab->installEventFilter(this);
  475. }
  476. foreach (QLabel *lab, labCn) {
  477. lab->installEventFilter(this);
  478. }
  479. foreach (QLabel *lab, labMore) {
  480. lab->installEventFilter(this);
  481. }
  482. } else {
  483. //绑定全局改变焦点信号槽
  484. connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)), this, SLOT(focusChanged(QWidget *, QWidget *)));
  485. qApp->installEventFilter(this);
  486. }
  487. }
  488. void DialogSoftKeyboard::btnClicked()
  489. {
  490. clearScroll();
  491. QPushButton *btn = (QPushButton *)sender();
  492. QString objectName = btn->objectName();
  493. QString btnText = btn->text();
  494. QString labText = ui->labPinYin->text();
  495. //下面采用startsWith的判断是因为有多个按钮功能一样比如 btnDelete btnDelete2
  496. if (objectName == "btnUpper") {
  497. upper = !upper;
  498. setUpper(upper);
  499. pinyinHelper.clearChinese();
  500. ui->labPinYin->clear();
  501. } else if (objectName == "btnChar") {
  502. setInputType("char");
  503. //立即切换到初始的字符界面 注释掉的话则保留以前的最后字符状态
  504. pinyinChar.setCharType(0, ui->btnChar2);
  505. } else if (objectName == "btnChar2") {
  506. if (charType == 0) {
  507. charType = 1;
  508. } else if (charType == 1) {
  509. charType = 2;
  510. } else {
  511. charType = 0;
  512. }
  513. pinyinChar.setCharType(charType, ui->btnChar2);
  514. } else if (objectName.startsWith("btnDelete")) {
  515. //如果当前是中文模式,则删除对应拼音,删除完拼音之后再删除对应文本输入框的内容
  516. int len = labText.length();
  517. if (inputType == "chinese" && len > 0) {
  518. ui->labPinYin->setText(labText.left(len - 1));
  519. pinyinHelper.selectChinese(ui->labPinYin->text());
  520. } else {
  521. deleteValue();
  522. }
  523. } else if (objectName.startsWith("btnSpace")) {
  524. //如果中文模式而且有待输入字母,判断是否有中文则插入第一个中文否则插入字母
  525. if (inputType == "chinese" && !labText.isEmpty()) {
  526. QString text = useHardKeyBoard ? labCh.first()->text() : labCn.first()->text();
  527. text.isEmpty() ? insertValue(labText) : insertValue(text);
  528. pinyinHelper.clearChinese();
  529. } else {
  530. insertValue(" ");
  531. }
  532. } else if (objectName.startsWith("btnEnter")) {
  533. //如果中文模式而且有待输入字母则立即插入字母
  534. if (inputType == "chinese" && !labText.isEmpty()) {
  535. insertValue(labText);
  536. pinyinHelper.clearChinese();
  537. }
  538. if (currentWidget != 0 && !onlyControl) {
  539. //如果手动指定了属性隐藏,或者不是多行文本则自动隐藏
  540. //如果单行文本不希望回车隐藏则设置属性 ui->txt->setProperty("enterhide", false);
  541. QVariant enterHide = currentWidget->property("enterhide");
  542. if (enterHide.isValid()) {
  543. if (enterHide.toBool()) {
  544. hidePanel();
  545. }
  546. } else {
  547. if (!currentWidget->inherits("QTextEdit") && !currentWidget->inherits("QPlainTextEdit") && !currentWidget->inherits("QTextBrowser")) {
  548. hidePanel();
  549. }
  550. }
  551. //插入回车符
  552. sendEvent(3, "");
  553. } else {
  554. insertValue("\n");
  555. }
  556. } else if (objectName.startsWith("btnClose")) {
  557. hidePanel();
  558. } else {
  559. //如果是&按钮,因为对应&被过滤,所以真实的text为去除前面一个&字符
  560. if (btnText == "&&") {
  561. btnText = "&";
  562. }
  563. //当前不是中文模式,则单击按钮对应text为传递参数,大写优先
  564. //中文模式+非大写+并且按下的是字母按钮 则设置字母并查询汉字
  565. if (inputType != "chinese" || upper) {
  566. insertValue(btnText);
  567. } else {
  568. if (btn->property("btnLetter").toBool()) {
  569. ui->labPinYin->setText(labText + btnText);
  570. pinyinHelper.selectChinese(ui->labPinYin->text());
  571. }
  572. }
  573. }
  574. }
  575. //用来全局焦点切换的时候 处理输入法显示隐藏及模式切换和位置处理
  576. void DialogSoftKeyboard::focusChanged(QWidget *oldWidget, QWidget *nowWidget)
  577. {
  578. Q_UNUSED(oldWidget);
  579. //qDebug() << "oldWidget:" << oldWidget << "nowWidget:" << nowWidget;
  580. this->currentWidget = nowWidget;
  581. if (nowWidget != 0 && !this->isAncestorOf(nowWidget)) {
  582. //如果对应属性noinput为真或者只读则不显示
  583. if (nowWidget->property("noinput").toBool() || nowWidget->property("readOnly").toBool()) {
  584. currentWidget = 0;
  585. QTimer::singleShot(0, this, SLOT(hidePanel()));
  586. return;
  587. }
  588. if (nowWidget->inherits("QWidget")) {
  589. //合法的输入控件,如果后面还发现其他控件也需要输入可以自行增加
  590. QStringList classNames;
  591. classNames << "QLineEdit" << "QTextEdit" << "QPlainTextEdit" << "QAbstractSpinBox" << "QComboBox";
  592. classNames << "QQuickWidget" << "QWebView" << "QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget";
  593. //查找当前焦点控件是否属于合法输入的控件
  594. bool exist = false;
  595. foreach (QString className, classNames) {
  596. if (nowWidget->inherits(className.toLatin1().constData())) {
  597. //如果当前是下拉框则判断下拉框可编辑属性是否为真
  598. //下面这个判断很巧妙哦,即能识别除了下拉框以外的控件还能识别可编辑的下拉框
  599. if (className != "QComboBox" || nowWidget->property("editable").toBool()) {
  600. exist = true;
  601. break;
  602. }
  603. }
  604. }
  605. //需要输入法的地方弹出输入法否则隐藏
  606. if (exist) {
  607. showPanel();
  608. pinyinHelper.movePosition();
  609. } else {
  610. currentWidget = 0;
  611. hidePanel();
  612. }
  613. }
  614. }
  615. }
  616. void DialogSoftKeyboard::insertValue(const QString &value)
  617. {
  618. //先过滤前面的标号
  619. QString text = value;
  620. if (text != " ") {
  621. text = value.split(" ").last();
  622. }
  623. //仅仅当做独立的面板使用,发送选择的内容即可
  624. if (onlyControl) {
  625. clearValue();
  626. emit receiveValue(text);
  627. return;
  628. }
  629. if (currentWidget == 0) {
  630. return;
  631. }
  632. //保存当前选中汉字到文件,作为优先显示的汉字
  633. //如果某个控件开启了永远大写则强制转换为大写
  634. bool upper = currentWidget->property("upper").toBool();
  635. text = upper ? text.toUpper() : text;
  636. if (!text.isEmpty()) {
  637. sendEvent(4, text);
  638. }
  639. clearValue();
  640. }
  641. void DialogSoftKeyboard::clearValue()
  642. {
  643. //清空拼音标签,同时滚动条恢复
  644. clearScroll();
  645. ui->labPinYin->clear();
  646. //如果是汉字面板显示则隐藏汉字面板并显示字母面板
  647. if (ui->widgetChinese->isVisible()) {
  648. setWidgetVisible(1);
  649. //重新设置图标
  650. QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
  651. ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
  652. }
  653. }
  654. void DialogSoftKeyboard::deleteValue()
  655. {
  656. if (currentWidget == 0) {
  657. return;
  658. }
  659. sendEvent(2, "");
  660. }
  661. void DialogSoftKeyboard::clearScroll()
  662. {
  663. ui->scrollAreaCn->horizontalScrollBar()->setValue(0);
  664. ui->scrollAreaMore->verticalScrollBar()->setValue(0);
  665. }
  666. void DialogSoftKeyboard::showPanel()
  667. {
  668. if (!isEnabled() || currentWidget == 0) {
  669. return;
  670. }
  671. //根据不同的标识符切换到不同的面板
  672. QString flag = currentWidget->property("flag").toString();
  673. if (currentWidget->inherits("QAbstractSpinBox")) {
  674. flag = "number";
  675. }
  676. //如果是父控件中的子控件需要过滤,比如表格控件自动出现的文本框,需要判断是否设置了number
  677. if (flag != "number") {
  678. QWidget *father = (QWidget *)currentWidget->parent();
  679. if (father != 0) {
  680. father = (QWidget *)father->parent();
  681. if (father != 0) {
  682. flag = father->property("flag").toString();
  683. }
  684. }
  685. }
  686. if (flag == "number") {
  687. if (inputType != numberType) {
  688. this->setVisible(false);
  689. setInputType(numberType);
  690. }
  691. pinyinChar.setCharType(0, ui->btnChar2);
  692. } else {
  693. if (inputType == numberType) {
  694. this->setVisible(false);
  695. setInputType("english");
  696. }
  697. }
  698. this->setVisible(true);
  699. }
  700. void DialogSoftKeyboard::hidePanel()
  701. {
  702. //如果已经是隐藏状态则不需要处理
  703. if (!isVisible()) {
  704. return;
  705. }
  706. //解决当更多汉字面板打开时候突然隐藏不会自动关闭的BUG
  707. if (ui->widgetMore->isVisible()) {
  708. sendEvent(1, "");
  709. }
  710. pinyinHelper.clearChinese();
  711. ui->labPinYin->clear();
  712. this->setVisible(false);
  713. }
  714. void DialogSoftKeyboard::setWidgetVisible(int indexVisible)
  715. {
  716. ui->widgetLetter->setVisible(indexVisible == 1);
  717. ui->widgetChar->setVisible(indexVisible == 2);
  718. ui->widgetChinese->setVisible(indexVisible == 3);
  719. ui->widgetTop->setVisible(indexVisible != 4);
  720. inputNumber->setVisible(indexVisible == 4);
  721. //切换小数字键盘和全键盘
  722. if (indexVisible == 4) {
  723. this->setFixedSize(fixedWidth / 2.2, fixedHeight / 1.2);
  724. } else {
  725. this->setFixedSize(fixedWidth / 1, fixedHeight / 1);
  726. }
  727. }
  728. void DialogSoftKeyboard::sendEvent(quint8 type, const QString &text)
  729. {
  730. if (type == 0) {
  731. //切换中英模式
  732. QMouseEvent mousePress(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
  733. QApplication::sendEvent(ui->labType->isVisible() ? ui->labType : ui->labType2, &mousePress);
  734. } else if (type == 1) {
  735. //隐藏汉字候选面板
  736. QMouseEvent mousePress(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
  737. QApplication::sendEvent(ui->labMore, &mousePress);
  738. } else if (type == 2) {
  739. //删除
  740. QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier, QString());
  741. QApplication::sendEvent(currentWidget, &keyPress);
  742. } else if (type == 3) {
  743. //插入回车符
  744. QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, QString("\n"));
  745. QApplication::sendEvent(currentWidget, &keyPress);
  746. } else if (type == 4) {
  747. //插入字符
  748. QKeyEvent keyPress(QEvent::KeyPress, 0, Qt::NoModifier, QString(text));
  749. QApplication::sendEvent(currentWidget, &keyPress);
  750. }
  751. }
  752. void DialogSoftKeyboard::setFontInfo(const QString &fontName, int btnFontSize, int labFontSize)
  753. {
  754. QFont btnFont(fontName, btnFontSize);
  755. QFont labFont(fontName, labFontSize);
  756. QList<QPushButton *> btns = this->findChildren<QPushButton *>();
  757. foreach (QPushButton *btn, btns) {
  758. btn->setFont(btnFont);
  759. }
  760. ui->labType->setFont(btnFont);
  761. ui->labType2->setFont(btnFont);
  762. ui->labPinYin->setFont(labFont);
  763. foreach (QLabel *lab, labCn) {
  764. lab->setFont(labFont);
  765. }
  766. foreach (QLabel *lab, labCh) {
  767. lab->setFont(labFont);
  768. }
  769. foreach (QLabel *lab, labMore) {
  770. lab->setFont(labFont);
  771. lab->setFixedHeight(labFontSize + 30);
  772. }
  773. }
  774. void DialogSoftKeyboard::setFixedSize2(int fixedWidth, int fixedHeight)
  775. {
  776. this->fixedWidth = fixedWidth;
  777. this->fixedHeight = fixedHeight;
  778. this->setFixedSize(fixedWidth, fixedHeight);
  779. }
  780. void DialogSoftKeyboard::setIconSize(int iconWidth, int iconHeight)
  781. {
  782. //图标尺寸大小
  783. QSize sizeUpper(iconWidth + 3, iconHeight);
  784. QSize sizeDelete(iconWidth + 10, iconHeight);
  785. QSize sizeEnter(iconWidth + 3, iconHeight);
  786. QSize sizeClose(iconWidth + 5, iconHeight + 3);
  787. ui->btnUpper->setIconSize(sizeUpper);
  788. ui->btnDelete->setIconSize(sizeDelete);
  789. ui->btnDelete2->setIconSize(sizeDelete);
  790. ui->btnEnter->setIconSize(sizeEnter);
  791. ui->btnEnter2->setIconSize(sizeEnter);
  792. ui->btnClose->setIconSize(sizeClose);
  793. ui->btnClose2->setIconSize(sizeClose);
  794. }
  795. void DialogSoftKeyboard::setSpacing(int spacing)
  796. {
  797. ui->widgetLetter1->layout()->setSpacing(spacing);
  798. ui->widgetLetter2->layout()->setSpacing(spacing);
  799. ui->widgetLetter3->layout()->setSpacing(spacing);
  800. ui->widgetChar1->layout()->setSpacing(spacing);
  801. ui->widgetChar2->layout()->setSpacing(spacing);
  802. ui->widgetChar3->layout()->setSpacing(spacing);
  803. inputNumber->setSpacing(spacing);
  804. }
  805. void DialogSoftKeyboard::setTopHeight(int topHeight)
  806. {
  807. ui->widgetTop->setFixedHeight(topHeight);
  808. }
  809. void DialogSoftKeyboard::setOnlyControl(bool onlyControl)
  810. {
  811. this->onlyControl = onlyControl;
  812. }
  813. void DialogSoftKeyboard::setOnlyTouch(bool onlyTouch)
  814. {
  815. this->onlyTouch = onlyTouch;
  816. this->setStyleName(styleName);
  817. }
  818. void DialogSoftKeyboard::setUseHardKeyBoard(bool useHardKeyBoard)
  819. {
  820. this->useHardKeyBoard = useHardKeyBoard;
  821. ui->widgetCh->setVisible(useHardKeyBoard);
  822. ui->scrollAreaCn->setVisible(!useHardKeyBoard);
  823. ui->labMore->setVisible(!useHardKeyBoard);
  824. }
  825. void DialogSoftKeyboard::setColumnCount(int columnCount)
  826. {
  827. this->columnCount = columnCount;
  828. }
  829. void DialogSoftKeyboard::setMaxCount(int maxCountCn)
  830. {
  831. this->maxCountCn = maxCountCn;
  832. }
  833. void DialogSoftKeyboard::setNumberType(const QString &numberType)
  834. {
  835. this->numberType = numberType;
  836. }
  837. void DialogSoftKeyboard::setDbPath(const QString &dbPath)
  838. {
  839. this->dbPath = dbPath;
  840. }
  841. void DialogSoftKeyboard::setPosition(const QString &position)
  842. {
  843. this->position = position;
  844. }
  845. void DialogSoftKeyboard::setInputType(const QString &inputType)
  846. {
  847. //每次模式更改都把原有的汉字清空
  848. clearScroll();
  849. pinyinHelper.clearChinese();
  850. ui->labPinYin->clear();
  851. this->inputType = inputType;
  852. if (inputType == "number") {
  853. setWidgetVisible(4);
  854. } else if (inputType == "char") {
  855. setWidgetVisible(2);
  856. } else if (inputType == "english") {
  857. setWidgetVisible(1);
  858. //通过html设置文字产生不同汉字不同的颜色
  859. ui->labType->setText(QString("<font color='%1'>中/</font><font color='%2' size='4'>英</font>").arg(mainTextColor).arg(btnHoveColor));
  860. } else if (inputType == "chinese") {
  861. setWidgetVisible(1);
  862. //通过html设置文字产生不同汉字不同的颜色
  863. ui->labType->setText(QString("<font color='%2' size='4'>中</font><font color='%1'>/英</font>").arg(mainTextColor).arg(btnHoveColor));
  864. }
  865. //重新设置图标
  866. QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
  867. ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
  868. }
  869. void DialogSoftKeyboard::setUpper(bool isUpper)
  870. {
  871. QList<QPushButton *> btns = ui->widgetLetter->findChildren<QPushButton *>();
  872. foreach (QPushButton *btn, btns) {
  873. QString text = isUpper ? btn->text().toUpper() : btn->text().toLower();
  874. btn->setText(text);
  875. }
  876. //改变图标
  877. QString strUpper = upper ? "upper" : "lower";
  878. ui->btnUpper->setIcon(QIcon(QString(":/image/btn_%1_%2.png").arg(strUpper).arg(iconType)));
  879. }
  880. void DialogSoftKeyboard::setStyleName(const QString &styleName)
  881. {
  882. this->styleName = styleName;
  883. this->iconType = "white";
  884. if (styleName == "black") {
  885. setColor("#191919", "#F3F3F3", "#313131", "#24B1DF", "#F3F3F3", "#F95717", "#F3F3F3");
  886. } else if (styleName == "blue") {
  887. setColor("#377FC9", "#F3F3F3", "#4189D3", "#386487", "#F3F3F3", "#386487", "#F3F3F3");
  888. } else if (styleName == "gray") {
  889. setColor("#989898", "#FFFFFF", "#A2A2A2", "#333333", "#F3F3F3", "#2E2E2E", "#F3F3F3");
  890. } else if (styleName == "brown") {
  891. setColor("#667481", "#F3F3F3", "#566373", "#4189D3", "#F3F3F3", "#4189D3", "#F3F3F3");
  892. } else if (styleName == "silvery") {
  893. setColor("#868690", "#000002", "#C3C2C7", "#F0F0F0", "#000002", "#F0F0F0", "#000002");
  894. this->iconType = "black";
  895. }
  896. QString strMore = ui->widgetMore->isVisible() ? "up" : "down";
  897. QString strUpper = upper ? "upper" : "lower";
  898. ui->labMore->setPixmap(QString(":/image/btn_%1_%2.png").arg(strMore).arg(iconType));
  899. ui->btnUpper->setIcon(QIcon(QString(":/image/btn_%1_%2.png").arg(strUpper).arg(iconType)));
  900. QString strDelete = QString(":/image/btn_%1_%2.png").arg("delete").arg(iconType);
  901. QString strEnter = QString(":/image/btn_%1_%2.png").arg("enter").arg(iconType);
  902. QString strClose = QString(":/image/btn_%1_%2.png").arg("close").arg(iconType);
  903. ui->btnDelete->setIcon(QIcon(strDelete));
  904. ui->btnDelete2->setIcon(QIcon(strDelete));
  905. ui->btnEnter->setIcon(QIcon(strEnter));
  906. ui->btnEnter2->setIcon(QIcon(strEnter));
  907. ui->btnClose->setIcon(QIcon(strClose));
  908. ui->btnClose2->setIcon(QIcon(strClose));
  909. }
  910. void DialogSoftKeyboard::setColor(const QString &mainBackgroundColor, const QString &mainTextColor,
  911. const QString &btnBackgroundColor, const QString &btnHoveColor,
  912. const QString &btnHoveTextColor, const QString &labHoveColor,
  913. const QString &labHoveTextColor)
  914. {
  915. this->mainTextColor = mainTextColor;
  916. this->btnHoveColor = btnHoveColor;
  917. QStringList list;
  918. list << QString("QScrollArea{border:none;background:rgba(255,255,255,0);}QWidget#widgetCn,QWidget#widgetMore{background:rgba(0,0,0,0);}");
  919. list << QString("QWidget#widgetTop,QWidget#widgetLetter,QWidget#widgetChar{background-color:%1;}").arg(mainBackgroundColor);
  920. list << QString("QWidget#widgetChinese,QWidget#widgetNumber{background-color:%1;}").arg(mainBackgroundColor);
  921. list << QString("#labType,#labType2,QPushButton{border-width:0px;border-radius:3px;color:%1;}").arg(mainTextColor);
  922. list << QString("#labType,#labType2,QPushButton{padding:0px;background-color:%1;}").arg(btnBackgroundColor);
  923. //触摸屏上不需要设置hover
  924. if (onlyTouch) {
  925. list << QString("QPushButton:pressed{background-color:%1;color:%2;}").arg(btnHoveColor).arg(btnHoveTextColor);
  926. } else {
  927. list << QString("QPushButton:pressed,QPushButton:hover{background-color:%1;color:%2;}").arg(btnHoveColor).arg(btnHoveTextColor);
  928. }
  929. list << QString("QLabel{padding:0px 5px 0px 5px;border-width:0px;border-radius:3px;color:%1;background:none;}").arg(mainTextColor);
  930. list << QString("QLabel:pressed,QLabel:hover{background-color:%1;color:%2;}").arg(labHoveColor).arg(labHoveTextColor);
  931. list << QString("QLabel:disabled{background:none;}");
  932. QString qss = list.join("");
  933. this->setStyleSheet(qss);
  934. ui->labType->setText(QString("<font color='%1'>中/</font><font color='%2' size='4'>英</font>").arg(mainTextColor).arg(btnHoveColor));
  935. ui->labType2->setText(QString("<font color='%2' size='4'>中</font><font color='%1'>/英</font>").arg(mainTextColor).arg(btnHoveColor));
  936. qApp->processEvents();
  937. }