Qt6.0开发 第六章 事件处理

第六章 事件处理


Qt的事件系统

事件的产生与派发

GUI应用程序是由事件(event)驱动的,点击鼠标、按下某个按键、改变窗口大小等都会产生对应事件.Qt为事件处理编程提供了完善的支持.QWidget定义了大量与事件处理相关的数据类型与接口函数.

事件表示应用程序中发生的操作或变化.在Qt中,事件是对象,是QEvent类或其派生类的实例.

按事件的来源,可以将事件划分为3类:

  • 自生事件(spontaneous event):是由窗口系统产生的事件.自生事件会进入系统队列,然后被应用程序的事件循环逐个处理.
  • 发布事件(posted event):是由Qt或应用程序产生的事件.发布事件会进入Qt事件队列,然后由应用程序的事件循环进行处理.
  • 发送事件(sent event):是由Qt或应用程序定向发送给某个对象的事件.

窗口系统产生的自生事件自动进入系统队列,应用程序发布事件进入Qt事件队列.

自生事件和发布事件的处理是异步的,也就是事件进入队列后由系统去处理,程序不会在产生事件的地方停止进行等待.

应用程序里的事件循环只处理自生事件和发布事件,而不会处理发送事件,因为发送事件由应用程序直接派发给某个对象,是以同步模式运行的.

处理事件相关的函数有:

  • void QCoreApplication::postEvent(QObject *receiver,QEvent *event,int priority=Qt::NormalEventPriority)
    //发布某个事件
  • bool QCoreApplication::sentEvent(QObject *receiver,QEvent *event)//向某个对象发送事件
  • void QCoreApplication::processEvent(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
    //将事件队列里未处理的时间派发出来
  • void QCoreApplication::sendPostedEvents(QObject *receiver=nullptr,int event_type=0)
    //立刻将发布事件派发出去

枚举类型QEventLoop::ProcessEventsFlag有以下几种枚举值:

  • QEventLoop::AllEvents:处理所有事件
  • QEventLoop::ExcludeUserInputEvents::排除用户输入事件
  • QEventLoop::ExcludeSocketNotifiers:排除网络socket的通知事件
  • QEventLoop::WaitForMoreEvents::如果没有未处理的事件,等待更多事件

事件类和事件类型

事件是QEvent类或其派生类的实例,大多数的事件有其专门的类.QEvent是所有事件类的基类,但它不是一个抽象类,它也可以用于创建事件.

QEvent的主要接口函数有:

  • void accept()//接受事件
  • void ignore()//忽略事件
  • bool isAccepted()//是否接受事件
  • bool isInputEvent()//事件对象是否为QInputEvent或其派生类
  • bool isPointerEvent()//事件对象是否为QPointerEvent或其派生类
  • bool isSinglePointEvent()//事件对象是不是QSinglePointEvent或其派生类
  • bool spontaneous()//是否为自生事件
  • QEvent::Type type()//事件类型

常见的事件类及其所述的事件类见下表:

常见的事件类型及其所属的事件类
事件类 事件类型 事件描述
QMouseEvent QEvent::MouseButtonDblClick
QEvent::MouseButtonPress
QEvent::MouseButtonRelease
QEvent::MouseMove
鼠标双击
鼠标按键按下
鼠标按键释放
鼠标移动
QWheelEvent QEvent::QWheelEvent 鼠标滚轮滚动
QHoverEvent QEvent::HoverEnter
QEvent::HoverLeave
QEvent::HoverMove
鼠标光标移动到组件上方并悬停
鼠标光标离开某个组件上方
鼠标光标在组件上方移动
QEnterEvent QEvent::Enter 鼠标光标进入组件或窗口边界范围内
QEvent QEvent::Leave 鼠标光标离开组件或窗口边界范围
QKeyEvent QEvent::KeyPress
QEvent::KeyRelease
键盘按键按下
键盘按键释放
QFocusEvent QEvent::FocusIn
QEvent::FocusOut
QEvent::FocusAboutToChange
组件或窗口获得键盘的输入焦点
组件或窗口失去键盘的输入焦点
组件或窗口的键盘输入焦点即将变化
QShowEvent QEvent::Show 窗口在屏幕上显示出来,或组件变得可见
QHideEvent QEvent::Hide 窗口在屏幕上隐藏,或组件变得不可见
QMoveEvent QEvent::Mode 组件或窗口的位置移动
QCloseEvent QEvent::Close 窗口或组件被关闭
QPaintEvent QEvent::Paint 界面组件需要更新重绘
QResizeEvent QEvent::Resize 窗口或组件改变大小
QStatusTipEvent QEvent::StatusTip 请求显示组件的statusTip信息
QHelpEvent QEvent::ToolTip
QEvent::WhatsThis
请求显示组件的toolTip信息
请求显示组件的whatsThis信息
QDragEnterEvent QEvent::DragEvent 在拖放操作中,鼠标光标移动到组件上方
QDragLeaveEvent QEvent::DragLeave 在拖放操作中,鼠标光标离开了组件
QDragMoveEvent QEvent::DragMove 拖放操作正在移动过程中
QDropEvent QEvent::Drop 拖放操作完成,即放下拖动的对象
QTouchEvent QEvent::TouchBegin
QEvent::TouchCancel
QEvent::TouchEnd
QEvent::TouchUpdate
开始一个触屏事件序列
取消一个触屏事件序列
结束一个触屏事件序列
触屏事件
QGestureEvent QEvent::Gesture 手势事件
QNativeGestureEvent QEvent::NativeGesture 手势事件
QActionEvent QEvent::ActionAdded
QEvent::ActionChanged
QEvent::ActionRemoved
运行QWidget::addAction()函数
Action改变时触发
Action移除时触发的事件

事件的处理

任何从QObject派生的类都可以处理事件,但其中主要是从QWidget派生的窗口类和界面组件类需要处理事件.

一个对象接收到应用程序派发来的事件后,首先会由函数event()处理.event()是QObject类中定义的一个虚函数,其函数原型定义如下:

  • bool QObject::event(QEvent* e)

被accept()接受的事件由事件接收者处理,被ignore()忽略的事件则传播到事件接收者的父容器组件.这称为事件的传播(propagation),事件最后可能会传播给窗口.

QWidget类中定义了很多典型事件的处理函数,这些函数都有一个参数event,它是具体事件类的对象.一个函数对应一个类型的事件,但是多个函数的参数event的类型可能是一样的.

事件处理函数名 对应的事件类型 参数event的类型 事件描述
mouseDoubleClickEvent() QEvent::MouseButtonDblClick QMouseEvent 鼠标双击
mousePressEvent() QEvent::MouseButtonPress QMouseEvent 鼠标按键按下
mouseReleaseEvent() QEvent::MouseButtonRelease QMouseEvent 鼠标按键释放
mouseMoveEvent() QEvent::MouseMove QMouseEvent 鼠标移动
wheelEvent() QEvent::QWheelEvent QWheelEvent 鼠标滚轮滚动
enterEvent() QEvent::Enter QEnterEvent 鼠标光标进入组件或窗口边界范围内
leaveEvent() QEvent::Leave QEvent 鼠标光标离开组件或窗口边界范围
keyPressEvent() QEvent::KeyPress QKeyEvent 键盘按键按下
keyReleaseEvent() QEvent::KeyRelease QKeyEvent 键盘按键释放
focusInEvent() QEvent::FocusIn QFocusEvent 组件或窗口获得键盘的输入焦点
focusOutEvent() QEvent::FoucusOut QFocusEvent 组件或窗口失去键盘的输入焦点
showEvent() QEvent::Show QShowEvent 窗口在屏幕上显示出来
hideEvent() QEvent::Hide QHideEvent 窗口在屏幕上隐藏
moveEvent() QEvent::Move QMoveEvent 组件或窗口的位置移动
closeEvent() QEvent::Close QCloseEvent 窗口或组件被关闭
paintEvent() QEvent::Paint QPaintEvent 界面组件需要重绘
resizeEvent() QEvent::Resize QResizeEvent 窗口或组件需要改变大小
dragEnterEvent() QEvent::DragEvent QDragEnterEvent 在拖放操作中,鼠标光标移动到组件上方
dragLeaveEvent() QEvent::DragLeave QDragLeaveEvent 在拖放操作中,鼠标光标离开了组件
dragMoveEvent() QEvent::DragMove QDragMoveEvent 拖放操作正在移动过程中
dropEvent() QEvent::Drop QDropEvent 拖放操作完毕,即放下拖动的对象

事件与信号

事件和信号的区别在于,事件通常是由窗口系统或应用程序产生的,信号则是Qt定义或用户自定义的.

在使用界面组件为交互操作编程的时候,我们通常选择合适的信号,为该信号编写槽函数.

但是,Qt的界面只将少数事件封装成了信号,对于某些事件可能缺少对应的信号.在这种情况,我们可以从某些类继承定义出一个新类,通过自定义信号与事件处理来达到新事件的效果.

应用程序派发给界面组件的事件首先会由其函数event()处理,因而通过重载event()可以实现对事件处理机制的自定义化.

下面是一个综合应用的实例:

tmy_label.h

#ifndef TMYLABEL_H
#define TMYLABEL_H

#include <QLabel>
#include <QObject>
#include <QEvent>

class TMyLabel : public QLabel
{
    Q_OBJECT
public:
    TMyLabel(QWidget *parent=nullptr);
signals:
    void doubleClicked();

    // QWidget interface
protected:
    virtual void mouseDoubleClickEvent(QMouseEvent *event) override;

    // QObject interface
public:
    virtual bool event(QEvent *event) override;
};

#endif // TMYLABEL_H

mainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;

    // QWidget interface
private slots:
    void do_doubleClick();
protected:
    virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
};


#endif // MAINWINDOW_H

tmy_label.cpp

#include "tmy_label.h"

TMyLabel::TMyLabel(QWidget *parent)
    :QLabel(parent)
{
    setAttribute(Qt::WA_Hover,true);
}

void TMyLabel::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    emit doubleClicked();
}

bool TMyLabel::event(QEvent *event)
{
    if(event->type()==QEvent::HoverEnter){
        QPalette plet=this->palette();
        plet.setColor(QPalette::WindowText,Qt::red);
        setPalette(plet);
    }
    else if(event->type()==QEvent::HoverLeave){
        QPalette plet=this->palette();
        plet.setColor(QPalette::WindowText,Qt::black);
        setPalette(plet);
    }
    return QLabel::event(event);
}

mainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->label,SIGNAL(doubleClicked()),this,SLOT(do_doubleClick()));
}

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

void MainWindow::do_doubleClick()
{
    ui->label->setText("标签被双击,信号槽得到响应");
    ui->label->adjustSize();
}

void MainWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    ui->label->setText("被双击力(悲)");
    ui->label->adjustSize();
}


事件过滤器

从上面给出的例子可以看到,一个界面组件如果要对事件进行处理,需要从父类继承定义一个新类,在新类里编写程序直接处理事件,或者将事件转换为信号.

如果不想定义一个新的类,可以用事件过滤器(event filter)对界面组件的事件进行处理.

事件过滤器是QObject提供的一种处理事件的方法,它可以将一个对象的事件委托给另一个对象来监视并处理.

要实现事件过滤器功能,需要完成两项操作:

  • 被监视对象使用函数installEventFilter()将自己注册给监视对象,监视对象就是过滤器.
  • 监视对象重新实现函数eventFilter()将监视到的事件进行处理.

涉及到的函数原型有:

  • void QObject::installEventFilter(QObject *filterObj)
  • bool QObject::eventFilter(QObject *watched,QEvent *event)

下面是一个例子:

mainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(watched==ui->lbUp)
        if(event->type()==QEvent::Enter)
            ui->lbUp->setStyleSheet("background-color:rgb(170,255,255);");
        else if(event->type()==QEvent::Leave){
            ui->lbUp->setText("单击我");
            ui->lbUp->setStyleSheet("");
        }
        else if(event->type()==QEvent::MouseButtonPress)
            ui->lbUp->setText("Button Pressed");
        else if(event->type()==QEvent::MouseButtonRelease)
            ui->lbUp->setText("Button Release");

    if(watched==ui->lbDown)
        if(event->type()==QEvent::Enter)
            ui->lbDown->setStyleSheet("background-color:rgb(85,255,127);");
        else if(event->type()==QEvent::Leave){
            ui->lbDown->setText("双击我");
            ui->lbDown->setStyleSheet("");
        }
        else if(event->type()==QEvent::MouseButtonDblClick)
            ui->lbDown->setText("Button Double Clicked");

    return QWidget::eventFilter(watched,event);
}

拖放事件与拖放操作

拖放(drag and drop)操作是GUI应用程序中经常使用的一种操作.

拖放由两个操作组成:拖动(drag)和放置(drop).被拖动的组件称为拖动点(drag site).接收拖动操作的组件称为放置点(drop site).

拖动点与放置点可以是不同的组件.甚至可以是不同的应用程序.

整个拖放操作可以分解为两个过程:

  • 拖动点启动拖动操作:被拖动组件通过mousePressEvent()和mouseMoveEvent()这两个事件处理函数的处理,检测到左键按下并移动时就可以启动拖动操作.
  • 放置点处理放置操作:当拖动操作移动到放置点范围内时,首先触发dragEnterEvent()事件处理函数,在此函数里一般要通过QDrag对象的mimeData数据判断拖动操作的来源和参数,以决定是否触发dropEvent()接收此拖动操作.
    下面是两个相关函数的原型:
  • void dragEnterEvent(QDragEnterEvent *event);
  • void dropEvent(QDropEvent *event);

还有一些相关的函数包括有:

  • acceptDrops():返回一个bool型值,表示组件是否可以作为放置点接受放置操作
  • dragEnabled():返回一个bool型值,表示组件是否可以作为拖动点启动拖动操作
  • dragDropMode():返回结果为QAbstractItemView类型的值,表示拖放操作模式
  • defaultDropAction():返回结果为枚举类型Qt::DropAction.当组件作为放置点时,它表示完成拖放操作时数据操作的模式.

以上函数都有其对应的setter函数.

QAbstractItemView::DragDropMode的枚举值:

  • QAbstractItemView::NoDragDrop//组件不支持拖放操作
  • QAbstractItemView::DragOnly//组件只支持拖动操作
  • QAbstractItemView::DropOnly//组件只支持放置操作
  • QAbstractItemView::DragDrop//组件支持拖放操作
  • QAbstractItemView::InternalMove//组件支持内部项拖放操作

Qt::DropAction的枚举值:

  • Qt::CopyAction//将数据复制到放置点处
  • Qt::MoveAction//将数据从拖动点组件移动到放置点处
  • Qt::LinkAction//在拖动点组件和放置点组件之间建立数据连接
  • Qt::IgnoreAction//对数据不进行任何操作

QWidget类有一个属性acceptDrops,如果设置为true,那么对应的这个组件就可以设置为一个放置点.

QAbstractItemView类定义了更多与拖动操作相关的函数,因而其相关类可以作为放置点.

多用途互联网跟邮件扩展(multipurpose Internet mail extensions,MIME)被设计的最初目的是在发送电子邮件时附加多媒体数据,使邮件客户端能根据其类型进行处理.

QMimeData是对MIME数据的封装,在拖放操作和剪切板操作中都用QMimeData描述传输的数据.

QMimeData常用函数
MIME格式 判断函数 获取数据的函数 设置函数
text/plain hasText() text() setText()
text/html hasHtml() html() setHtml()
text/url-list hasUrls() urls() setUrls()
image/* hasImage() imageData() setImageData()
application/x-color hasColor() colorData() setColorData()

下面是一个综合使用的例子:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setAcceptDrops(true);
    ui->plainTextEdit->setAcceptDrops(false);
    ui->plainTextEdit->setAcceptDrops(false);
    ui->label->setScaledContents(true);
}

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

void MainWindow::resizeEvent(QResizeEvent *event)
{
    QSize sz=ui->plainTextEdit->size();

    ui->plainTextEdit->move(0,5);
    ui->label->move(0,sz.height()+10);

    ui->plainTextEdit->resize(this->width(),sz.height());
    ui->label->resize(this->width(),this->height()-sz.height());
    event->accept();
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    ui->plainTextEdit->clear();
    ui->plainTextEdit->appendPlainText(QString("dragEnter事件:mimeData的Format"));
    for(auto &iter:event->mimeData()->formats())
        ui->plainTextEdit->appendPlainText(iter);
    ui->plainTextEdit->appendPlainText(QString("dragEnter事件:mimeData的Urls"));
    for(auto &iter:event->mimeData()->urls())
        ui->plainTextEdit->appendPlainText(iter.path());

    if(event->mimeData()->hasUrls()){
        QString filename=event->mimeData()->urls().at(0).fileName();
        QFileInfo fileInfo(filename);
        QString ex=fileInfo.suffix().toUpper();
        if(ex=="JPG")
            event->acceptProposedAction();
        else
            event->ignore();
    }
    else
        event->ignore();
}

void MainWindow::dropEvent(QDropEvent *event)
{
    QString filepath=event->mimeData()->urls().at(0).path();
    filepath=filepath.right(filepath.length()-1);
    QPixmap pixmap(filepath);
    ui->label->setPixmap(pixmap);
    event->accept();
}


Qt类库中的一些类实现了完整的拖放操作功能,例如QAbstractItemView等.这些类都有一个函数setDragEnabled,当设置为true时,组件就可以作为一个拖动点,具有默认的拖动操作.

下面是一个综合应用拖放的例子:
mainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGroupBox>
#include <QAbstractItemView>
#include <QLabel>
#include <QEvent>
#include <QKeyEvent>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_radListSource_clicked();

    void on_radListWidget_clicked();

    void on_radTreeWidget_clicked();

    void on_radTableWidget_clicked();

    void on_chkAcceptDrops_clicked(bool checked);

    void on_chkDragEnabled_clicked(bool checked);

    void on_comMode_currentIndexChanged(int index);

    void on_comAction_currentIndexChanged(int index);

private:
    Ui::MainWindow *ui;
    QAbstractItemView *m_itemView=nullptr;
    void refreshToUI(QLabel *curGroupBox);
    int getDropActionIndex(Qt::DropAction actionType);
    Qt::DropAction getDropActionType(int index);

    // QObject interface
public:
    virtual bool eventFilter(QObject *watched, QEvent *event) override;
};

#endif // MAINWINDOW_H

mainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

    ui->listSource->setAcceptDrops(true);
    ui->listSource->setDefaultDropAction(Qt::CopyAction);
    ui->listSource->setDragDropMode(QAbstractItemView::DragDrop);
    ui->listSource->setDragEnabled(true);

    ui->listWidget->setAcceptDrops(true);
    ui->listWidget->setDefaultDropAction(Qt::CopyAction);
    ui->listWidget->setDragDropMode(QAbstractItemView::DragDrop);
    ui->listWidget->setDragEnabled(true);

    ui->treeWidget->setAcceptDrops(true);
    ui->treeWidget->setDefaultDropAction(Qt::CopyAction);
    ui->treeWidget->setDragDropMode(QAbstractItemView::DragDrop);
    ui->treeWidget->setDragEnabled(true);
    ui->treeWidget->clear();

    ui->tableWidget->setAcceptDrops(true);
    ui->tableWidget->setDefaultDropAction(Qt::MoveAction);
    ui->tableWidget->setDragDropMode(QAbstractItemView::DragDrop);
    ui->tableWidget->setDragEnabled(true);

    ui->listSource->installEventFilter(this);
    ui->listWidget->installEventFilter(this);
    ui->treeWidget->installEventFilter(this);
    ui->tableWidget->installEventFilter(this);

    refreshToUI(ui->lbListSource);
}

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

void MainWindow::refreshToUI(QLabel *curGroupBox)
{
    ui->chkAcceptDrops->setChecked(m_itemView->acceptDrops());
    ui->chkDragEnabled->setChecked(m_itemView->dragEnabled());

    ui->comMode->setCurrentIndex((int)m_itemView->dragDropMode());
    int index=getDropActionIndex(m_itemView->defaultDropAction());
    ui->comAction->setCurrentIndex(index);

    QFont font=curGroupBox->font();
    font.setBold(false);
    ui->lbListSource->setFont(font);
    ui->lbListWidget->setFont(font);
    ui->lbTreeWidget->setFont(font);
    ui->lbTableWidget->setFont(font);
    font.setBold(true);
    curGroupBox->setFont(font);
}

int MainWindow::getDropActionIndex(Qt::DropAction actionType)
{
    switch(actionType){
    case Qt::CopyAction:
        return 0;
    case Qt::MoveAction:
        return 1;
    case Qt::LinkAction:
        return 2;
    case Qt::IgnoreAction:
        return 3;
    default:
        return 0;
    }
}

Qt::DropAction MainWindow::getDropActionType(int index)
{
    switch(index){
    case 0:
        return Qt::CopyAction;
    case 1:
        return Qt::MoveAction;
    case 2:
        return Qt::LinkAction;
    case 3:
        return Qt::IgnoreAction;
    default:
        return Qt::CopyAction;
    }

}

void MainWindow::on_radListSource_clicked()
{
    m_itemView=ui->listSource;
    refreshToUI(ui->lbListSource);
}


void MainWindow::on_radListWidget_clicked()
{
    m_itemView=ui->listWidget;
    refreshToUI(ui->lbListWidget);
}


void MainWindow::on_radTreeWidget_clicked()
{
    m_itemView=ui->treeWidget;
    refreshToUI(ui->lbTreeWidget);
}


void MainWindow::on_radTableWidget_clicked()
{
    m_itemView=ui->tableWidget;
    refreshToUI(ui->lbTableWidget);
}


void MainWindow::on_chkAcceptDrops_clicked(bool checked)
{
    m_itemView->setAcceptDrops(checked);
}


void MainWindow::on_chkDragEnabled_clicked(bool checked)
{
    m_itemView->setDragEnabled(checked);
}


void MainWindow::on_comMode_currentIndexChanged(int index)
{
    m_itemView->setDragDropMode((QAbstractItemView::DragDropMode)index);
}


void MainWindow::on_comAction_currentIndexChanged(int index)
{
    m_itemView->setDefaultDropAction(getDropActionType(index));
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if(event->type()!=QEvent::KeyPress)
        return QWidget::eventFilter(watched,event);
    QKeyEvent *keyEvent=static_cast<QKeyEvent*>(event);
    if(keyEvent->key()!=Qt::Key_Delete)
        return QWidget::eventFilter(watched,event);
    if(watched==ui->listSource)
        delete ui->listSource->takeItem(ui->listSource->currentRow());
    else if(watched==ui->listWidget)
        delete ui->listWidget->takeItem(ui->listWidget->currentRow());
    else if(watched==ui->treeWidget){
        QTreeWidgetItem *curItem=ui->treeWidget->currentItem();
        if(curItem->parent()!=nullptr)
            curItem->parent()->removeChild(curItem);
        else{
            int index=ui->treeWidget->indexOfTopLevelItem(curItem);
            ui->treeWidget->takeTopLevelItem(index);
        }
        delete curItem;
    }
    else if(watched==ui->tableWidget)
        delete ui->tableWidget->takeItem(ui->tableWidget->currentRow(),ui->tableWidget->currentColumn());
    return true;
}

posted @ 2024-03-26 22:37  Mesonoxian  阅读(141)  评论(0编辑  收藏  举报