如何解决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 举报,一经查实,本站将立刻删除。