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

丶灬走出姿态 提交于 2021-02-05 11:50:10

问题


I've created a simple GUI using qt designer and imported it into my python project. The main window comes up, and the menus/buttons are responsive, but I cannot manage to connect my QActions to custom functions (I did it for buttons though, and it works). The weird thing is that my custom function (on_action_clicked) is called once when I run the application, but not when I click on the menu items or icons of the toolbar (I tried connecting both). Below are the test codes. Am I missing something?

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_())

回答1:


You have 2 errors:

  • on_btn_clicked is a method of the class so it must have as the first parameter the instance, that is, self.

  • the connection is with the name of the function without evaluating, in your case the slot on_action_clicked you are evaluating it, so you are getting it printed at the beginning, for it there are 2 possible solutions: use partial or use a lambda function.


    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')


来源:https://stackoverflow.com/questions/52163305/pyside2-qaction-triggers-once-automatically-but-not-when-user-clicks-the-menu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!