PyQt:QPushButton 是否可以分配一个 QAction?

5
使用 Python 3.2x 和 PyQT 4.8x:
我初始化了一个操作,并将其分配给一个菜单项:
self.__actionOpen = QtGui.QAction(self.__mw)
self.__actionOpen.setObjectName("actionOpen")
self.__actionOpen.setText("OpenFile")
QtCore.QObject.connect(self.__actionOpen, QtCore.SIGNAL("triggered()"), self.__accessFile)
self.__menuFile.addAction(self.__actionOpen)

运行良好 - 菜单项显示为“打开文件”,并且已调用操作信号/插槽。

我尝试使用QPushButton - 同一个QAction对象:

self.__buttonFile.addAction(self.__actionOpen)

Nothing: 按钮上没有标题,点击时不会发生任何事情。

QButton无法执行操作(addAction调用没有报错)吗?或者我的代码有问题?也许“triggered()”信号不适用于与QPushButton交互的操作?

4个回答

11
您无法按照您想要的方式将 QAction 分配给 QPushButtonQPushButton 没有重新定义 addAction,因此行为来自于 QWidget.addAction,该操作会将动作添加到按钮的上下文菜单中。
但是,您可以使用setDefaultAction 将动作分配给 QToolButton,这将更改按钮标题并在单击时触发动作。
或者,您仍然可以手动子类化 QPushButton 并添加一个 setDefaultAction 方法,该方法会根据动作更改按钮中的所有内容(标题、工具提示等),并将相关的按钮信号连接到动作槽。

1
好的 - 我没有问关于 QToolButton,而是 QPushButton,它没有 setDefaultAction 方法,正如解释器告诉我的那样。所以听起来你是在说我正在做的事情不会起作用。这并不是一个很重要的问题,我更喜欢工具栏/按钮。我只是在尝试编写一些简单的 GUI 代码,没有使用 QtDesigner 的帮助。 - Vector
@Mikey,这就是我想说的。但你仍然可以手动完成,通过子类化QPushButton并添加一个setDefaultAction方法,根据操作更改按钮中的所有内容,并将相关按钮的信号连接到操作的插槽。 - alexisdm
明白了。我根据您的评论编辑了您的答案并接受了它。 - Vector

4

添加一个动作不会在按钮被点击时“运行”该动作,这是设计上的考虑。

如果您想要重用或引用QAction的行为,则可以将QPushButton的clicked()信号连接到QAction的trigger()上:

QtCore.QObject.connect(self.__menuFile,
                       QtCore.SIGNAL("clicked()"),
                       self.__actionOpen.trigger)

这样,每当单击self.menuFile按钮时,将触发self.__actionOpen操作。


不错的想法,尽管从OP的代码来看,我猜第一个参数应该是self.__buttonFile而不是self.__menuFile。无论如何,在PyQt5中,这可以进一步简化为self.__buttonFile.clicked.connect(self.__actionOpen.trigger) - f0xdx

1

我对这个问题的解决方案:

from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QPushButton

class QActingPushButton(QPushButton):
    """QPushButtons don't interact with their QActions. This class triggers
    every `QAction` in `self.actions()` when the `clicked` signal is emitted.
    https://dev59.com/JHLYa4cB1Zd3GeqPXnD6#16703358
    """
    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.clicked.connect(self.trigger_actions)

    @pyqtSlot()
    def trigger_actions(self) -> None:
        for act in self.actions():
            act.trigger()

-1
你可以创建一个PushButtonAction:
h文件:
#ifndef PUSHBUTTONACTION_H
#define PUSHBUTTONACTION_H
#include <QAction>
#include <QPushButton>

class PushButtonAction: public QPushButton
{
    Q_OBJECT
public:
    PushButtonAction(QAction *action, QWidget *parent = 0);
};

#endif // PUSHBUTTONACTION_H

cpp 文件:

#include "pushbuttonaction.h"

PushButtonAction::PushButtonAction(QAction *action, QWidget *parent):
    QPushButton(parent)
{
    setIcon(action->icon());
    setText(action->text());
    connect(this, SIGNAL(clicked()), action, SLOT(trigger()));
}

我认为这个类应该被称为“ActionPushButton”,因为它是从一个按钮派生出来的,所以它是一个按钮,而不是一个动作。 - Tilman Vogel
3
我会尽力为您翻译:我正在对这个答案进行负面评价:这个问题是关于 Python 和 PyQt 的,而不是 C++。 - Vector
2
@Vector:即使您不了解C++,也很容易理解这个概念。 - antoyo
4
@antoyo - 我了解C++,但如果问题是关于Python的,你不能用C++来回答。那样是错误的。你应该将它翻译成Python。这个问题的标题是PyQt。 - Vector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接