Python system windows form

Overview

When developing GUI applications in python for Windows, standard python library choices are limiting and do not provide the same quality of experience as applications developed with Visual Studio, especially when bundled together with 3rd party WinForms or WPF such as DevExpress, As a result, python developers typically turn to Visual Studio and IronPython when developing for Windows. However, there is an alternative.

Python.Net

Python.Net( http://pythonnet.sourceforge.net/ ), built by Brian Lloyd is a lightweight, yet powerful package that enables CPython to load and interact with CLR based packages/libraries. It is fairly robust, performant and supports most CLR constructs and data types. In the simplest form, the following coding snippet demonstrates power and capability of Python.Net. You can download Python.Net here( http://www.lfd.uci.edu/~gohlke/pythonlibs/ )

Building a WinForms application

With python.net configured, we can now build a basic Winforms application running from CPython. First let’s use Visual Studio to build a basic form and compile it into an clr assembly. For below example, I created a form called SimpleForm in SimpleForm namespace and packaged it inside SimpleForm.dll. The form has text field called textBox and a button called btn_sayit . The following python code can then be used launch the form and handle click event on btn_sayit to print contents of textBox to the console.

Читайте также:  Python tkinter label get text

To simplify the python interface, I’ve set Modifier as public on textBox and btn_sayit widgets, this is not strictly necessary as you can also get access to them using form.Controls collection, but it makes for simpler and cleaner interface

Defining a UI Framework

To keep GUI Development more pythonic and UnitTestable, we can formally define Model View and Presenter python classes which would decouple WinForms code from the application and create a classical UI segregation of responsibilities.

With above structure in place, all business logic is performed in the model that is completely independent of the view and, therefore, can be unit tested and developed separately from WinForms components. Furthermore, presenter is injected with a python object wrapping a WinForms view which can be easily substituted with a stub or a mock for unit testing purposes.

Above pattern is an extension of a Passive View Pattern described by Martin Fowler http://martinfowler.com/eaaDev/PassiveScreen.html

Handling real-time updates

Источник

IronPython: A Quick WinForms Introduction

A few months ago I wrote up an article on using PyTools, Visual Studio, and Python all together. I received some much appreciated positive feedback for it, but really for me it was about exploring. I had dabbled with Python a few years back and hadn’t really touched it much since. I spend the bulk of my programming time in Visual Studio, so it was a great opportunity to try and bridge that gap when looking at something like IronPython.

I had an individual contact me via the Dev Leader Facebook group that had come across my original article. However, he wanted a little bit more out of it. Since I had my initial exploring out of the way, I figured it was probably worth trying to come up with a semi-useful example. I could get two birds with one stone here–Help out at least one person, and get another blog post written up!

The request was really around taking the output from a Python script and being able to display it in a WinForm application. I took it one step further and created an application that either lets you choose a Python script from your file system or let you type in a basic script directly on the form. There isn’t any fancy editor tools on the form, but someone could easily take this application and extend it into a little Python editor if they wanted to.

Leveraging IronPython

In my original PyTools article, I mention how to get IronPython installed into your Visual Studio project. In Visual Studio 2012 (and likely a very similar approach for other versions of Visual Studio), the following steps should get you setup with IronPython in your project:

  • Open an existing project or start a new one.
  • Make sure your project is set to be at least .NET 4.0
    • Right click on the project within your solution explorer and select “Properties”
    • Switch to the “Application” tab.
    • Under “Target framework”, select “.NET Framework 4.0”.
    var py = Python.CreateEngine(); py.Execute("your python code here");

    And there you have it. If it seems easy, that’s because it is. But what about the part about getting the output from Python? What if I wanted to print something to the console in Python and see what it spits out? After all, that’s the goal I was setting out to accomplish with this article. If you try the following code, you’ll notice you see a whole lot of nothing:

    var py = Python.CreateEngine(); py.Execute("print('I wish I could see this in the console. ')");

    What gives? How are we supposed to see the output from IronPython? Well, it all has to do with setting the output Stream of the IronPython engine. It has a nice little method for letting you specify what stream to output to:

    var py = Python.CreateEngine(); py.Runtime.IO.SetOutput(yourStreamInstanceHere);

    In this example, I wanted to output the stream directly into my own TextBox . To accomplish this, I wrote up my own little stream wrapper that takes in a TextBox and appends the stream contents directly to the Text property of the TextBox. Here’s what my stream implementation looks like:

    private class ScriptOutputStream : Stream < private readonly TextBox _control; public ScriptOutputStream(TextBox control) < _control = control; >public override bool CanRead < get < return false; >> public override bool CanSeek < get < return false; >> public override bool CanWrite < get < return true; >> public override long Length < get < throw new NotImplementedException(); >> public override long Position < get < throw new NotImplementedException(); >set < throw new NotImplementedException(); >> public override void Flush() < >public override int Read(byte[] buffer, int offset, int count) < throw new NotImplementedException(); >public override long Seek(long offset, SeekOrigin origin) < throw new NotImplementedException(); >public override void SetLength(long value) < throw new NotImplementedException(); >public override void Write(byte[] buffer, int offset, int count) < _control.Text += Encoding.GetEncoding(1252).GetString(buffer, offset, count); >>

    Now while this isn’t pretty, it serves one purpose: Use the stream API to allow binary data to be appended to a TextBox. The magic is happening inside of the Write() method where I take the binary data that IronPython will be providing to us, convert it to a string via code page 1252 encoding, and then append that directly to the control’s Text property. In order to use this, we just need to set it up on our IronPython engine:

    var py = Python.CreateEngine(); py.Runtime.IO.SetOutput(new ScriptOutputStream(txtYourTextBoxInstance), Encoding.GetEncoding(1252));

    Now, any time you output to the console in IronPython you’ll get your console output directly in your TextBox! The ScriptOutputStream implementation and calling SetOutput() are really the key points in getting output from IronPython.

    The Application at a Glance

    I wanted to take this example a little bit further than the initial request. I didn’t just want to show that I could take the IronPython output and put it in a form control, I wanted to demonstrate being able to pick the Python code to run too!

    Firstly, you’re able to browse for Python scripts using the default radio button. Just type in the path to your script or use the browse button:

    IronPython - Run script from file

    Next, press “Run Script”, and you’re off! This simply uses a StreamReader to get the contents of the file and then once in the contents are stored in a string, they are passed into the IronPython engine’s Execute() method. As you might have guessed, my “helloworld.py” script just contains a single line that prints out “Hello, World!”. Nothing too fancy in there!

    Let’s try running a script that we type into the input TextBox instead. There’s some basic error handling so if your script doesn’t execute, I’ll print out the exception and the stack trace to go along with it. In this case, I tried executing a Python script that was just “asd”. Clearly, this is invalid and shouldn’t run:

    That should be along the lines of what we expected–The script isn’t valid, and IronPython tells us why. What other errors can we see? Well, the IronPython engine will also let you know if you have bad syntax:

    Finally, if we want to see some working Python we can do some console printing. Let’s try a little HelloWorld-esque script:

    Summary

    This sample was pretty short but that just demonstrates how easy it is! Passing in a script from C# into the IronPython is straight forward, but getting the output from IronPython is a bit trickier. If you’re not familiar with the different parts of the IronPython engine, it can be difficult to find the things you need to get this working. With a simple custom stream implementation we’re able to get the output from IronPython easily. All we had to do was create our own stream implementation and pass it into the SetOutput() method that’s available via the IronPython engine class. Now we can easily hook the output of our Python scripts!

    As always, all of the source for you to try this out is available online:

    • PasteBin (Just the MainForm where the bulk of the code resides)
      • MainForm.cs
      • MainForm.Designer.cs

      Some next steps might include:

      • Creating your own Python IDE. Figure out some nice text-editing features and you can run Python scripts right from your application.
      • Creating a test script dashboard. Do you write test scripts for other applications in Python? Why not have a dashboard that can report on the results of these scripts?
      • Add in some game scripting! Sure, you could have done this with IronPython alone, but maybe now you can skip the WinForms part of this and just make your own stream wrapper for getting script output. Cook up some simple scripts in a scripting engine and voila! You can easily pass information into Python and get the results back out.

      Let me know in the comments if you come up with some other cool ideas for how you can leverage this!

      Tags: .NET , BitBucket , C# , Code Project , coding , development , example , GitHub , google code , guide , Input , IronPython , Output , PasteBin , Programming , Python , PyTools , sample , Scripting , Software , Stream , Tutorial , Visual Studio , VS2012 , walkthrough , WinForms

      Nick Cosentino

      You Might Also Like

      v6.2 of IEF from Magnet Forensics! – Weekly Article Dump

      Thread vs BackgroundWorker

      Read more about the article Burn Out – An Alternate Perspective

      July 29, 2013

      Источник

Оцените статью