PyQt5将命令传递给嵌入式终端“ urxvt”或“ xterm”

如何解决PyQt5将命令传递给嵌入式终端“ urxvt”或“ xterm”

我已经按照answer完成了对PyQt5应用程序的嵌入式终端。

现在,我想使用按钮向类似here的嵌入式终端发送命令。

例如:

Button_1 send "ifconfig",Button_2 send "ping 127.0.0.1". 

我的代码:

import sys
from PyQt5 import QtCore,QtWidgets
from PyQt5.QtWidgets import QPushButton


class EmbTerminal(QtWidgets.QWidget):
    def __init__(self,parent=None):
        super(EmbTerminal,self).__init__(parent)
        self.process = QtCore.QProcess(self)
        self.terminal = QtWidgets.QWidget(self)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.terminal)
        # Works also with urxvt:
        # self.process.start('urxvt',['-embed',str(int(self.winId()))])
        self.process.start('xterm',['-into',str(int(self.winId()))])
        # self.setFixedSize(640,480)

        button1 = QPushButton('ifconfig')
        layout.addWidget(button1)
        button1.clicked.connect(self.button_1_clicked)

        button2 = QPushButton('ping 127.0.0.1')
        layout.addWidget(button2)
        button2.clicked.connect(self.button_2_clicked)

    def button_1_clicked(self):
        print('send \"ifconfig\" to embedded termial')

    def button_2_clicked(self):
        print('send \"ping 127.0.0.1\" to embedded termial')

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

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

        tab_widget = QtWidgets.QTabWidget()
        lay.addWidget(tab_widget)

        tab_widget.addTab(EmbTerminal(),"EmbTerminal")
        tab_widget.addTab(QtWidgets.QTextEdit(),"QTextEdit")
        tab_widget.addTab(QtWidgets.QMdiArea(),"QMdiArea")


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

我该怎么办?

我已经尝试了其他answer(将另一个应用程序附加到PyQt5窗口)和answer(将命令传递给QProcess C ++而不是Python)

解决方法

一种可能的解决方案是使用tmux作为中介来发送命令:

import sys
import time
import uuid

from PyQt5 import QtCore,QtGui,QtWidgets

import gi

gi.require_version("Wnck","3.0")
from gi.repository import Wnck,Gdk


class TerminalContainer(QtWidgets.QTabWidget):
    def __init__(self,parent=None):
        super().__init__(parent)
        lay = QtWidgets.QVBoxLayout(self)
        lay.setContentsMargins(0,0)
        self.name_session = uuid.uuid4().hex

    def start(self):
        started,procId = QtCore.QProcess.startDetached(
            "xterm",["-e","tmux","new","-s",self.name_session],"."
        )
        if not started:
            QtWidgets.QMessageBox.critical(
                self,'Command "{}" not started!'.format(command),"Eh"
            )
            return
        attempts = 0
        while attempts < 10:
            screen = Wnck.Screen.get_default()
            screen.force_update()
            time.sleep(0.1)
            while Gdk.events_pending():
                Gdk.event_get()
            for w in screen.get_windows():
                print(attempts,w.get_pid(),procId,w.get_pid() == procId)
                if w.get_pid() == procId:
                    win32w = QtGui.QWindow.fromWinId(w.get_xid())
                    widg = QtWidgets.QWidget.createWindowContainer(win32w)
                    self.layout().addWidget(widg)
                    self.resize(500,400)
                    return
            attempts += 1
        QtWidgets.QMessageBox.critical(
            self,"Window not found","Process started but window not found"
        )

    def stop(self):
        QtCore.QProcess.execute("tmux",["kill-session","-t",self.name_session])

    def send_command(self,command):
        QtCore.QProcess.execute(
            "tmux",["send-keys",self.name_session,command,"Enter"]
        )


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

        self.ifconfig_btn = QtWidgets.QPushButton("ifconfig")
        self.ping_btn = QtWidgets.QPushButton("ping")
        self.terminal = TerminalContainer()

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

        lay = QtWidgets.QGridLayout(central_widget)
        lay.addWidget(self.ifconfig_btn,0)
        lay.addWidget(self.ping_btn,1)
        lay.addWidget(self.terminal,1,2)

        self.terminal.start()

        self.resize(640,480)

        self.ifconfig_btn.clicked.connect(self.launch_ifconfig)
        self.ping_btn.clicked.connect(self.launch_ping)

    def launch_ifconfig(self):
        self.terminal.send_command("ifconfig")

    def launch_ping(self):
        self.terminal.send_command("ping 8.8.8.8")

    def closeEvent(self,event):
        self.terminal.stop()
        super().closeEvent(event)


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

将上面接受的答案与此answer结合后,我已经完成了必填项。

这是在Python2-Qt5上运行的组合代码

import sys
from PyQt5 import QtCore,QtWidgets
import gi
import uuid
gi.require_version('Wnck','3.0')
from gi.repository import Wnck,Gdk
import time

class Container(QtWidgets.QTabWidget):
    def __init__(self):
        QtWidgets.QTabWidget.__init__(self)
        self.embed('xterm')

    def embed(self,*args):
        self.name_session = uuid.uuid4().hex
        proc = QtCore.QProcess()
        proc.setProgram(command)
        proc.setArguments(args)

        started,"."
        )
        if not started:
            QtWidgets.QMessageBox.critical(self,"Eh")
            return
        attempts = 0
        while attempts < 10:
            screen = Wnck.Screen.get_default()
            screen.force_update()
            # do a bit of sleep,else window is not really found
            time.sleep(0.1)
            # this is required to ensure that newly mapped window get listed.
            while Gdk.events_pending():
                Gdk.event_get()
            for w in screen.get_windows():
                print(attempts,w.get_pid() == procId)
                if w.get_pid() == procId:
                    self.window = QtGui.QWindow.fromWinId(w.get_xid())
                    proc.setParent(self)
                    win32w = QtGui.QWindow.fromWinId(w.get_xid())
                    win32w.setFlags(QtCore.Qt.FramelessWindowHint)
                    widg = QtWidgets.QWidget.createWindowContainer(win32w)

                    self.addTab(widg,command)
                    self.resize(500,400) # set initial size of window
                    return
            attempts += 1
        QtWidgets.QMessageBox.critical(self,'Window not found','Process started but window not found')

    def stop(self):
        QtCore.QProcess.execute("tmux","Enter"]
        )

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

        self.ifconfig_btn = QtWidgets.QPushButton("ifconfig")
        self.ping_btn = QtWidgets.QPushButton("ping")
        self.terminal = Container()

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

        lay = QtWidgets.QGridLayout(central_widget)
        lay.addWidget(self.ifconfig_btn,2)

        self.resize(640,event):
        self.terminal.stop()
        super().closeEvent(event)

app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-