【Qt实用技巧】实现群聊@群成员-弹出跟随窗口

489 阅读2分钟

📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!


前言

前面的文章中提到了在QTextEdit输入框中输入字符时会有检测,遇到@等特定的字符时产生响应。本节则接着上节来研究一下产生的响应如何实现弹出一个可以跟随文字输入的窗口(这个窗口可以放置列表,下拉框,输入框等控件,根据实际需要使用)。

示例

动画1.gif

创建跟随的窗口

新建一个QWidget窗口或者QDialog弹窗都可,作为跟随的小窗口。

image.png

//form.cpp

#include "form.h"
#include "ui_form.h"

Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form)
{
    ui->setupUi(this);

    setWindowFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint
                   |Qt::WindowStaysOnTopHint|Qt::WindowSystemMenuHint);
}

Form::~Form()
{
    delete ui;
}

获取窗口位置

主要使用QTextEdit输入框中的textCursor文字光标位置来获取光标位置,然后将上面创建的自定义窗口移动到光标位置并显示。

因为创建的跟随窗口并没有将主窗口作为父窗口,因此在关闭主窗口时跟随窗口并不会随之关闭,需要使用closeEvent关闭事件来将跟随窗口关闭。

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "form.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

protected:
    void closeEvent(QCloseEvent *event);

private slots:
    void on_textEdit_cursorPositionChanged();

private:
    Ui::MainWindow *ui;

    Form *w;
};
#endif // MAINWINDOW_H
//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTextBlock>
#include <QTextCursor>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    w = new Form();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(w->isVisible())
        w->close();
}


void MainWindow::on_textEdit_cursorPositionChanged()
{
    QTextCursor tc = ui->textEdit->textCursor();
    QTextBlock tb = tc.block();
    QString tx = tb.text();
    
    if(w->isVisible())
    {
#if 1
        QRect rect = ui->textEdit->cursorRect();                     //获取光标位置
        QPoint point = ui->textEdit->mapToGlobal(rect.topLeft());    //转换为全局坐标
        w->move(point.x(),point.y()-w->height());
#else
//        w->close();
#endif
    }
    else
    {
       if(tx.endsWith("@"))
       {
           QRect rect = ui->textEdit->cursorRect();                     //获取光标位置
           QPoint point = ui->textEdit->mapToGlobal(rect.topLeft());    //转换为全局坐标
           w->show();
           w->move(point.x(),point.y()-w->height());

           ui->textEdit->activateWindow();
           ui->textEdit->setFocus();
       }
    }
}