📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!
前言
前面的文章中已经实现了输入@符号弹出可以跟随文字显示的窗口,窗口中简单放置了一行文字(作者的笔名何名取)。本节则来模拟一下微信中输入@弹出群成员列表,并且可以进行群成员的选择。
按键过滤
在输入框与弹出的群成员列表交互过程中会产生一系列的按键事件。如上面动图中显示的那样,弹出群成员列表后可以按下键盘上的上下键进行选择成员,按下回车键确定选择,还有其他的比如空格键等。因此需要对按键事件进行过滤,并且实现相应按键事件的响应功能。
在Qt中可以重写eventFilter事件过滤函数来实现我们所需的按键过滤。
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if(event->type() == QEvent::KeyPress) //键盘按下事件
{
if(watched == ui->textEdit) //事件发送者为输入框
{
QKeyEvent *k = static_cast<QKeyEvent *>(event);
if(k->key() == Qt::Key_Up)
{
if(w->isVisible())
{
w->keySelectItem(false);
return true;
}
else
return QWidget::eventFilter(watched,event);
}
else if(k->key() == Qt::Key_Down)
{
if(w->isVisible())
{
w->keySelectItem(true);
return true;
}
else
return QWidget::eventFilter(watched,event);
}
else if(k->key() == Qt::Key_Space)
{
if(w->isVisible())
{
w->close();
return true;
}
else
return QWidget::eventFilter(watched,event);
}
else if(k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter)
{
if(w->isVisible())
{
QString name = w->getSelectName();
receiveName(name);
w->close();
return true;
}
else
return QWidget::eventFilter(watched,event);
}
else if(k->key() == Qt::Key_Backspace)
{
if(w->isVisible())
{
w->close();
return true;
}
else
return QWidget::eventFilter(watched,event);
}
else
return QWidget::eventFilter(watched,event);
}
else
return QWidget::eventFilter(watched,event);
}
else
return QWidget::eventFilter(watched,event);
}
需要注意的一点是重写完成eventFilter事件过滤函数后必须进行注册才可以产生过滤。
ui->textEdit->installEventFilter(this);
修改弹出窗口
上节并没有对弹出的窗口进行过多操作,本节将给窗口中添加QListWidget列表作为可选择的群成员列表。
按键选择
通过上下按键来进行当前列表项的选择。
void Form::keySelectItem(bool flag)
{
int row = ui->listWidget->currentRow();
if(flag)
{
if(row + 1 >= ui->listWidget->count())
ui->listWidget->setCurrentRow(0);
else
ui->listWidget->setCurrentRow(row + 1);
}
else
{
if(row - 1 < 0)
ui->listWidget->setCurrentRow(ui->listWidget->count() - 1);
else
ui->listWidget->setCurrentRow(row - 1);
}
}
设置成员添加规则
我使用了QMap来储存三个简单的字符串来模拟群成员选项。
users["hemingqu"] = "何名取";
users["juejin"] = "掘金";
users["2023"] = "2023";
之后为列表中添加上这几个成员,并且设置输入时的匹配规则。
void Form::setFilter(QString filter)
{
ui->listWidget->clear();
for (int i = 0; i < users.count(); ++i) {
addItem(users.keys().at(i),users.values().at(i),filter);
}
if(ui->listWidget->count() == 0)
{
close();
return;
}
ui->listWidget->setCurrentRow(0);
this->setAttribute(Qt::WA_ShowWithoutActivating);
ui->listWidget->setFocus();
}
void Form::addItem(QString userId, QString name, QString filter)
{
if(!userId.contains(filter) && !name.contains(filter))
return;
QListWidgetItem *item = new QListWidgetItem(ui->listWidget);
item->setFont(QFont("",14));
item->setText(name);
ui->listWidget->addItem(item);
}
成员信息获取
最后在弹窗中被选择的信息需要一个可以获取函数来进行传递。
QString Form::getSelectName()
{
QListWidgetItem *item = ui->listWidget->currentItem();
if(item == nullptr)
return "";
return item->text();
}
接收信息响应
在主窗口中要将传递的成员信息进行接收,并插入输入框中展示。
void MainWindow::receiveName(QString name)
{
while(!ui->textEdit->textCursor().block().text().endsWith("@"))
ui->textEdit->textCursor().deletePreviousChar();
if(ui->textEdit->textCursor().block().text().endsWith("@"))
;
else
ui->textEdit->textCursor().insertText("@");
ui->textEdit->textCursor().insertText(name);
}