2

I have created instance of QAction inside QGraphicsView child class and connected it to my slot in the same class.

QAction *action   = new QAction(tr("New"), this);
action->setObjectName("addStopAction");
action->setShortcut(QKeySequence(Qt::ControlModifier | Qt::Key_N));
connect(action, SIGNAL(triggered()), this, SLOT(addNew()));
addAction(action);

Slot is a function creating new instance of QGraphicsItem on scene assigned to QGraphicsView.

void MyGraphicsView::addNew() {
    // Insert new item at cursor position
}

I also add this action to a QMenu which serves as my class context menu.

QMenu *contextMenu = new QMenu(this);
contextMenu->addAction(action);

Everything works fine. When I press Command/Ctrl + N new item is created at cursor position. But when I right-click and select action from context menu I want new item to be created at menu positon.

I can, of course, do some little hack to flag if SLOT was called after contextMenuEvent or something like that, but what I would like to know is:

Is there any way to find out what made QAction emit its triggered() signal inside connected SLOT? That way I could handle when I should place new item at cursor position and when at context menu position inside SLOT implementation.

4

5 に答える 5

4

もちろん、接続されたSLOT内でどの信号が放出されるかを知ることができます。

QObject :: sender()を使用するだけです。あなたの場合:

void MyGraphicsView::addNew() {
    QAction* pAction = qobject_cast<QAction*>(sender());
    Q_ASSERT(pAction);
    // do something with pAction
}
于 2013-01-20T17:21:57.813 に答える
1

QAction オブジェクトに含めることができるカスタム データを使用できると思います。コンテキスト メニューを作成するときに設定できます。

void showContextMenu(const QPoint &pos)
{
    ...
    action->setData(pos);
    ...
}

関数では、addNew()データが存在するかどうかを確認し、最後にリセットします。

void addNew()
{
    QPoint pos;
    QPoint posFromAction = action->data()->toPoint();
    if (posFromAction.isNull())
    {
        pos = QCursor::pos(); ///< pos will be current cursor's position
    }
    else
    {
        pos = posFromAction; ///< pos will be menu's position
    }

    doYourStuffAt(pos)

    action->setData(QPoint()); ///< reset action's data
}
于 2013-01-18T12:43:36.003 に答える
1

メニューを次のような関数に接続することで、同様のものを管理しましたconnect (menu, SIGNAL( triggered(QAction*) ), this, SLOT( menuAction_triggered(QAction*) ));

コンテキストメニューを実行するQMenu::exec(QPoint)と、アクションへのポインターが返されるため、追加の関数/スロットは必要ない場合があります。

アクションの名前をそのテキストで確認しQAction::text()たり、アドレスを比較してポインターをどこかに保存したかどうかを確認したりできます。

スーロン ザイ

于 2013-01-18T09:01:42.703 に答える
1

customContextMenuRequested シグナルによって呼び出される関数で self.sender() を参照できます。

self.tree1.customContextMenuRequested.connect(self.menu1pop)  # rightclick menu signal

...

def menu1pop(self, pos):

    widget = self.sender()

    item = widget.itemAt(pos)
    if item is None: return            # only show contextmenu if on an item
    self.setProperty("mywidget", widget)  # pass current widget 
    self.menu1.popup(QCursor.pos())    # show menu at right click cursor position

self.sender() はウィジェット オブジェクトを返すので、ウィジェット オブジェクトをプロパティ内に設定できます。

次に、アクション関数が呼び出されたときに、プロパティを読み取ってウィジェット オブジェクトを呼び出すことができます。

widget = self.property("mywidget")

ちょっとしたハックですが、アクションがどのウィジェットから呼び出されたかを知るためのシンプルで信頼できる方法です。

于 2020-02-19T00:36:24.073 に答える
-1

呼び出しを受信するスロットでQObject::sender()を使用できる場合があります。ただし、アクションではこれを試していません。提案された「ハック」(スコープクラスを使用して実際に非常にうまく実装できる)よりもおそらく少し醜いです。

于 2013-01-17T22:20:30.390 に答える