qt类似电视盒子的通过方向键切换焦点的实现方法

1 篇文章 0 订阅

比如中
比如这样的需求需要焦点通过上下左右在按钮和widget或者其他窗口类中切换。
核心实现方法就是通过一个信号单例接收全局的键盘事件并发出信号每个要切换的焦点类都连接上接收到信号的窗口类或者button将自己的指针传入单例类延时50ms后(一般50毫秒后所有连接信号的槽函数都执行完了)再在这个单例类中获取当前焦点的对象的全局坐标和所有的对象比对全局坐标通过方向计算找到最近的一个对象设置焦点。

代码文件就一个

#ifndef FOCUSMANAGEMENT_H
#define FOCUSMANAGEMENT_H

#include <QObject>
#include <QTimer>
#include <QWidget>
#include <QMap>
#include <QApplication>
class FocusManagement : public QObject
{
    Q_OBJECT
public:
    static FocusManagement* getinstance();
    void startJudge(QWidget * w,Qt::Key);
private:
    explicit FocusManagement(QObject *parent = 0);
    void clearInfo();

signals:
    void sigFocusChange(Qt::Key key);
public slots:
    void onTimeOut();
private:
    QTimer m_timer;
    Qt::Key m_currentKey;
    QList<QWidget*>m_eventWidgetList;
    QMap<int,QWidget*>m_eventMap;
};

#endif // FOCUSMANAGEMENT_H



#include "focusmanagement.h"
#include <QLine>
#include <QDebug>
FocusManagement *FocusManagement::getinstance()
{
    static FocusManagement *instance = NULL;

    if(instance == NULL)
    {
        instance = new FocusManagement();
    }
    return instance;
}

void FocusManagement::startJudge(QWidget *w, Qt::Key key)
{
    if(!w){
        return;
    }
    m_eventWidgetList.push_back(w);
    if(m_timer.isActive())
        return;
    m_timer.start(50);
    m_currentKey = key;
}

void FocusManagement::clearInfo()
{
    m_eventWidgetList.clear();
    m_eventMap.clear();
}

FocusManagement::FocusManagement(QObject *parent) : QObject(parent)
{
    connect(&m_timer,SIGNAL(timeout()),this,SLOT(onTimeOut()));
}

void FocusManagement::onTimeOut()
{
    m_timer.stop();
    QWidget * cfw = qApp->focusWidget();
    if(cfw == nullptr){
        clearInfo();
        return;

    }

    QPoint cfp;
    switch (m_currentKey) {
    case Qt::Key_Up:
        cfp = cfw->mapToGlobal(QPoint(cfw->width()/2,0));
        break;
    case Qt::Key_Down:
        cfp = cfw->mapToGlobal(QPoint(cfw->width()/2,cfw->height()));
        break;
    case Qt::Key_Left:
        cfp = cfw->mapToGlobal(QPoint(0,cfw->height()/2));
        break;
    case Qt::Key_Right:
        cfp = cfw->mapToGlobal(QPoint(cfw->width(),cfw->height()/2));
        break;
    default:
        break;
    }

    for(int i = 0 ; i<m_eventWidgetList.size();i++)
    {
        QWidget *evw = m_eventWidgetList.at(i);

        if(evw == cfw)
            continue;
        QPoint evp;
        switch (m_currentKey) {
        case Qt::Key_Up:
                evp = evw->mapToGlobal(QPoint(evw->width()/2,evw->height()));
                if(evp.y()<= cfp.y()){
                m_eventMap[QLineF(evp,cfp).length()] = evw;
            }
            break;
        case Qt::Key_Down:
                evp = evw->mapToGlobal(QPoint(evw->width()/2,0));
                if(evp.y()>= cfp.y()){
                m_eventMap[QLineF(evp,cfp).length()] = evw;
            }
            break;
        case Qt::Key_Left:

                evp = evw->mapToGlobal(QPoint(evw->width(),evw->height()/2));
                if(evp.x()- cfp.x()<=0){
                m_eventMap[QLineF(evp,cfp).length()] = evw;
            }
            break;
        case Qt::Key_Right:

                evp = evw->mapToGlobal(QPoint(0,evw->height()/2));
                if(evp.x()- cfp.x()>=0){
                m_eventMap[QLineF(evp,cfp).length()] = evw;
            }
            break;
        default:
            break;
        }

    }

    if(!m_eventMap.isEmpty()){
        m_eventMap.first()->setFocus();
    }
    clearInfo();
}

需要切换焦点的类的槽函数

#include "testwidget.h"
#include "ui_testwidget.h"

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

    m_eventWidgetList.push_back(ui->pushButton);
    m_eventWidgetList.push_back(ui->pushButton_2);
    m_eventWidgetList.push_back(ui->pushButton_3);

    connect(FocusManagement::getinstance(),SIGNAL(sigFocusChange(Qt::Key)),this,SLOT(onFocusChange(Qt::Key)));

}

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


void TestWidget::onFocusChange(Qt::Key key)
{
    for(int i = 0; i<m_eventWidgetList.size();i++)
    {
        FocusManagement::getinstance()->startJudge(static_cast<QWidget*>(m_eventWidgetList.at(i)),key);
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值