问题
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