通过GUI重定向标准输入
我有一个非常简单的应用程序,它的目的是在一个 textEdit
组件中评估给定的 Python 代码,并在另一个组件中显示结果。
import sys
from PyQt4 import QtGui
from cStringIO import StringIO
class SampleGUI(QtGui.QWidget):
def __init__(self):
super(SampleGUI, self).__init__()
self.initGUI()
def initGUI(self):
self.code = QtGui.QTextEdit()
self.result = QtGui.QTextEdit()
btn = QtGui.QPushButton('Evaluate')
btn.clicked.connect(self.evaluate)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(self.code)
vbox.addWidget(btn)
vbox.addWidget(self.result)
self.setLayout(vbox)
self.show()
def evaluate(self):
source_code = str(self.code.toPlainText())
old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
exec source_code
sys.stdout = old_stdout
self.result.setText(redirected_output.getvalue())
def main():
app = QtGui.QApplication([])
s = SampleGUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
到目前为止,这个功能运行得很好,只要你不需要输入值。比如说,你从控制台运行这个脚本,输入 python samplegui.py
,如果你在第一个文本框中输入类似这样的内容:
a = 3
print 5 + a
b = input()
print 1 + b
然后点击 Evaluate
,这个应用程序会期待你在控制台中输入一个值。你输入一些值并按下回车后,它就会继续并正确评估。
我想要实现的是将 stdin
重定向到一个我可以在 GUI
内部操作的组件。
我该怎么做呢?理想情况下,我希望能像在 Python 解释器中那样,输入和输出是互动的。另一种选择是以某种方式处理或捕捉当应用程序等待输入时的信号,并显示一个输入对话框。
编辑:
结果发现这比我想的要简单。这里你可以看到一个版本的脚本,它用 QInputDialog
拦截了 sys.stdin
,这样用户就可以从 GUI
输入值。
import sys
from PyQt4 import QtGui
from cStringIO import StringIO
class InputGUI():
def __init__(self, parentWidget):
self.parentWidget = parentWidget
def readline(self):
text, ok = QtGui.QInputDialog.getText(self.parentWidget, 'Introduce value', 'Value:')
if ok:
return str(text)
else:
return ''
class SampleGUI(QtGui.QWidget):
def __init__(self):
super(SampleGUI, self).__init__()
self.initGUI()
def initGUI(self):
self.code = QtGui.QTextEdit()
self.result = QtGui.QTextEdit()
btn = QtGui.QPushButton('Evaluate')
btn.clicked.connect(self.evaluate)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(self.code)
vbox.addWidget(btn)
vbox.addWidget(self.result)
self.setLayout(vbox)
self.show()
def evaluate(self):
source_code = str(self.code.toPlainText())
streams = sys.stdin, sys.stdout
sys.stdin = InputGUI(self)
redirected_output = sys.stdout = StringIO()
exec source_code
sys.stdin, sys.stdout = streams
self.result.setText(redirected_output.getvalue())
def main():
app = QtGui.QApplication([])
s = SampleGUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()