Qt編寫可換膚的中文雙拼漢字輸入法


新版輸入法V2018+V2019請移步這里:https://www.cnblogs.com/feiyangqingyun/p/9690175.html  和 https://www.cnblogs.com/feiyangqingyun/p/10433663.html

時間過得真快,不知不覺已到2015年,農歷春節一眨眼就過去了,端正狀態收拾心情整裝待發出發。

曾經有段時間,我有一個很執着的夢想,我要導演出一部空前絕后的巨幕。不過現實無情地碾碎我的夢想,也同時將我推進了人生的低谷。

我開始思考,思想很多很多我以前總是回避的問題,在一次次思考中,我能感覺到我正在向一個陌生的地方走去,前途是光是暗也無法推測,我發現我在賭,賭注是一輩子的懊悔或是郁郁終生。

但當我看到陽光彌漫在我身邊時,才發現以前的我是那么幼稚,我始終在找借口或不是借口的借口推卸掉與生俱來的責任,在光怪陸離的現實中找個僻靜的地方希望過雲淡風輕的日子。我錯了,我擁有足夠的能力卻不敢恣意妄為,我擁有驚人的天賦卻畏懼這只是南柯一夢,或者這本來就是夢,醒來時卻是了無痕跡和無休止的眷戀。

從前有個同學問我是不是幻想過一些特別的經歷會降臨到自己身上,當時我只笑了笑,卻不知道該怎么回答。

我想我是矛盾的,我認為我的存在與否關系到世間的萬事萬物,但我找不到足夠的證據來證明我具有救世主的身份。因此我一度懷疑過我是不是生不逢時,或是天妒英才。

我在一次次輪回中等待着一個機會,也許是亂世,也許是太平,我沒有所謂的一技之長,只有飛揚跋扈的驕傲和潮洗潮卷的胸懷。只有一笑置之的孤傲和白雲蒼狗的方式。我想我不該妄自菲薄,甚至這是理所當然的不加半點修飾的順其自然。

我很喜歡這樣一句話:如果我將庸碌一生的話,地球將停止轉動,地球停止轉動了嗎?沒有,那我將不會庸碌一生。

在特定的時間,特定的環境,特定的地點,有個特定的人將主宰萬事萬物!天生我才必有用!經典的心照不宣,只可惜他的傲慢卻沒有足夠的能力做基墊。

我想我是對的,注定的便是永遠無法改變的,過去的只是匆匆一瞥,將來的只是白駒過隙,一次次的輪回換來的是麻木的循規蹈矩,所以世界需要那么一個人----改變。

分割線-----------------------------------------------------------------------

高中和大學很喜歡文學,特別是在大學期間,在任何填寫個人資料興趣愛好一欄中填寫的都是文學和編程,這就好比我的左手和右手,缺一不可。

好了言歸正傳,來說說Qt編寫可換膚的中文拼音輸入法。在ARM上,如果采用QT開發應用程序,基本上都會遇到一個問題,需要在應用程序中輸入漢字,這個就比較麻煩,就算接了實體鍵盤,也只能輸入字母和數字的,對中文無可奈何,為此就需要用QT自己來實現一個。

百度一搜索,有很多前輩都寫過類似的輸入法,但是基本上都是用QWSInputMethod相關的機制,我覺得這樣有點不妥,絕大部分界面丑陋,只支持單個漢字輸入,而且基本上不支持實體鍵盤和虛擬鍵盤同步輸入。 

運行截圖:

 

 

 

 

 

 

 

 

 

 

特點:

1:各Qt版本(Qt4.6-Qt5.4)、各操作系統(windows、linux、嵌入式linux-ARM)全編譯運行通過,界面一致。

2:支持小寫、大寫、中文三種模式輸入,自由切換。

3:支持單拼雙拼詞組輸入,網上大部分只支持單個漢字輸入。

4:智能分頁算法,可任意翻頁查看漢字詞組。

5:除了支持鼠標單擊軟鍵盤輸入外,還支持實體鍵盤同步輸入,代碼中有映射處理,對應實體鍵盤的按鍵會反應到軟鍵盤處理。

6:七套精美皮膚樣式選擇,鼠標右鍵任意換膚。

7:代碼優化到極致,包括注釋和所有完善性代碼處理總共不到500行。

8:除了可以單擊軟鍵盤和實體鍵盤上的數字來選擇對應的漢字外,還支持鼠標單擊漢字顯示處來選擇漢字。

9:無邊框窗體,可拖動移動。

10:sqlite數據庫存儲漢字字庫,可自由添加自定義的詞組。

11:參考實體鍵盤布局,更逼真。

12:界面布局、字庫算法、界面切換100%首創處理,與任何網上的Qt輸入法處理方式和布局截然不同。

核心方法:

1:獲取當前焦點控件。

Qt封裝了一個focusChanged信號,提供兩個參數QWidget *oldWidget, QWidget *nowWidget,這樣就給輸入法的處理帶來了極大的方便。

// 綁定全局改變焦點信號槽
connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),
             this, SLOT(focusChanged(QWidget *, QWidget *)));
void frmInput::focusChanged(QWidget *oldWidget, QWidget *nowWidget)
{
     // qDebug() << "oldWidget:" << oldWidget << "nowWidget:" << nowWidget;
     if (nowWidget !=  0 && ! this->isAncestorOf(nowWidget)) {
         if (nowWidget->inherits( " QLineEdit ")) {
            currentLineEdit = (QLineEdit *)nowWidget;
             this->setVisible( true);
        }  else {
            currentLineEdit =  0;
             this->setVisible( false);
             // 需要將輸入法切換到最初的原始狀態--小寫
            currentType= " min ";
            changeType(currentType);
        }
    }
}

2:小寫、大寫、中文三種模式切換。

void frmInput::changeType(QString type)
{
     if (type ==  " max ") {
        changeLetter( true);
        ui->btnType->setText( " 大寫 ");
        ui->widgetTop->setVisible( false);
         this->setGeometry( this->geometry().x(),  this->geometry().y(),  550160);
    }  else  if (type ==  " min ") {
        changeLetter( false);
        ui->btnType->setText( " 小寫 ");
        ui->widgetTop->setVisible( false);
         this->setGeometry( this->geometry().x(),  this->geometry().y(),  550160);
    }  else {
        changeLetter( false);
        ui->btnType->setText( " 中文 ");
        ui->widgetTop->setVisible( true);
         this->setGeometry( this->geometry().x(),  this->geometry().y(),  550215);
         // 每次切換到中文顯示,都要執行清空之前中文模式下的信息
        clearChinese();
        ui->labPY->setText( "");
    }
}
void frmInput::changeLetter( bool isUpper)
{
    QList<QPushButton *> btn =  this->findChildren<QPushButton *>();
     foreach (QPushButton * b, btn) {
         if (b->property( " btnLetter ").toBool()) {
             if (isUpper) {
                b->setText(b->text().toUpper());
            }  else {
                b->setText(b->text().toLower());
            }
        }
    }
}

3:軟鍵盤按鈕單擊事件處理。

void frmInput::btn_clicked()
{
    QPushButton *btn = (QPushButton *)sender();
    QString objectName = btn->objectName();
     if (objectName ==  " btnType ") {
         if (currentType ==  " min ") {
            currentType =  " max ";
        }  else  if (currentType ==  " max ") {
            currentType =  " chinese ";
        }  else  if (currentType ==  " chinese ") {
            currentType =  " min ";
        }
        changeType(currentType);
    }  else  if (objectName ==  " btnDelete " || objectName ==  " btnDeleteMin ") {
         // 如果當前是中文模式,則刪除對應拼音,刪除完拼音之后再刪除對應文本輸入框的內容
         if (currentType ==  " chinese ") {
            QString txt = ui->labPY->text();
             int len = txt.length();
             if (len >  0) {
                ui->labPY->setText(txt.left(len -  1));
                selectChinese();
            }  else {
                 if (currentLineEdit !=  0) {
                    currentLineEdit->backspace();
                }
            }
        }  else {
             if (currentLineEdit !=  0) {
                currentLineEdit->backspace();
            }
        }
    }  else  if (objectName ==  " btnPre ") {
         if (currentPY_index >=  20) {
             if (currentPY_index %  10 ==  0) {
                currentPY_index -=  20;
            }  else {
                currentPY_index = currentPY_count - (currentPY_count %  10) -  10;
            }
        }  else {
            currentPY_index =  0;
        }
        showChinese();
    }  else  if (objectName ==  " btnNext ") {
         if (currentPY_index < currentPY_count -  1) {
            showChinese();
        }
    }  else {
        QString value = btn->text();
         // 如果是&按鈕,因為對應&被過濾,所以真實的text為去除前面一個&字符
         if (objectName ==  " btnOther7 ") {
            value = value.right( 1);
        }
         // 當前不是中文模式,則單擊按鈕對應text為傳遞參數
         if (currentType !=  " chinese ") {
             if (currentLineEdit !=  0) {
                currentLineEdit->insert(value);
            }
        }  else {
             if (currentLineEdit !=  0) {
                 // 中文模式下,不允許輸入特殊字符,單擊對應數字按鍵取得當前索引的漢字
                 if (btn->property( " btnOther ").toBool()) {
                     if (ui->labPY->text().length() ==  0) {
                        currentLineEdit->insert(value);
                    }
                }  else  if (btn->property( " btnNum ").toBool()) {
                     if (ui->labPY->text().length() ==  0) {
                        currentLineEdit->insert(value);
                    }  else  if (objectName ==  " btn0 ") {
                        setChinese( 0);
                    }  else  if (objectName ==  " btn1 ") {
                        setChinese( 1);
                    }  else  if (objectName ==  " btn2 ") {
                        setChinese( 2);
                    }  else  if (objectName ==  " btn3 ") {
                        setChinese( 3);
                    }  else  if (objectName ==  " btn4 ") {
                        setChinese( 4);
                    }  else  if (objectName ==  " btn5 ") {
                        setChinese( 5);
                    }  else  if (objectName ==  " btn6 ") {
                        setChinese( 6);
                    }  else  if (objectName ==  " btn7 ") {
                        setChinese( 7);
                    }  else  if (objectName ==  " btn8 ") {
                        setChinese( 8);
                    }  else  if (objectName ==  " btn9 ") {
                        setChinese( 9);
                    }
                }  else  if (btn->property( " btnLetter ").toBool()) {
                    ui->labPY->setText(ui->labPY->text() + value);
                    selectChinese();
                }
            }
        }
    }
}

4:漢字列表單擊選擇。

// 事件過濾器,用於識別鼠標單擊漢字標簽處獲取對應漢字
bool frmInput::eventFilter(QObject *obj, QEvent * event)
{
     if ( event->type() == QEvent::MouseButtonPress) {
         if (obj == ui->labCh0) {
            setChinese( 0);
        }  else  if (obj == ui->labCh1) {
            setChinese( 1);
        }  else  if (obj == ui->labCh2) {
            setChinese( 2);
        }  else  if (obj == ui->labCh3) {
            setChinese( 3);
        }  else  if (obj == ui->labCh4) {
            setChinese( 4);
        }  else  if (obj == ui->labCh5) {
            setChinese( 5);
        }  else  if (obj == ui->labCh6) {
            setChinese( 6);
        }  else  if (obj == ui->labCh7) {
            setChinese( 7);
        }  else  if (obj == ui->labCh8) {
            setChinese( 8);
        }  else  if (obj == ui->labCh9) {
            setChinese( 9);
        }
         return  false;
    }  else  if ( event->type() == QEvent::KeyPress) {
         // 如果處於中文模式,需要將當前按鍵對應反應到輸入法界面上
         if (currentType ==  " chinese ") {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>( event);
             if (keyEvent->key() == Qt::Key_Backspace) {
                ui->btnDelete->click();
            }  else {
                QString key = keyEvent->text();
                QList<QPushButton *> btn =  this->findChildren<QPushButton *>();
                 foreach (QPushButton * b, btn) {
                     if (b->text() == key) {
                        b->click();
                         break;
                    }
                }
            }
             return  true;
        }
         return  false;
    }
     return QObject::eventFilter(obj,  event);
}

5:漢字智能分頁算法。

void frmInput::selectChinese()
{
    clearChinese();
    QSqlQuery query;
    QString currentPY = ui->labPY->text();
    QString sql =  " select [word] from [pinyin] where [pinyin]=' " + currentPY +  " '; ";
    query.exec(sql);
     // 逐個將查詢到的字詞加入漢字隊列
     while(query.next()) {
        QString result = query.value( 0).toString();
         if (App::PYType ==  " danpin ") {
            allPY.append(result);
            currentPY_count++;
        }  else {
            QStringList text = result.split( "   ");
             foreach (QString txt, text) {
                 if (txt.length() >  0) {
                    allPY.append(txt);
                    currentPY_count++;
                }
            }
        }
    }
    showChinese();
}
void frmInput::showChinese()
{
     // 每個版面最多顯示10個漢字
     int count =  0;
    currentPY.clear();
     for ( int i =  0; i <  10; i++) {
        labCh[i]->setText( "");
    }
 
     for ( int i = currentPY_index; i < currentPY_count; i++) {
         if (count ==  10) {
             break;
        }
        QString txt = QString( " %1.%2 ").arg(count).arg(allPY[currentPY_index]);
        currentPY.append(allPY[currentPY_index]);
        labCh[count]->setText(txt);
        count++;
        currentPY_index++;
    }
     // qDebug() << "currentPY_index:" << currentPY_index << "currentPY_count:" << currentPY_count;
}

 

可定制皮膚樣式和輸入法布局,聯系QQ:517216493

可執行文件下載地址:http://pan.baidu.com/s/1sjHPM8l

核心代碼下載地址:http://pan.baidu.com/s/1hqu16M4

備注:

核心代碼開源,希望大家嘴下留情,10元出售完整工程,歡迎大家多多提建議!

謝謝!

編譯完成后將源碼下的file目錄中的兩個數據庫文件復制到bin目錄即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM