Python QT findChildren does not find any children from UI file

半腔热情 提交于 2020-06-20 05:04:06

问题


I have a UI file like this

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>RoverPlanner</class>
 <widget class="QWidget" name="RoverPlanner">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>752</width>
    <height>555</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>RoverPlanner</string>
  </property>
  <widget class="QWidget" name="horizontalLayoutWidget_6">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>10</y>
     <width>641</width>
     <height>501</height>
    </rect>
   </property>
   <layout class="QHBoxLayout" name="hl_rover_planner">
    <item>
     <layout class="QVBoxLayout" name="vl_path_config">
      <item>
       <layout class="QHBoxLayout" name="hl_rover_select">
        <item>
         <widget class="QLabel" name="lbl_rover">
          <property name="text">
           <string>Rover : </string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QComboBox" name="cb_rover">
          <item>
           <property name="text">
            <string>Husky</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>ArgoJ5</string>
           </property>
          </item>
          <item>
           <property name="text">
            <string>Husky (Simulated)</string>
           </property>
          </item>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="hl_path_creator">
        <item>
         <widget class="QLabel" name="lbl_path_creator">
          <property name="text">
           <string>Path Creator</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QPushButton" name="btn_add_to_path">
          <property name="text">
           <string>Add to path</string>
          </property>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="hl_segment_options">
        <item>
         <layout class="QVBoxLayout" name="vl_segment_type">
          <item>
           <widget class="QRadioButton" name="radio_circle">
            <property name="text">
             <string>Circle</string>
            </property>
            <property name="checked">
             <bool>true</bool>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QRadioButton" name="radio_line">
            <property name="text">
             <string>Line</string>
            </property>
           </widget>
          </item>
         </layout>
        </item>
        <item>
         <layout class="QVBoxLayout" name="vl_segment_extra_options">
          <item>
           <widget class="QCheckBox" name="chk_backwards">
            <property name="text">
             <string>Backwards</string>
            </property>
           </widget>
          </item>
          <item>
           <widget class="QCheckBox" name="chk_clockwise">
            <property name="text">
             <string>Clockwise</string>
            </property>
            <property name="checked">
             <bool>true</bool>
            </property>
           </widget>
          </item>
         </layout>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="hl_radius">
        <item>
         <widget class="QLabel" name="lbl_radius">
          <property name="text">
           <string>Circle Radius (m)</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QDoubleSpinBox" name="spin_radius">
          <property name="singleStep">
           <double>0.010000000000000</double>
          </property>
          <property name="value">
           <double>1.000000000000000</double>
          </property>
         </widget>
        </item>
       </layout>
      </item>
      <item>
       <layout class="QHBoxLayout" name="hl_arc_angle">
        <item>
         <widget class="QLabel" name="lbl_arc_angle">
          <property name="text">
           <string>Arc Angle (rad)</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QDoubleSpinBox" name="spin_arc_angle">
          <property name="decimals">
           <number>5</number>
          </property>
          <property name="singleStep">
           <double>0.010000000000000</double>
          </property>
          <property name="value">
           <double>0.785400000000000</double>
          </property>
         </widget>
        </item>
       </layout>
      </item>
     </layout>
    </item>
    <item>
     <layout class="QVBoxLayout" name="vl_segments">
      <item>
       <widget class="QLabel" name="lbl_path">
        <property name="text">
         <string>Paths</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QTreeView" name="tree_paths"/>
      </item>
      <item>
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <widget class="QPushButton" name="btn_save_paths">
          <property name="text">
           <string>Save Paths</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QPushButton" name="btn_load_paths">
          <property name="text">
           <string>Load Paths</string>
          </property>
         </widget>
        </item>
       </layout>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

And some Python code below, which is for an RQT ROS plugin.


import os
import rospy
import rospkg
from PySide2.QtWidgets import QTreeView, QPushButton, QFileDialog
from python_qt_binding import loadUi

from qt_gui.plugin import Plugin
from python_qt_binding.QtWidgets import QWidget
from argparse import ArgumentParser

def get_file():
    print("Hello World!")
    dlg = QFileDialog()
    dlg.setFileMode(QFileDialog.AnyFile)
    dlg.setFilter("XML files (*.xml)")

    if dlg.exec_():
        filenames = dlg.selectedFiles()
        f = open(filenames[0], 'r')

        with f:
            data = f.read()
            # self.contents.setText(data)


class RoverPlanner(Plugin):
    def __init__(self, context):
        super(RoverPlanner, self).__init__(context)
        self.setObjectName('RoverPlanner')
        parser = ArgumentParser()
        parser.add_argument("-q", "--quiet", action="store_true",
                            dest="quiet",
                            help="Put plugin in silent mode")
        args, unknowns = parser.parse_known_args(context.argv())
        if not args.quiet:
            print('arguments: ', args)
            print('unknowns: ', unknowns)

        self.widget = QWidget()
        ui_file = os.path.join(rospkg.RosPack().get_path('cuarl-rover-planner'), 'resource', 'rover_planner_widget.ui')
        loadUi(ui_file, self.widget)
        self.widget.setObjectName('RoverPlannerUI')
        # Show widget.windowTitle on left-top of each plugin (when
        # it's set in widget). This is useful when you open multiple
        # plugins at once. Also if you open multiple instances of your
        # plugin at once, these lines add number to make it easy to
        # tell from pane to pane.
        if context.serial_number() > 1:
            self.widget.setWindowTitle(self.widget.windowTitle() + (' (%d)' % context.serial_number()))
        # Add widget to the user interface
        context.add_widget(self.widget)
        self.tree_paths = self.widget.findChild(QTreeView)
        self.btn_load_paths = self.widget.findChildren(QPushButton)
        print(self.tree_paths)
        print(self.btn_load_paths)

    def shutdown_plugin(self):
        # TODO unregister all publishers here
        pass

    def save_settings(self, plugin_settings, instance_settings):
        # TODO save intrinsic configuration, usually using:
        # instance_settings.set_value(k, v)
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        # TODO restore intrinsic configuration, usually using:
        # v = instance_settings.value(k)
        pass

According to the documentation, it seems that my code should find these children. But the output of this code is

('arguments: ', Namespace(quiet=False))
('unknowns: ', [])
None
[]

I don't know if I'm not using the findChildren/findChild functions correctly or there's something that I am missing


回答1:


I ever encountered a similar problem and the cause was that the library used some wrapper like python_qt_binding but another part of the code used PyQt5 or PySide2. Why does that happen? because wrappers create new classes that use the same code base but in the end they are different classes.

My recommendation is that if you are going to use python_qt_binding then no longer use pyqt5 or pyside2 directly but rather the wrapper, in your case you should use the following:

import os

from argparse import ArgumentParser

import rospy
import rospkg

from qt_gui.plugin import Plugin

from python_qt_binding.QtWidgets import QWidget, QTreeView, QPushButton, QFileDialog
from python_qt_binding import loadUi

# ....


来源:https://stackoverflow.com/questions/62139551/python-qt-findchildren-does-not-find-any-children-from-ui-file

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