Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用PyQt GUI中嵌入的终端_Python_User Interface_Terminal_Pyqt - Fatal编程技术网

Python 如何使用PyQt GUI中嵌入的终端

Python 如何使用PyQt GUI中嵌入的终端,python,user-interface,terminal,pyqt,Python,User Interface,Terminal,Pyqt,有一个可以通过Bash终端使用的现有环境和框架,我想围绕它制作一个GUI。我想到的是以下流程: 在Bash会话中,将设置框架环境。这将导致在会话中设置从环境变量到身份验证的所有内容 运行pythongui脚本是为了包装现有会话并使后续步骤更容易运行 GUI出现,一面显示嵌入式终端中的Bash会话,另一面显示一组按钮,对应于可以在现有框架环境中运行的各种命令 可以在GUI中按下按钮,从而运行某些Bash命令。运行结果将显示在嵌入式终端中 创建这样一个GUI的好方法是什么?我意识到与现有环境交互

有一个可以通过Bash终端使用的现有环境和框架,我想围绕它制作一个GUI。我想到的是以下流程:

  • 在Bash会话中,将设置框架环境。这将导致在会话中设置从环境变量到身份验证的所有内容
  • 运行pythongui脚本是为了包装现有会话并使后续步骤更容易运行
  • GUI出现,一面显示嵌入式终端中的Bash会话,另一面显示一组按钮,对应于可以在现有框架环境中运行的各种命令
  • 可以在GUI中按下按钮,从而运行某些Bash命令。运行结果将显示在嵌入式终端中
创建这样一个GUI的好方法是什么?我意识到与现有环境交互的想法可能很棘手。如果特别棘手,我愿意在GUI会话中重新创建环境。在任何情况下,GUI如何与嵌入式终端交互。当按下GUI按钮时,如何在嵌入式终端中运行和显示命令

GUI(具有嵌入式终端)的基本启动如下:

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

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

class embeddedTerminal(QWidget):

    def __init__(self):

        QWidget.__init__(self)
        self.resize(800, 600)
        self.process  = QProcess(self)
        self.terminal = QWidget(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.terminal)
        self.process.start(
            'xterm',
            ['-into', str(self.terminal.winId())]
        )

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = embeddedTerminal()
    main.show()
    sys.exit(app.exec_())
比如说,按下GUI中的按钮后,我如何在这个嵌入式终端上运行
top

如果它必须是一个真正的终端和一个真正的shell(而不仅仅是接受一行输入,运行一些命令,然后显示输出)——tmux呢

您可以使用类似于
tee
的方法将输出返回到程序中

请注意,tmux会话可能会在程序运行期间持续存在,因此您需要了解它是如何工作的以及如何控制它的

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

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

class embeddedTerminal(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._processes = []
        self.resize(800, 600)
        self.terminal = QWidget(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.terminal)
        self._start_process(
            'xterm',
            ['-into', str(self.terminal.winId()),
             '-e', 'tmux', 'new', '-s', 'my_session']
        )
        button = QPushButton('List files')
        layout.addWidget(button)
        button.clicked.connect(self._list_files)

    def _start_process(self, prog, args):
        child = QProcess()
        self._processes.append(child)
        child.start(prog, args)

    def _list_files(self):
        self._start_process(
            'tmux', ['send-keys', '-t', 'my_session:0', 'ls', 'Enter'])

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

这里还有一点:

如果其他人发现了这个问题,请对它进行一些轻微的修改,以关闭tmux会话(如果它存在),因为前一个会话在退出时没有关闭它。还为PySide2设置了它

现在它只需要调整大小支持

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import psutil
import os
import platform
import sys
from pathlib import Path
from subprocess import call

from PySide2 import QtCore
from PySide2.QtCore import *
from PySide2.QtWidgets import QWidget, QVBoxLayout, QPushButton, QApplication

platform = platform.system()
print(str(platform))

term_dir = Path(os.path.abspath(os.path.dirname(__file__))) / 'terminus'

if platform == 'Windows':
    term_bin = str(term_dir) + '/' + str(platform.lower()) + '/' + 'terminus.exe'

elif platform == 'Linux':
    term_bin = str(term_dir) + '/' + str(platform.lower()) + '/' + 'terminus'

print(term_bin)


class embeddedTerminal(QWidget):

    def __init__(self):
        QWidget.__init__(self)
        self._processes = []
        self.resize(800, 600)
        self.terminal = QWidget(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.terminal)
        self._stop_process()
        self._start_process(
            'xterm',
            ['-into', str(self.terminal.winId()),
             '-e', 'tmux', 'new', '-s', 'my_session']
        )
        button = QPushButton('List files')
        layout.addWidget(button)
        button.clicked.connect(self._list_files)

    def _start_process(self, prog, args):
        child = QProcess()
        self._processes.append(child)
        child.start(prog, args)

    def _list_files(self):
        self._start_process(
            'tmux', ['send-keys', '-t', 'my_session:0', 'ls', 'Enter'])

    @classmethod
    def _stop_process(self):
        call(["tmux", "kill-session", "-t", "my_session"])


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


你能再解释一下为什么你想用这种方式而不是传统的GUI来解决问题吗?是为了节省编写GUI的工作,还是为了节省更改现有命令的工作?或者两者都有,或者别的什么?这些命令是交互式的,还是在没有进一步用户输入的情况下(在输入命令行并点击return之后)运行到完成?你说的是“bash命令”--我猜事实上某些进程需要运行,而bash除了作为运行它们的一种方式之外并没有真正密切地参与其中?嘿,谢谢你考虑这一点。基本上,有一个庞大的基础设施,用户可以通过终端与之交互。典型的用法可能涉及调用多个命令,这些命令对应于多种语言的脚本,大多数使用复杂的命令行参数。我知道自动创建将在终端上运行的各种命令的方法,我想看看是否可以通过在终端上添加一个GUI(带有可用于自动生成和运行某些命令的按钮)来有效地简化用户的操作。实际上,我想拥有一个交互式终端,并将其连接到终端上(或将其固定在)一个简单的PyQt GUI上,该GUI也可以与终端交互(导入命令并运行它们并获得命令的输出)因此,它实际上需要是一个终端+ BASH,而不是一个你自己实现的简单的行编辑器——在这种情况下,你可以自己使用Q进程或子进程来运行命令。管道和作业控制使用得多吗?如果只有少数情况,考虑用一些新的命令来包装这些情况,这样就不会有零的情况了。结束?与我在上面的评论中的提问不同,只是为了展示各种可能性/灵感(我不是建议你使用这个或做任何类似的事情):(这是一个组合的shell和终端,用python编写,因此可以扩展以与之交互)我终于完成了对这个问题的思考。非常感谢您对这个问题的所有非常有用的指导。很可能Python中新构造的终端是一个更干净的解决方案,但tmux方法基本上正是我想要的。谢谢!:)如果不清楚,答案顶部的注释并不是将这个答案与椰子壳进行比较——而是将它与更简单的想法进行比较,即用户在行编辑中键入命令,让程序在按enter键时运行该命令(比如说,使用QProcess),然后只在文本区域中打印输出。这个想法类似于浏览器使用JS外壳所做的事情(但不必那么花哨)。非常感谢。