Files
Renderive/Widget/base/Virtual_Keyboard/Virtual_Keyboard.cpp
T
2026-08-01 20:09:45 +08:00

208 lines
6.8 KiB
C++

#include "Virtual_Keyboard.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
namespace Flex_Qt {
Key_Button::Key_Button() {
/*支持长按*/
// this->setAutoRepeat(true);
// this->setAutoRepeatDelay(500);
// this->setAutoRepeatInterval(100);
connect(this, &QPushButton::pressed, [&]() {
virtual_keyboard->handle_Key_Press(this);
});
}
Virtual_Keyboard::Virtual_Keyboard(QWidget* parent) : QWidget(parent) {
this->setStyleSheet(
"QPushButton{"
"font: 16pt 黑体;"
"font-size: 26px;"
"color: white;"
"margin: 2px;"
"border-radius: 5px;"
"background: #00C78C;}"
"QPushButton:pressed{"
"background: #F0FFFF ;}"
"QListWidget::Item:hover { background: #00C78C; color: white; }"
"QListWidget {outline: none; border:1px solid #00000000; color: black; }"
"QLineEdit {outline: none; border:1px solid #00000000; color: black;}");
QSize screen_size = QGuiApplication::primaryScreen()->size();
resize(screen_size / 2);
main_layout = new QVBoxLayout(this);
size_policy.setHorizontalPolicy(QSizePolicy::Preferred);
size_policy.setVerticalPolicy(QSizePolicy::Preferred);
size_policy.setHorizontalStretch(1);
size_policy.setVerticalStretch(0);
english = create_english();
chinese = create_chinese();
symbol = create_symbol();
main_layout->addWidget(english);
main_layout->addWidget(chinese);
main_layout->addWidget(symbol);
cur_widget = english;
chinese->hide();
symbol->hide();
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool | Qt::WindowDoesNotAcceptFocus);
core = new Input_Core(this);
if (!core->init()) {
std::cout << "字典加载失败,请将dict文件移至工作目录";
}
/* 设置为列表显示模式 */
list_widget->setViewMode(QListView::ListMode);
/* 从左往右排列 */
list_widget->setFlow(QListView::LeftToRight);
/* 屏蔽水平滑动条 */
list_widget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
/* 屏蔽垂直滑动条 */
list_widget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
/* 设置为像素滚动 */
list_widget->setHorizontalScrollMode(QListWidget::ScrollPerPixel);
/* 设置鼠标左键拖动 */
QScroller::grabGesture(list_widget, QScroller::LeftMouseButtonGesture);
// 设置不可选中
connect(edit, &QLineEdit::selectionChanged, [=] {
edit->deselect();
});
// 中文输入
connect(edit, &QLineEdit::textChanged, [=](const QString& text) {
/* 单个字符过长引发崩溃
* 处理:单个字符限制长度为10
*/
if (text.isEmpty()) {
return;
}
if (text.length() >= 10) {
if (is_single_char(text)) {
QString deal_text = text.mid(0, 10);
get_candidate_list(deal_text);
return;
}
get_candidate_list(text);
return;
}
else {
get_candidate_list(text);
}
});
connect(list_widget, &QListWidget::itemClicked, [=](QListWidgetItem* item) {
QKeyEvent key_press(QEvent::KeyPress, Qt::Key_unknown, Qt::NoModifier, item->text());
QCoreApplication::sendEvent(input_widget, &key_press);
list_widget->clear();
edit->clear();
});
}
Virtual_Keyboard::~Virtual_Keyboard() {}
bool Virtual_Keyboard::is_single_char(QString spell) {
bool ret = true;
for (auto s : spell) {
if (s != spell[0]) {
ret = false;
break;
}
}
return ret;
}
void Virtual_Keyboard::set_edit(QWidget* edit) {
this->input_widget = edit;
this->input_widget->installEventFilter(this);
}
void Virtual_Keyboard::get_candidate_list(const QString spell) {
unsigned int cand = core->search(spell);
if (cand == 0) {
return;
}
std::vector<QString> ret = core->get_candidate(cand);
if (ret.empty()) {
return;
}
list_widget->clear();
for (const QString& candidate : ret)
list_widget->addItem(candidate);
}
void Virtual_Keyboard::handle_Key_Press(Key_Button* button) {
if (state == Chinese) {
if (button->key != Qt::Key_Backspace) {
edit->insert(button->text);
}
else {
if (!edit->text().isEmpty()) {
edit->backspace();
}
else {
list_widget->clear();
QKeyEvent key_press(QEvent::KeyPress, button->key, button->modifiers, button->text);
QCoreApplication::sendEvent(input_widget, &key_press);
}
}
}
else {
if (button->is_text) {
QKeyEvent key_press(QEvent::KeyPress, button->key, button->modifiers, button->text);
if (input_widget) {
QCoreApplication::sendEvent(input_widget, &key_press);
}
else {
qWarning("VirtualKeyBoard input_widget == NULL!");
}
}
}
}
bool Virtual_Keyboard::eventFilter(QObject* watched, QEvent* event) {
bool ok = false;
if (QApplication::focusWidget() == watched && event->type() == QEvent::MouseButtonRelease) {
ok = true;
}
if (event->type() == QEvent::FocusIn) {
ok = true;
}
if (ok) {
QWidget* w = qobject_cast<QWidget*>(watched);
set_edit(w);
QPoint pos = w->mapToGlobal(QPoint(0, 0));
QSize screen_size = QGuiApplication::primaryScreen()->size();
int keyboard_width = width();
int keyboard_height = height();
int screen_width = screen_size.width();
int screen_height = screen_size.height();
int x = pos.x();
int y = pos.y() + w->height();
if (x + keyboard_width > screen_width) {
setFixedWidth(screen_width - pos.x() - w->width());
}
if (y + keyboard_height > screen_height) {
setFixedHeight(screen_height - pos.y() - w->height());
}
move(x, y);
show();
}
if (event->type() == QEvent::FocusOut) {
this->hide();
}
return QObject::eventFilter(watched, event);
}
void Virtual_Keyboard::mousePressEvent(QMouseEvent* event) {
if (moving)
return;
if (event->button() == Qt::LeftButton) {
moving = true;
start_pos = pos();
start_global_pos = event->globalPos();
QApplication::setOverrideCursor(Qt::ClosedHandCursor);
}
event->accept();
}
void Virtual_Keyboard::mouseMoveEvent(QMouseEvent* event) {
if (!moving)
return;
move(start_pos + event->globalPos() - start_global_pos);
event->accept();
}
void Virtual_Keyboard::mouseReleaseEvent(QMouseEvent* event) {
if (!moving)
return;
moving = false;
event->accept();
QApplication::restoreOverrideCursor();
}
} // Flex_Qt