How to embed gnuplot qt in pyqt?

The gnuplot terminal qt accepts an widget id (http://www.bersch.net/gnuplot-doc/complete-list-of-terminals.html#qt). How can I use this id number to embed gnuplot qt window into an pyqt5 application? I would appreciate a minimal working code.

A similar question for c++ has no answer (Embed gnuplot inside existing QtWidget).

For comparison, with tcl/tk (program wish) + x11 terminal the following works

set unit [open "| gnuplot 2>@1" w+]  
frame .x11 -bg "white" -width 640 -height 450
button .b1 -text "some button"
pack .x11 .b1

puts $unit "set term x11 window '[winfo id .x11]'"
flush $unit

puts $unit "pl sin(x)"
flush $unit

Upvotes: 0

Views: 612

Answers (1)

eyllanesc
eyllanesc

Reputation: 244033

You can use a QProcess to send the commands, and in those commands pass the window id to it:

import sys
from functools import cached_property

from PyQt5 import QtCore, QtWidgets


class GnuPlotManager(QtCore.QObject):
    @cached_property
    def process(self):
        qprocess = QtCore.QProcess()
        qprocess.setProgram("gnuplot")
        return qprocess

    def start(self):
        self.process.start()

    def send_command(self, command):
        self.process.write((command + "\n").encode())


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)

        button = QtWidgets.QPushButton("Send Command")

        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.command_le)
        lay.addWidget(button)
        lay.addWidget(self.container)

        button.clicked.connect(self.handle_clicked)

        self.gnuplot_manager.start()
        self.gnuplot_manager.send_command("set terminal qt")
        wid = int(self.container.winId())
        self.gnuplot_manager.send_command(f"set term x11 window '{wid:x}'")

        self.gnuplot_manager.send_command("clear")

        self.command_le.setText("pl sin(x)")

        self.resize(640, 480)

    @cached_property
    def container(self):
        return QtWidgets.QWidget()

    @cached_property
    def command_le(self):
        return QtWidgets.QLineEdit()

    @cached_property
    def gnuplot_manager(self):
        return GnuPlotManager()

    def handle_clicked(self):
        self.gnuplot_manager.send_command(self.command_le.text())
        self.updateGeometry()


def main(args):
    app = QtWidgets.QApplication(args)

    w = MainWindow()
    w.show()

    ret = app.exec_()
    sys.exit(ret)


if __name__ == "__main__":
    main(sys.argv)

enter image description here

Upvotes: 2

Related Questions