I have this very basic application that intends to evaluate given Python code on one textEdit
component and show results on the other one.
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()
This works well so far you don't ask for input values. Say you run the script from the console with python samplegui.py
, if you happen to type something like this in the first text box:
a = 3
print 5 + a
b = input()
print 1 + b
and then push Evaluate
, the application expects a value input from the console. After put some value and press enter it continues and evaluates correctly.
What a I want to achieve is to redirect the stdin
to a component that I can manipulate from within the GUI
itself.
How can I do that? Ideally I would like to do it in the Python interpreter style, where the output and input happens interactively. Another option could be to handle/capture somehow the signal when the application is waiting for input and show an input dialog.
EDIT:
It turned out that it was easier than I thought. Here you can see a version of the script with sys.stdin
intercepted with a QInputDialog
so the user can input values from 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()