PyQt5 将命令传递给嵌入式终端 'urxvt' 或 'xterm'
PyQt5 pass command to embedded terminal 'urxvt' or 'xterm'
我已经按照此 .
完成了 PyQt5 应用程序的嵌入式终端
现在我想使用按钮向这个嵌入式终端发送类似的命令。
例如:
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_())
我该怎么做?
我已经尝试过其他 (attach another application to PyQt5 window) and 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, 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", "-t", 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, 0)
lay.addWidget(self.ping_btn, 0, 1)
lay.addWidget(self.terminal, 1, 0, 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_())
将 above-accepted 答案与此 结合后,我已经完成了我的要求。
这是组合代码,运行 Python2-Qt5
import sys
from PyQt5 import QtCore, QtGui, 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, command, *args):
self.name_session = uuid.uuid4().hex
proc = QtCore.QProcess()
proc.setProgram(command)
proc.setArguments(args)
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()
# 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, 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", ["kill-session", "-t", self.name_session])
def send_command(self, command):
QtCore.QProcess.execute(
"tmux", ["send-keys", "-t", self.name_session, command, "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, 0, 0)
lay.addWidget(self.ping_btn, 0, 1)
lay.addWidget(self.terminal, 1, 0, 1, 2)
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)
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
我已经按照此
现在我想使用按钮向这个嵌入式终端发送类似
例如:
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_())
我该怎么做?
我已经尝试过其他
一种可能的解决方案是使用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, 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", "-t", 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, 0)
lay.addWidget(self.ping_btn, 0, 1)
lay.addWidget(self.terminal, 1, 0, 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_())
将 above-accepted 答案与此
这是组合代码,运行 Python2-Qt5
import sys
from PyQt5 import QtCore, QtGui, 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, command, *args):
self.name_session = uuid.uuid4().hex
proc = QtCore.QProcess()
proc.setProgram(command)
proc.setArguments(args)
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()
# 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, 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", ["kill-session", "-t", self.name_session])
def send_command(self, command):
QtCore.QProcess.execute(
"tmux", ["send-keys", "-t", self.name_session, command, "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, 0, 0)
lay.addWidget(self.ping_btn, 0, 1)
lay.addWidget(self.terminal, 1, 0, 1, 2)
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)
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())