Collaptic
Collaptic

Reputation: 307

Simple PyQt Function Evaluator

I'm a beginner when it comes to GUIs in the python universe, and I'm trying to code a simple function evaluator for sin(x), cos(x), tan(x). Here is my code.

import matplotlib.pyplot as plt
import numpy as np
import sys
from PyQt4 import QtGui, QtCore


class Form(QtGui.QWidget) :
    def __init__(self):
        super(Form, self).__init__()

        layout = QtGui.QVBoxLayout(self)
        combo = QtGui.QComboBox()
        combo.addItem("Sin")
        combo.addItem("Cos")
        combo.addItem("Tan")

        parameter = QtGui.QLineEdit("np.linspace(lower,upper,dx)")
        parameter.selectAll()
        output = QtGui.QLineEdit("Output (Press Enter)")
        output.selectAll()

        layout.addWidget(combo)
        layout.addWidget(parameter)
        layout.addWidget(output)

        self.setLayout(layout)
        combo.setFocus()
        self.connect(output, QtCore.SIGNAL("returnPressed()"), self.updateUI) 
        self.setWindowTitle("Function Evaluator")

    def updateUI(self) :
        x = float(self.parameter_edit.text())
        f = str(eval(str(self.function_edit.text())))
        self.output_edit.setText(f)


app = QtGui.QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

How do I go about doing this? I have a dropdown for the specific functions, but don't really know how to do the evaluation of the function for the specific drop down function. Or how I go about actually evaluating the function itself with the x input, and having it output in my updateUI method.

Upvotes: 0

Views: 152

Answers (1)

Alexander Lutsenko
Alexander Lutsenko

Reputation: 2160

QComboBox's item can have a name and a content:

qCombo.addItem('Sin', 'np.sin')

Here's a way to get a content of the selected item:

content = qCombo.itemData(qCombo.currentIndex())

Bear in mind that in python2 returned content is wrapped in QVariant; we must unwrap it manually:

content = content.toString()

So, your code may look as follows:

import matplotlib.pyplot as plt
import numpy as np
import sys
from PyQt4 import QtGui, QtCore


class Form(QtGui.QWidget):
    def __init__(self):
        super(Form, self).__init__()

        self.func_selector = QtGui.QComboBox()
        self.func_selector.setFocus()
        self.func_selector.addItem("Sin", 'np.sin')
        self.func_selector.addItem("Cos", 'np.cos')
        self.func_selector.addItem("Tan", 'np.tan')

        self.parameter_edit = QtGui.QLineEdit("np.linspace(lower, upper, n)")

        self.output_edit = QtGui.QLineEdit("Output (Press Enter)")
        self.output_edit.returnPressed.connect(self.updateUI)

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.func_selector)
        layout.addWidget(self.parameter_edit)
        layout.addWidget(self.output_edit)

        self.setLayout(layout)
        self.setWindowTitle("Function Evaluator")

    def updateUI(self):
        # A dictionary of local variables that can be used by eval()
        locs = {'lower': 0, 'upper': 2*np.pi, 'n': 10}

        x = self.parameter_edit.text()

        # Get a content of the selected QComboBox's item
        f = self.func_selector.itemData(self.func_selector.currentIndex())
        # In python2 a QComboBox item's content is wrapped in QVariant, so we must unwrap it:
        if sys.version_info.major == 2:
            f = f.toString()

        y = eval('{}({})'.format(f, x), None, locs)
        self.output_edit.setText(str(y))

        # if the function returns multiple values, show a plot
        if isinstance(y, np.ndarray):
            x_eval = eval(str(x), None, locs)
            plt.plot(x_eval, y)
            plt.show()


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    form = Form()
    form.show()
    app.exec_()

Upvotes: 1

Related Questions