将xterm嵌入QWidget并与之通信

时间:2013-02-08 12:02:17

标签: python qt4 pyqt4 xterm terminal-emulator

我想将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_())

1 个答案:

答案 0 :(得分:4)

要将xterm嵌入您的某个窗口,您应该使用:

  

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

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

  

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

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

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

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

  

-embed windowid
  告诉urxvt将其窗口嵌入已存在的窗口,   这使应用程序可以轻松嵌入终端。   [...]   这是一个简短的Gtk2-perl片段,说明了如何使用此选项(更长时间   示例在doc / embed中:

     

my $ rxvt = new Gtk2 :: Socket;
  $ rxvt-&gt; signal_connect_after(realize =&gt; sub {      我的$ xid = $ _ [0] - &gt; window-&gt; get_xid;
     system“urxvt -embed $ xid&amp;”;
  });

  

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

     

以下是perl中的一个示例,说明了如何使用此选项(较长的示例&gt;位于doc / pty-fd中):

     

使用IO :: Pty;
  使用Fcntl;

     

my $ pty = new IO :: Pty;
  fcntl $ pty,F_SETFD,0; #clear close-on-exec
  系统“urxvt -pty-fd”。 (fileno $ pty)。 “&安培;”;
  关闭$ pty;

     

#现在与rxvt通信   我的$ slave = $ pty-&gt;奴隶;
  while(){print $ slave“got \ n”}

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

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