Ich habe ein Tool mit Hilfe eines benutzerdefinierten Widgets erstellt.
Dieses Widget passt so in das Hauptfenster
. Der Benutzer kann mit einem Klick auf eine Schaltfläche neue Instanzen eines benutzerdefinierten Widgets erstellen.
benutzerdefiniertes Widget:
class RenderWidget(QWidget):
def __init__(self, toolname, process_queue):
QWidget.__init__(self)
self.initSubject()
self.organize()
self.toolname = toolname
self.process_queue = process_queue
def initSubject(self):
self.script_dir = os.path.dirname(os.path.realpath(__file__))
self.scene_widget = uic.loadUi(os.path.join(self.script_dir, 'ui', 'test_widget.ui'))
self.scene_widget.pushButton_scenefile.clicked.connect(lambda x: self.open_file_name_dialog(x))
def organize(self):
grid = QGridLayout(self)
self.setLayout(grid)
grid.addWidget(self.scene_widget)
def open_file_name_dialog(self, x):
dialog = QFileDialog(
self,
'submit_render',
"path",
"*.ma",
# supportedSchemes=["file"],
options=QFileDialog.DontUseNativeDialog,
)
self.change_button_name(dialog)
dialog.findChild(QTreeView).selectionModel().currentChanged.connect(
lambda: self.change_button_name(dialog)
)
if dialog.exec_() == QDialog.Accepted:
filename = dialog.selectedUrls()[0]
filename = filename.toLocalFile()
self.scene_widget.lineEdit_scenefile.setText(filename)
if validate_path(self.toolname, filename):
self.process_queue.put((filename, _count))
def change_button_name(self, dialog):
for btn in dialog.findChildren(QPushButton):
if btn.text() == self.tr("&Open"):
QTimer.singleShot(0, lambda btn=btn: btn.setText("open"))
Haupt-Widget:
class MyAppView(QWidget):
def __init__(self, toolname, process_queue):
self.toolname = toolname
self.process_queue = process_queue
super(MyAppView, self).__init__()
self.initUi()
def initUi(self):
self.layoutV = QVBoxLayout(self)
self.area = QScrollArea(self)
self.area.setWidgetResizable(True)
self.scrollAreaWidgetContents = QWidget()
self.scrollAreaWidgetContents.setGeometry(0, 0, 200, 100)
self.layoutH = QHBoxLayout(self.scrollAreaWidgetContents)
self.layoutH_Button = QHBoxLayout(self.scrollAreaWidgetContents)
self.gridLayout = QGridLayout()
self.layoutH.addLayout(self.gridLayout)
self.area.setWidget(self.scrollAreaWidgetContents)
self.left_spacer = QSpacerItem(50, 10, QSizePolicy.Minimum)
self.center_spacer = QSpacerItem(100, 10, QSizePolicy.Minimum)
self.submit_button = UVPush("Submit")
self.cancel_button = UVPush("Cancel")
# Log text
self.output = QPlainTextEdit()
self.output.setFixedHeight(150)
self.output.setPlaceholderText('output..')
self.layoutH_Button.addSpacerItem(self.left_spacer)
self.layoutH_Button.addWidget(self.submit_button)
self.layoutH_Button.addSpacerItem(self.center_spacer)
self.layoutH_Button.addWidget(self.cancel_button)
self.layoutV.addWidget(self.area)
self.layoutV.addLayout(self.layoutH_Button)
self.layoutV.addWidget(self.output)
self.widget = RenderWidget(self.toolname, self.process_queue)
self.gridLayout.addWidget(self.widget)
self.setGeometry(700, 200, 350, 300)
Verfahren:
class ChildProc(Process):
def __init__(self, to_emitter, from_mother, daemon=True):
super(ChildProc, self).__init__()
self.daemon = daemon
self.to_emitter = to_emitter
self.data_from_mother = from_mother
self.maya_output = MayaOutput()
def run(self):
from python_library.maya_python import data_from_maya_scene
while True:
filename, count = self.data_from_mother.get()
print('+++ filename ', filename, count)
_cameras, _frames, _layers = data_from_maya_scene(filename)
self.maya_output.cameras = _cameras
self.maya_output.layers = _layers
self.maya_output.frames = _frames
self.maya_output.count = count
self.to_emitter.send(self.maya_output)
#TODO call signal slot to start stop loader
(Referenz: Wie signalisiert man Slots in einer GUI von einem anderen Prozess? )
Sender:
class Emitter(QThread):
ui_data_available = pyqtSignal(object) # Signal indicating new UI data is available.
def __init__(self, from_process):
super(Emitter, self).__init__()
self.data_from_process = from_process
def run(self):
while True:
try:
_object = self.data_from_process.recv()
except EOFError:
break
else:
self.ui_data_available.emit(_object)
Hauptfenster:
class CloudRenderView(QtWidgets.QMainWindow):
def __init__(self, toolname, child_process_queue, emitter):
QtWidgets.QMainWindow.__init__(self)
self.toolname = toolname
self.process_queue = child_process_queue
self.MyAppView = MyAppView(self.toolname, self.process_queue)
.
.
self.emitter = emitter
self.emitter.daemon = True
self.emitter.start()
# set window dimension
self.connections()
.
.
def connections(self):
.
.
self.emitter.ui_data_available.connect(self.update_ui)
.
.
def update_ui(self, maya_object):
count = maya_object.count
example_widget = self.MyAppView.gridLayout.itemAt(count).widget()
if 'Error' not in maya_object.cameras:
example_widget.scene_widget.textEdit_camera.setText('\n'.join([str(elem) for elem in maya_object.cameras]))
else:
example_widget.scene_widget.textEdit_camera.setHtml("<font color='red' size='2'><red>{}</font>".format('Error'))
if 'Error' not in maya_object.frames:
example_widget.scene_widget.lineEdit_frames.setText(maya_object.frames)
else:
example_widget.scene_widget.lineEdit_frames.setText('Error')
if 'Error' not in maya_object.layers:
example_widget.scene_widget.textEdit_render_layer.setText('\n'.join([str(elem) for elem in maya_object.layers]))
else:
example_widget.scene_widget.textEdit_render_layer.setHtml("<font color='red' size='2'><red>{}</font>".format('Error'))
Frage:
Eine Schaltfläche zur Auswahl einer Datei aus dem System wurde angeklickt. Diese ausgewählte Datei wird über eine Warteschlange an einen qprocess gesendet, und nach Abschluss der Verarbeitung sendet der Emitter über eine Pipe ein Signal an die Hauptbenutzeroberfläche.
Kommen wir zu der Frage, sagen wir, dass Daten für Widget 3 oder 4 eingegeben wurden. Nach dem Prozess werden die Daten immer an Widget Nr. 1 zurückgesendet.
So ordnen Sie es demselben Widget zu, aus dem es ausgewählt wurde.?
Lösung des Problems
Der Versuch, eine Antwort zu finden, die hilft, aber ohne Code und wenn Sie Ihren speziellen Ansatz kennen, ist es schwierig.
Ich gehe davon aus, dass Sie die Daten nicht an das richtige Widget senden, da Ihr Verweis auf dieses Widget falsch ist. Sie brauchen eine Möglichkeit, auf das neu erstellte Widget zu verweisen, und dafür gibt es im Allgemeinen zwei Möglichkeiten.
Speichern Sie einen Verweis auf das neue Widget an einem Ort, an dem Sie leicht darauf zugreifen können, z. B. eine self._second_widget
Variable oder eine Liste oder ein Wörterbuch von Variablen. Wenn Sie dann Daten an Ihr Widget senden, verwenden Sie diese Referenz.
Finden Sie das Widget im QGridLayout mit entsprechenden Aufrufen, die so etwas wie sein könnten.itemAtPosition(x,y).widget()
Hoffentlich hilft das - wenn Sie eine bessere Antwort wünschen, ist es eine gute Idee, Code zu posten.
Keine Kommentare:
Kommentar veröffentlichen