0

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

3
  • c++ question has answer - the first comment Commented May 3, 2021 at 12:47
  • @mugiseyebrows Technically not an answer but a comment Commented May 3, 2021 at 12:49
  • But how does it look in pyqt? Commented May 3, 2021 at 12:49

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

22 Comments

Thanks for the reply. Looks good. Yet, I get ImportError: cannot import name 'cached_property'.
@Friedrich What version of python do you use? If you use a version lower than python 3.8 then you must install backports.cached-property: python -m pip install backports.cached-property and change from functools import cached_property to from backports.cached_property import cached_property
I have Python 3.6.9. The cached_property error is gone with your help. The x11 window however is not drawn into the qt app (maybe too fast?). Will it work also with qt terminal?
@Friedrich What do you mean by qt terminal? Have you pressed the button?
gnuplot's qt terminal is described in bersch.net/gnuplot-doc/complete-list-of-terminals.html#qt. Then in your code set term x11 window '{wid:x}' likely should be replaced by set term qt widget '{wid:x}'
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.