After successfully implementing OpenOPC to simulate field devices for our factory acceptance testing, I needed a clean way to write to the OPC Server without having to use the Kepware interface to force bits and values. After searching for a suitable UI for Python I landed on PyQT from Riverbank Computing. I am always cautious of webpages that appear to have been last updated in the 90's, but this one seems pretty legitimate. I installed PyQT4 and had no issues with it on Windows Server 2003. It was easy to build a self contained UI with PyQT. The trouble I had was getting the UI events to be read in my python code. Starting with PyQT4 all of the Python code is external to the UI. If the UI needs to be updated it can be recompiled without interfering with the main program. This is my first Python application so I had to read up on slots. The buttons and widgets on the UI can be tied to slots. In the main program I define the slots. After searching a while I came across this answer on stackoverflow. The gist is that each action associated with each object on the UI can be tied to a slot. Then in the main program you define the slot within the class you define for the UI. Here is some example code that shows the UI class in this case 'MyForm' and within that class I have defined 'slot1'. Now whenever slot1 is called from the UI the action I defined is taken. I added a push button and named it 'pushButton'. I tied the release() action to slot1 in PyQT and call the function 'action1' whenever the button is released. Now two things happen when I release pushButton. The first is the slot1 function is called and the second is the action1 function is called.
Here is the complete code that goes along with the UI.
class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
# Here, you should call the inherited class' init, which is QDialog
QtGui.QDialog.__init__(self, parent)
# Usual setup stuff
self.ui = Ui_Form()
self.ui.setupUi(self)
# Use new style signal/slots
self.ui.pushButton.released.connect(self.action1)
# Other things...
def slot1(self):
print 'Slot Working'
def action1(self):
print 'Action Working'#-------------------------------------------------------------------------------
# Name: module1
# Purpose:
#
# Author: Scada
#
# Created: 17/05/2012
# Copyright: (c) Scada 2012
# Licence: <your licence>
#-------------------------------------------------------------------------------
import sys
from PyQt4.QtCore import *
from button import *
class MyPopupDialog(QtGui.QDialog):
def __init__(self, parent=None):
pass
# Regular init stuff...
# and other things you might want
class MyForm(QtGui.QWidget):
def __init__(self, parent=None):
# Here, you should call the inherited class' init, which is QDialog
QtGui.QDialog.__init__(self, parent)
# Usual setup stuff
self.ui = Ui_Form()
self.ui.setupUi(self)
# Use new style signal/slots
self.ui.pushButton.released.connect(self.action1)
# Other things...
def slot1(self):
print 'Slot Working'
def action1(self):
print 'Action Working'
def popup(self):
self.dialog = MyPopupDialog()
# For Modal dialogs
self.dialog.exec_()
# Or for modeless dialogs
# self.dialog.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp= MyForm()
myapp.show()
sys.exit(app.exec_())