2013-04-17 207 views
1

在我正在构建的应用程序中,我实现了一个全局撤销/重做系统,可通过常规快捷键Ctrl-Z和Ctrl-Shift-Z访问该系统。QLineEdit撤销/重做功能干扰全局撤销/重做

我也使用QLineEdit字段,它们有自己的撤消/重做功能。无论何时触发editFinished事件(按下输入或焦点丢失),都会创建全局撤消事件。但是,如果您只需键入几个字母,然后按Ctrl-Z,该字段将捕获按键,使用其自己的撤消系统撤销上次编辑,然后不会按下按键。

我想实现什么是这样的:

  1. 当QLineEdit的具有焦点和Ctrl-Z被按下,但也有在QLineEdit的无编辑撤消(当undoAvailable()为假)我希望小部件忽略按键并将其传递给其父母。

  2. 当撤销可用并且用户在窗口小部件有焦点时(IE按下工具栏上的按钮)调用撤销/重做动作时,我希望它们被传递到此窗口小部件。

任何想法?

回答

1

从您的标签,我猜你使用Python包装到Qt。我的例子有C++代码,但仍然适用于Python版本的Qt,如果这是你使用的。

它看起来像QObject :: eventFilter可能会做你正在寻找。您需要创建一个带有eventFilter(QObject * sender,QEvent * event)的类作为成员。对于你想跟踪的每个QLineEdit,执行一些操作,比如'myLineEdit-> setEventFilter(eventFilterClassInstance);'

这使您可以拦截您安装了事件过滤器的每个对象的所有QEvent。您可以在多个对象上安装事件过滤器,然后通过设置它们的QObject开始过滤。最重要的是,如果您希望将事件作为正常处理,则可以从eventFilter返回true;如果不应该看到该事件,则可以返回false。

既然你有兴趣做撤销/重做,你可以做isUndoAvailable()来检查它是否是。

代码可能是这样的:

MyEventFilterClass::eventFilter(QObject *object, QEvent *event) 
{ 
    if (object == someLineEdit) { 
     if (event->type() == QEvent::KeyPress) { 
      QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); 

      int key = keyEvent->key(); 
      int mods = keyEvent->modifiers(); 
      if (mods == Qt::ShiftModifier && key == Qt::Key_Z) { 
       if (someLineEdit->undoAvailable()) { 
        someLineEdit->undo(); 
        return true; 
       } 
       else { 
        /* There are a few options here: */ 
        /* If you have a list of known parents, you could iter over them, and pick the right one. */ 
        /* Or maybe you want the event filter to emit a signal for the parents to see. */ 
        return true; 
       } 
      } 
     } 
    } 
} 

对于第二部分,你可以使用的QApplication :: focusWidget,看看当前具有焦点(我没有测试这个虽然)。我有一个主窗口,它查看两个可能的窗口来确定哪个窗口具有焦点,并将撤消操作应用于具有焦点的窗口。

我意识到你的问题很古老,但我希望这有助于。

+1

谢谢!我可以通过事件过滤器来捕捉按键,但我仍然无法让它们冒泡到主应用程序。我可以传递一个引用并明确地调用它,但我仍然想知道是否有更好的方法:) –