Pyside2 QAction 会自动触发一次,但不会在用户单击菜单时触发

Pyside2 QAction triggers once automatically but not when user clicks the menu

我使用 qt designer 创建了一个简单的 GUI,并将其导入到我的 python 项目中。主 window 出现,menus/buttons 响应,但我无法将我的 QActions 连接到自定义函数(虽然我为按钮做了它,但它有效)。奇怪的是,当我 运行 应用程序时,我的自定义函数 (on_action_clicked) 被调用一次,但当我单击工具栏的菜单项或图标时却没有调用(我尝试连接两者)。下面是测试代码。我错过了什么吗?

imbrowser3d.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>851</width>
    <height>649</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QGraphicsView" name="gv_image">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>0</y>
      <width>731</width>
      <height>501</height>
     </rect>
    </property>
   </widget>
   <widget class="QScrollBar" name="sb_index">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>510</y>
      <width>701</width>
      <height>20</height>
     </rect>
    </property>
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
   </widget>
   <widget class="QScrollBar" name="sb_zeta">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>530</y>
      <width>701</width>
      <height>20</height>
     </rect>
    </property>
    <property name="orientation">
     <enum>Qt::Horizontal</enum>
    </property>
   </widget>
   <widget class="QLabel" name="label_index">
    <property name="geometry">
     <rect>
      <x>700</x>
      <y>510</y>
      <width>55</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>index</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_zeta">
    <property name="geometry">
     <rect>
      <x>700</x>
      <y>530</y>
      <width>55</width>
      <height>16</height>
     </rect>
    </property>
    <property name="text">
     <string>zeta</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>740</x>
      <y>500</y>
      <width>93</width>
      <height>28</height>
     </rect>
    </property>
    <property name="text">
     <string>PushButton</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>851</width>
     <height>26</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuFile">
    <property name="title">
     <string>File</string>
    </property>
    <addaction name="menu_open"/>
    <addaction name="menu_save"/>
    <addaction name="menu_load"/>
   </widget>
   <addaction name="menuFile"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <widget class="QToolBar" name="action_toolbar">
   <property name="windowTitle">
    <string>toolBar</string>
   </property>
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
   <addaction name="action_save_state"/>
  </widget>
  <action name="menu_open">
   <property name="text">
    <string>Open</string>
   </property>
  </action>
  <action name="menu_save">
   <property name="icon">
    <iconset>
     <normaloff>ui_icons/save_icon.png</normaloff>ui_icons/save_icon.png</iconset>
   </property>
   <property name="text">
    <string>Save state</string>
   </property>
  </action>
  <action name="menu_load">
   <property name="text">
    <string>Load state</string>
   </property>
  </action>
  <action name="action_save_state">
   <property name="icon">
    <iconset>
     <normaloff>ui_icons/save_icon.png</normaloff>ui_icons/save_icon.png</iconset>
   </property>
   <property name="text">
    <string>Save state</string>
   </property>
   <property name="toolTip">
    <string>Save state</string>
   </property>
  </action>
 </widget>
 <resources/>
 <connections/>
</ui>

main.py

import sys
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QAction, QPushButton,  QFileDialog
from PySide2.QtCore import QFile, QObject


class UiMainWindow(QObject):

    def __init__(self, ui_file, parent=None):
        super(UiMainWindow, self).__init__(parent)
        ui_file = QFile(ui_file)
        ui_file.open(QFile.ReadOnly)

        loader = QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()

        self.btn = self.window.findChild(QPushButton, 'pushButton')
        self.btn.clicked.connect(self.on_btn_clicked)
        self.action_save = self.window.findChild(QAction, 'action_save_state')
        self.action_save.triggered.connect(self.on_action_clicked('action clicked'))
        self.window.show()

    def on_action_clicked(self, txt):
        print(txt)

    def on_btn_clicked():
        print('button clicked')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = UiMainWindow('imbrowser3d.ui')
    sys.exit(app.exec_())

您有 2 个错误:

  • on_btn_clicked 是 class 的一个方法,因此它的第一个参数必须是实例,即 self.

  • 连接与函数的名称没有评估,在你的情况下插槽 on_action_clicked 你正在评估它,所以你在开始时打印它,因为它在那里有 2 种可能的解决方案:使用部分或使用 lambda 函数。


    self.btn = self.window.findChild(QPushButton, 'pushButton')
    self.btn.clicked.connect(self.on_btn_clicked)
    self.action_save = self.window.findChild(QAction, 'action_save_state')
    self.action_save.triggered.connect(partial(self.on_action_clicked, 'action clicked'))
    # self.action_save.triggered.connect(lambda: self.on_action_clicked('action clicked')) # use lambda function
    self.window.show()

def on_action_clicked(self, txt):
    print(txt)

def on_btn_clicked(self):
    print('button clicked')