【问题标题】:Embed xterm into QWidget and communicate with it将 xterm 嵌入到 QWidget 中并与之通信
【发布时间】:2013-01-24 04:38:32
【问题描述】:

我想将xterm 嵌入到pyqt4 小部件中并与之通信。特别是我希望能够打印到它并在其上执行命令(这样它在执行命令后返回到正常的用户提示符,就像普通的 shell 一样)。考虑以下最小示例。我怎样才能让它发挥作用?

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import  sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *


class embedxterm(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self.setMinimumWidth(900)
        self.setMinimumHeight(400)
        self.process = QProcess(self)

        self.terminal = QWidget(self)
        self.terminal.setMinimumHeight(300)

        self.cmd1 = QPushButton('Command1',self)
        self.cmd2 = QPushButton('Command2',self)
        self.hello = QPushButton('Print Hello World',self)

        layout = QVBoxLayout(self)

        layoutH = QHBoxLayout(self)

        layoutH.addWidget(self.cmd1)
        layoutH.addWidget(self.cmd2)
        layoutH.addWidget(self.hello)


        layout.addLayout(layoutH)
        layout.addWidget(self.terminal)


        self.process.start(
            'xterm',['-into', str(self.terminal.winId())])

        self.cmd1.clicked.connect(self.Ccmd1)
        self.cmd2.clicked.connect(self.Ccmd2)
        self.hello.clicked.connect(self.Chello)

    def Ccmd1(self):
        self.process.write('ls -l')
        # Should execute ls -l on this terminal

    def Ccmd2(self):
        self.process.write('ping www.google.com')
        # should execute ping www.google.com on this terminal

    def Chello(self):
        self.process.write('Hello World')
        # should just print "Hello World" on this terminal

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = embedxterm()
    main.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python qt4 pyqt4 xterm terminal-emulator


    【解决方案1】:

    要将xterm 嵌入到您应该使用的一个窗口中:

    -into windowId 给定一个 X 窗口标识符(一个十进制整数),xterm 会将其顶级 shell 小部件重新设置为该窗口的父级。这是使用 将 xterm 嵌入到其他应用程序中。

    xterm 本身与启动的 shell(bash 等)对话。因此,您必须找到一种与启动的 shell 对话的方法。您可以通过-Sccn 标志将打开的文件描述符传递给xterm

    此选项允许 xterm 用作现有程序的输入和输出通道,有时用于专门的应用程序中

    所以,我认为您必须创建 bash、zsh 的实例,无论您想将命令发送到什么地方。然后将该子进程的 stdout/stderr fd 连接到您的 xterm 实例,并将标准输入连接到您的主程序,然后多路复用来自 xterm 的输入和您要发送到 bash 的命令(这样它们将被执行并被显示在 xterm)。

    bash ----------------------> xterm
        \--< your.py <----------/
    

    urxvt 的联机帮助页显示urxvt 有一些类似的开关:

    -嵌入windowid
    告诉 urxvt 将它的窗口嵌入到一个已经存在的窗口中, 这使应用程序能够轻松嵌入终端。 [ ... ] 这是一个简短的 Gtk2-perl sn-p 说明如何使用此选项(更长的 示例在 doc/embed 中):

    我的 $rxvt = new Gtk2::Socket;
    $rxvt->signal_connect_after (实现 => sub { 我的 $xid = $_[0]->window->get_xid;
    系统“urxvt -embed $xid &”;
    });

    -pty-fd 文件描述符
    告诉 urxvt 不要执行任何命令或创建新的 pty/tty 对,而是使用给定的文件描述符作为 tty 主机。如果您想将 urxvt 作为通用终端仿真器来驱动,而无需在其中运行程序,这将非常有用。

    下面是 perl 中的示例,说明如何使用此选项(更长的示例 > 在 doc/pty-fd 中):

    使用 IO::Pty;
    使用 Fcntl;

    我的 $pty = 新 IO::Pty;
    fcntl $pty,F_SETFD,0; # 清除关闭执行
    系统“urxvt -pty-fd”。 (文件号 $pty)。 "&";
    关闭 $pty;

    # 现在与 rxvt 通信
    我的 $slave = $pty->slave;
    while () { print $slave "得到\n" }

    要从 python 中打开 PTY,pty 模块看起来很有希望:http://docs.python.org/2/library/pty.html

    有趣的阅读:http://sqizit.bartletts.id.au/2011/02/14/pseudo-terminals-in-python/

    【讨论】:

    • 你能在我的帖子的最小示例中实现这一点吗?
    • 谢谢,但我没有拼凑起来。也许有人可以针对我的最小示例或至少在 pyqt4 上提供更多详细信息。
    • 我回答的哪一部分你不明白?
    • 老实说,我在问我的问题之前在谷歌上找到了你答案中的大部分信息。问题是我不知道如何将它组合在一起以及从哪里开始。所以我整理了一个最小的例子,只是问如何让它工作。如果我坚持使用 xterm,我认为您的答案中最相关的部分是首先将我的 python 应用程序连接到 bash 等。但是我不知道如何具体执行此操作(请参阅我的最小示例)。我还应该补充一点,我是一个绝对的 python pyqt4 初学者。
    • 不,因为我没有时间为你做这项工作。我仍然觉得你不理解我列出的概念。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多