2012-04-27 35 views
6

ここではqtcentreのように配置されています。この問題が発生していますが、動作していないようです。私は(QFrameのサブクラス)2つのペインのウィジェットが含まれていQSplitterメインウィンドウウィジェットを持っています。各ペインには、同一の関連付けを持つメニューバーがあります。QActions/ShortcutsQT - QAction :: eventFilter:あいまいなショートカットオーバーロード

私はsetShortcutContext()ShortcutContextsのすべての組み合わせを試してみました。

WindowShortcutApplicationShortcutはコンテキストが期待される "あいまいなショートカットの過負荷" を与えます。

WidgetWithChildrenShortcutWidgetShortcutものの両方が何もしません。

手動でメニューを有効にすると、もちろん正常に動作します。 私はまた、オーバーロードされた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)コールを追加します私たちと一緒にg Qt::WidgetShortcutコンテキストは、私が欲しいものを私に与えるようです。

私がドキュメントを理解しているので、これはウィジェットのコンテキストメニューを作成することになっています。私は1つ(右マウスクリック私が仮定)を取得しているようには表示されませんが、私は1つをしたくないので、それは大丈夫です。フォーカスを正しく設定するには、eventEvent()leaveEvent()のオーバーライドが必要です。

答えて

1

AFAIKショートカットコンテキストをWidgetShortcutに設定するのがこのようなシナリオの場合、正しいことです。しかし、問題は重複したアクションが(従来のウィジェットの意味で)フォーカスを持つことができないメニューバーにあることで、何もしないのです。

共有アクションをメインウィンドウに配置し、アプリケーションのショートカットにする方が適切な場合があります。次に、アクションがトリガするメインウィンドウスロットで、どのオブジェクトにフォーカスがあるかを確認し、その上にコマンドを押します。

+0

私はコンストラクタで 'this'に' QAction'の親を設定しています。 'WidgetShortcut'のドキュメントでは"親ウィジェットにフォーカスがあるときにショートカットが有効です "と言っても問題ありませんか?イベント 'QAction'が' QMenubar'の子であった場合、 'WidgetWithChildrenShortcut'が動作するように見えます。あなたの他のアイデアは、私が複数のペインのサブタイプを持つことを除いて実行可能であると思われ、 'MainWindow'クラスに可能なすべてのショートカットを追加する必要はありません。ありがとう! – user1360310

4

私は同じような問題を抱えています:2つの異なるウィジェットは同じアクションのショートカットを持っていました(ウィジェット間で異なるアクション)。ウィジェットのうちの1つだけがアプリケーションに表示されていれば、すべてが機能しました。両方が見えるとすぐに、私はこの "あいまいなショートカットオーバーロード"メッセージを得ました。

解決策は次のとおりです。両方のアクションのコンテキストをQt :: WidgetWithChildrenShortcutに正しく設定する必要があります。

アクションが1つだけ正しいコンテキストを持つ場合、デフォルトコンテキストのものがトリガーされ、メッセージが表示されます。

両方のアクションにコンテキストが設定されていない(デフォルト)場合、最後に作成されたアクションがトリガーされ、メッセージが表示されます。

ショートカットが付いたアクションをどこにでも追加する場合は、正しいコンテキストについて考えて設定してください。

0

このソリューションは、メニューバーが無効になっているか使用されていないときに、ショートカットでアクションをトリガするのに効果的でした。ショートカットを追加するには

ルーチン:

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); 
    } 
} 

あなたが次にあなたがQEvent::Shortcutをキャッチするイベントをリッスン/フィルタリングする必要がありますshortcut_action->setShortcutContext(Qt::ApplicationShortcut);

を使用することが重要である:

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; 
} 

このようなイベントに登録することを忘れないでください:

qApp->installEventFilter(this);

関連する問題