1

I build a lot of very basic QT repetitive programs at work with QT python then compile them with py2exe. These are used by my coworkers at controllers for another program. I am wonder how I could build a python interpreter that would convert simple commands into actual python code similar to the way Processing converts a simplified code into java.

For example the "simple code" file may read:

slider('Distance', 'dist', 50, 100, 'int')
button('Apply Changes', 'apply')

which I would then interpret into a pyQT program form using types below:

slider(label, name, min, max, type)
button(label, name)

These would all be written to new python file, which when run would generate the appropriate form. The part I am stuck on is how to interpret the "simple code" into python code.

Thanks in advance


Solution #1

The code below is uses the regex and split idea by SPEN-zar to identify the widget type, then parse the inputs to generate the necessary outputs. Obviously, this will be expanded upon to generate real pyQT file, but this is the basic demonstrates the basic logic.

Thank you for the help.

import re

input = ["slider('Distance', 'dist', 50, 100, 'int')", "button('Apply Changes', 'apply')"]

pattern = r"([a-z]+)\s*\((.*)\)"
rexp = re.compile(pattern)

for line in input:
    content = rexp.findall(line)
    if content[0][0] == 'slider':
        params = content[0][1].split(',')
        name = params[0]
        label = params[1]
        minimum = float(params[2])
        maximum = float(params[3])
        print 'Slider Type: name-%s, label-%s, min-%f, max-%f' % (name, label, minimum, maximum)
    elif content[0][0] == 'button':
        params = content[0][1].split(',')
        name = params[0]
        label = params[1]
        print 'Button Type: name-%s, label-%s' % (name, label)
    else:
        print 'This widget type is not recognized'

Solution #2

After doing further research into blender's suggestion, I have modified the code below that uses a class to define a button. This class can then be easily added to the form as many times as needed. By building classes for all the types needed it would be easy to easy generate forms as well maintain and add to the library.

from PyQt4 import QtGui, QtCore
import sys

class Main(QtGui.QMainWindow):
    def __init__(self, parent = None):
        super(Main, self).__init__(parent)

        # main button
        self.addButton = QtGui.QPushButton('button to add other widgets')
        self.addButton.clicked.connect(self.addWidget)

        # scroll area widget contents - layout
        self.scrollLayout = QtGui.QFormLayout()

        # scroll area widget contents
        self.scrollWidget = QtGui.QWidget()
        self.scrollWidget.setLayout(self.scrollLayout)

        # scroll area
        self.scrollArea = QtGui.QScrollArea()
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setWidget(self.scrollWidget)

        # main layout
        self.mainLayout = QtGui.QVBoxLayout()

        # add all main to the main vLayout
        self.mainLayout.addWidget(self.addButton)
        self.mainLayout.addWidget(self.scrollArea)

        # central widget
        self.centralWidget = QtGui.QWidget()
        self.centralWidget.setLayout(self.mainLayout)

        # set central widget
        self.setCentralWidget(self.centralWidget)

    def addButton(self):
        self.scrollLayout.addRow(Test())


class Test(QtGui.QWidget):
  def __init__( self, parent=None):
      super(Test, self).__init__(parent)

      self.pushButton = QtGui.QPushButton('I am in Test widget')
      self.pushButton.clicked.connect(self.testPush)

      layout = QtGui.QHBoxLayout()
      layout.addWidget(self.pushButton)
      self.setLayout(layout)

  def testPush(self):
      print "The test button was pushed!"



app = QtGui.QApplication(sys.argv)
myWidget = Main()
for i in xrange(5):
    myWidget.addButton()
myWidget.show()
app.exec_()
rgathmann
  • 75
  • 5
  • 3
    Why don't you just make your own high-level library on top of PyQt4 and use that instead? It'll be more maintainable than generating Python source code. – Blender Mar 14 '13 at 03:32
  • Well I am not stuck on everything. I have the pyQT down, I just need to know the best way to interpret a line like this: slider(attributes) – rgathmann Mar 14 '13 at 03:36
  • Blender, after doing more research, I can now see the value of your approach. By following this example [link](http://stackoverflow.com/questions/8651742/dynamically-adding-and-removing-widgets-in-pyqt), I can see how you would dynamically add widgets to a form by writing classes in a library. – rgathmann Mar 14 '13 at 05:39

1 Answers1

0

Have you tried just parsing it into a .ui format? That is XML, which is pretty straightforward.

Whichever output format you prefer, try PLY for the lexing and parsing. Otherwise, just use a regular expression to search for the substring with "(" ")" surrounding it and use .split(',') to get the arguments. That's my take.

Spen-ZAR
  • 818
  • 6
  • 19
  • Ok, this seems like the answer I was looking for, both of those methods would let me read line by line and interpret the simple code and generate the more complex code I need. Thanks. – rgathmann Mar 14 '13 at 03:49