2012-04-27 37 views
6

搜索這裏和其他放置像qtcentre我見過這個問題已經出現,但似乎無法得到它的工作。我有一個主窗口小部件了QSplitter其中包含兩個窗格小部件(從子類QFrame)。每個窗格都有一個菜單欄,具有相同的關聯質量控制/快捷方式QT - QAction :: eventFilter:模糊的快捷方式超負荷

我試過的ShortcutContexts所有組合與setShortcutContext()

WindowShortcutApplicationShortcut環境得到所需要的 「曖昧快捷超載」。

雖然WidgetShortcutWidgetWithChildrenShortcut都無能爲力。

如果我手動激活菜單,他們當然工作得很好。 我也嘗試着重於重載enterEvent()的父窗口小部件。

任何想法?

謝謝。

main.h
#include <QMainWindow> 
#include <QFrame> 

QT_BEGIN_NAMESPACE 
class QAction; 
class QMenu; 
class QHBoxLayout; 
class QSplitter; 
class QWidget; 
QT_END_NAMESPACE 

class Pane: public QFrame 
{ 
    Q_OBJECT 

    public: 
    Pane(QWidget* parent = 0); 

    protected: 
    void   enterEvent(QEvent *event); 
    void   leaveEvent(QEvent *event); 

    private: 
    void   createMenus(); 

    QMenuBar *  m_menuBar; 

    private Q_SLOTS: 
    void   split(); 
}; 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    MainWindow(); 

private: 
    void createActions(); 
    void createMenus(); 
    void setupUi(QMainWindow *MainWindow); 

    QMenu *fileMenu; 
    QAction *exitAct; 

    QWidget *centralwidget; 
    QHBoxLayout *horizontalLayout; 
    QSplitter *splitter; 
    QFrame *frame; 
    QFrame *frame_2; 
}; 

main.cpp中
#include <iostream> 
#include <QApplication> 
#include <QMainWindow> 
#include <QSplitter> 
#include <QFrame> 
#include <QMenuBar> 
#include <QBoxLayout> 
#include "main.h" 

Pane::Pane(QWidget* parent) : 
    QFrame(parent) 
{ 
    setFrameShape(QFrame::StyledPanel); 
    setFrameShadow(QFrame::Raised); 

    QVBoxLayout *layout = new QVBoxLayout; 
    QFrame::setLayout(layout); 

    m_menuBar = new QMenuBar; 
    QWidget *m_widget = new QWidget; 

    layout->addWidget(m_menuBar); 
    layout->addWidget(m_widget); 
    layout->setContentsMargins(2, 2, 2, 2); 

    show(); 

    createMenus(); 
} 

void 
Pane::enterEvent(QEvent *event) 
{ 
    std::cout << "enter" << std::endl; 
    setFocus(); 
    setStyleSheet("QFrame { border: 1px solid rgb(127, 127, 0); }"); 
    if (focusWidget()) 
     std::cout << "focuswidget = " << focusWidget()->objectName().toUtf8().constData() << std::endl; 
} 

void 
Pane::leaveEvent(QEvent *event) 
{ 
    std::cout << "leave" << std::endl; 
    clearFocus(); 
    setStyleSheet("QFrame { border: 1px solid rgb(64, 64, 64); }"); 
} 

void 
Pane::split() 
{ 
    std::cout << "split pane" << std::endl; 
} 

void 
Pane::createMenus() 
{ 
    QMenu *paneMenu = m_menuBar->addMenu(tr("&Pane")); 

    QAction *paneSplitAct = new QAction(tr("Split"), this); 
    paneSplitAct->setShortcut(Qt::Key_S); 
    paneSplitAct->setShortcutContext(Qt::WidgetWithChildrenShortcut); 
    paneSplitAct->setStatusTip(tr("Split Pane")); 
    connect(paneSplitAct, SIGNAL(triggered()), this, SLOT(split())); 
    paneMenu->addAction(paneSplitAct); 
} 

MainWindow::MainWindow() 
{ 
    setupUi(this); 

    createActions(); 
    createMenus(); 
} 

void MainWindow::createActions() 
{ 
    exitAct = new QAction(tr("E&xit"), this); 
    exitAct->setShortcuts(QKeySequence::Quit); 
    exitAct->setStatusTip(tr("Exit the application")); 
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); 
} 

void MainWindow::createMenus() 
{ 
    fileMenu = menuBar()->addMenu(tr("&File")); 
    fileMenu->addAction(exitAct); 
} 


void MainWindow::setupUi(QMainWindow *MainWindow) 
{ 
    if (MainWindow->objectName().isEmpty()) 
     MainWindow->setObjectName(QString::fromUtf8("MainWindow")); 

    MainWindow->resize(800, 600); 
    centralwidget = new QWidget(MainWindow); 
    centralwidget->setObjectName(QString::fromUtf8("centralwidget")); 
    horizontalLayout = new QHBoxLayout(centralwidget); 
    horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); 
    splitter = new QSplitter(centralwidget); 
    splitter->setObjectName(QString::fromUtf8("splitter")); 
    splitter->setOrientation(Qt::Horizontal); 

    frame = new Pane(splitter); 
    frame->setObjectName(QString::fromUtf8("frame")); 
    splitter->addWidget(frame); 

    frame_2 = new Pane(splitter); 
    frame_2->setObjectName(QString::fromUtf8("frame_2")); 
    splitter->addWidget(frame_2); 

    horizontalLayout->addWidget(splitter); 

    MainWindow->setCentralWidget(centralwidget); 

    QMetaObject::connectSlotsByName(MainWindow); 
} 

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 
    app.setOrganizationName("Trolltech"); 
    app.setApplicationName("Application Example"); 
    MainWindow mainWin; 
    mainWin.show(); 
    return app.exec(); 
} 

main.pro中
HEADERS  = main.h 
SOURCES  = main.cpp 
CONFIG  += no_keywords 

UPDATE:Pane::createMenus()結合到底添加一個addAction(paneSplitAct)呼叫與usin g Qt::WidgetShortcut上下文似乎給了我想要的。

從我所瞭解的文檔中,這應該是在小部件中創建一個上下文菜單。我似乎沒有得到一個(我承擔的鼠標右鍵單擊),但沒關係,因爲我不想要一個。仍然需要eventEvent()leaveEvent()覆蓋來正確設置焦點。

回答

1

AFAIK對於像這樣的大多數場景,設置WidgetShortcut的快捷方式是正確的。但問題在於你的重複動作是在菜單欄中,它不能有焦點(在傳統的小部件意義上),這就是爲什麼它沒有做任何事情。

將共享操作放入主窗口並使其成爲應用程序快捷方式可能更有意義。然後在動作觸發的主窗口插槽中找出哪個對象具有焦點並將命令推送到其上。

+0

因爲我在其構造函數中將'QAction'的父項設置爲'this',並且'WidgetShortcut'的文檔聲明「當它的父窗口小部件具有焦點時該快捷方式處於活動狀態」應該不行?事件如果'QAction'是'QMenubar'的一個孩子,那麼'WidgetWithChildrenShortcut'似乎可以工作。你的其他想法似乎可行,除了我會有多個窗格子類型,我寧願不必將所有可能的快捷方式添加到'MainWindow'類。謝謝! – user1360310 2012-04-28 00:19:48

4

我遇到了類似的問題:2個不同的小部件具有相同的操作快捷方式(小部件之間的不同操作)。只要其中一個小部件在應用程序中可見,一切都有效。只要兩者都可見,我就得到了這個「模糊快捷超載」的消息。

的解決方案是:這兩個動作的背景下,必須正確設置的Qt :: WidgetWithChildrenShortcut,然後它好工作 - 只是根據目前的工作重點。

如果只有一個動作有正確的情況下,一個與默認情況下得到觸發,並顯示該消息。

如果這兩個動作沒有上下文中設置(默認值),最後產生的行動被觸發和顯示的消息。

所以,如果你有一個快捷方式的任意位置添加一個動作,記得去思考正確的上下文並設置它,是限制性的!

0

該解決方案的工作很適合我,當菜單欄被禁用或不用於觸發行動的快捷方式。

程序添加快捷方式:

bool StingrayEditor::eventFilter(QObject* obj, QEvent* e) 
{ 
    switch (e->type()) { 
    case QEvent::Shortcut: { 
     QShortcutEvent* sev = static_cast<QShortcutEvent*>(e); 
     if (sev->isAmbiguous()) { 
      foreach(const auto& action, actions()) { 
       if (action->shortcut() == sev->key()) { 
        action->trigger(); // Trigger the action that matches the ambigous shortcut event. 
        return true; 
       } 
      } 
     } 
    } 
    // ... 
    default: break; 
    } 

    return false; 
} 

void StingrayEditor::add_shortcut(const QJsonObject& item_json) 
{ 
    QString item_path = item_json["path"].toString(); 
    QString shortcut = item_json["shortcut"].toString(); 
    if (!shortcut.isEmpty()) { 
     QKeySequence key_sequence = QKeySequence::fromString(shortcut); 
     QAction* shortcut_action = new QAction(item_path, this); 
     if (!key_sequence.isEmpty()) { 
      shortcut_action->setShortcut(key_sequence); 
      shortcut_action->setShortcutContext(Qt::ApplicationShortcut); 
     } 
     connect(shortcut_action, &QAction::triggered, this, [item_path]() 
     { 
      // Action to be executed 
     }); 

     // Add the action to the main window. 
     addAction(shortcut_action); 
    } 
} 

則需要使用shortcut_action->setShortcutContext(Qt::ApplicationShortcut);

然後你需要過濾器/監聽事件趕上QEvent::Shortcut是非常重要的

不要忘記事件,像這樣註冊:

qApp->installEventFilter(this);