Visar inlägg med etikett wxPython. Visa alla inlägg
Visar inlägg med etikett wxPython. Visa alla inlägg

2008-01-21

SudokuDemo.wx.py

About a week later than I had hoped I've finally managed to finish the Sudoku demo from ClipsJNI. I've tried staying as close to the Java version as possible but there are a few differences. For example, I've added an Open File-button that allows you to load a puzzle from a text file. I've included a few sample puzzles in the zip. The format of the puzzle must be exactly as in the examples: 9 lines of 9 characters (and a newline) each. Characters "1", "2", "3" to "9" are added as-is, all other characters are "added" as blanks (I use "0" in my examples).



I've still got some work to do before I upload this as a pyClips example on SourceForge. I really want to clean up the code and try to make it as easy to understand as possible. I also intend to write a short introduction to using wxPython and pyClips together.

The code is here if you want to have a premature look. If you find any bugs or peculiar behaviour please let me know. Enjoy!

2008-01-18

A simple wx.grid.Grid example

I've had the opportunity to help Dereje with a wxPython question this week. His question was how to add an image to a cell in a wx.Grid. The wxPython demo and docs are great (really) but are not always the easiest to understand and the wx.Grid examples are a bit over-complicated so I've made an implementation that's as simple as can be. Here goes.

>>> import wx
>>> import wx.grid
>>> class MyApp(wx.App):
... def OnInit(self):
... frame = wx.Frame(None, -1, title = "wx.Grid - Bitmap example")
... grid = wx.grid.Grid(frame)
... grid.CreateGrid(1,1)
... img = wx.Bitmap("python-logo.png", wx.BITMAP_TYPE_PNG)
... imageRenderer = MyImageRenderer(img)
... grid.SetCellRenderer(0,0,imageRenderer)
... grid.SetColSize(0,img.GetWidth()+2)
... grid.SetRowSize(0,img.GetHeight()+2)
... frame.Show(True)
... return True

>>> class MyImageRenderer(wx.grid.PyGridCellRenderer):
... def __init__(self, img):
... wx.grid.PyGridCellRenderer.__init__(self)
... self.img = img
... def Draw(self, grid, attr, dc, rect, row, col, isSelected):
... image = wx.MemoryDC()
... image.SelectObject(self.img)
... dc.SetBackgroundMode(wx.SOLID)
... if isSelected:
... dc.SetBrush(wx.Brush(wx.BLUE, wx.SOLID))
... dc.SetPen(wx.Pen(wx.BLUE, 1, wx.SOLID))
... else:
... dc.SetBrush(wx.Brush(wx.WHITE, wx.SOLID))
... dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID))
... dc.DrawRectangleRect(rect)
... width, height = self.img.GetWidth(), self.img.GetHeight()
... if width > rect.width-2:
... width = rect.width-2
... if height > rect.height-2:
... height = rect.height-2
... dc.Blit(rect.x+1, rect.y+1, width, height, image, 0, 0, wx.COPY, True)

>>> app = MyApp(0)
>>> app.MainLoop()
The above code ought to look something like this:



The class MyImageRenderer is the same as the one from the demo. I modified it slightly so that it loads an image from file rather than from a hex coded string and that you can set the image as a parameter instead of having it defined within the renderer itself.

2008-01-09

Kicking a dead horse

This is my first week of my 8 months of daddy-duty. I've got a bit more free time now, not an obscene amount more, but Eowyn is very easy to take care of and she sleeps quite a few times during the day so I've found myself spending more time thinking about my after-work projects.

So, as I was converting the ClipsJNI demos to wxPython/pyClips (still one to go though) I realised that I might have use for a project I worked on a couple of years ago.

The summer of 2004 I wrote an "application browser" based on wxPython. The easiest way to explain what it does is to think of it as a regular web browser but instead of reading HTML and generating a view it reads something I called wxWML or wxWidgets Markup Language (wxML was taken already) and "generates" a wxPython rich client application.

The project is called wxBrowser and can be found on SourceForge. We used it at work to deploy an application we couldn't get working in the web browsers at that time. Today, there are several options that are much, much better of course. XUL and Eclipse RCF come to mind.

Anyway, I made one last release in the summer of 2005 and I haven't looked at it since. Until today that is.

It turns out that creating a GUI for a Clips application requires you to divide your application into (at least) two distinct parts that are quite tightly coupled. You can try to make the coupling looser by having a more dynamic GUI application that decides what to show on the screen based on Facts in Working Memory (see the Auto Demo for an example of this). But there will still be quite a lot of GUI specific code that won't be all that dynamic. Which, as it turns out, was exactly the problem I wrote the wxBrowser for in the first place.

If I can translate Facts in Clips' Working Memory to wxWML I could use the wxBrowser to provide a GUI for a Clips program. Sure, I'd have to write a whole lot of rules and functions to get it to work but at least I won't have to do it in another language or environment. The wxBrowser itself can be distributed as an .exe which contains pyClips so all you really need is the Clips program to run and you're good to go.

There's of course a down side to all of this which is why I decided to go with the Kicking a dead horse title instead of Blowing new life into old things or something similar. First of all, wxPython code (and the structure of the library) isn't always that easy to understand. This was one of the major stumbling blocks in 2004 and it hasn't gone away. Secondly, there's a reason people use all sorts of tools to generate GUIs and last time I checked there was no tool that could save in Clips' deffacts format. Third, it's an evil bitch-monster of death to debug if something isn't working as expected (which almost ALWAYS is the case when working with GUIs).

Well, luckily I've gotten quite good at kicking dead horses over the years so I'll give this idea a try in the next few weeks. If it doesn't work out, I'll just bring it up again in 2012 or so ;-)

[2008-01-10] Update: Fourth, Client-side scripting. This will actually be less of a problem with Clips as a backend because, well, there wouldn't be any need for client side scripting since the back end is available all the time unlike in an HTTP environment.

2008-01-08

AutoDemo.wx.py

I've just finished implementing the ClipsJNI Auto Demo example in wxPython. This time it was easier to do a line by line (more or less) re-write of the Java code, but that's mostly because most of the GUI is controlled from within the Clips file.



Just as with the Wine Demo I had to modify some of the calls to the Clips engine. I added two functions that return Fact indexes instead of Fact addresses, but that's it.

The demo is here. If you've already got Python, wxPython and pyClips installed all you have to do is run python AutoDemo.wx.py at a command line and it should pop right up (same goes for the Wine Demo).

Once I've finished the Sudoku Demo I'll write up some instructions on how to use pyClips and wxPython in general. Where to start, where to get help and such things. Enjoy!

2008-01-05

Clips Wine Demo using wxPython

I finally got enough free time to finish the wxPython Wine Demo I found last week. At first I wanted it to be, more or less, a line by line re-write of the Java version (ClipsJNI) but that turned out to be too difficult in the end.



Instead, I've tried to do as little "over all" damage as possible.

I didn't make the GUI 100% the same because that would have required too much wxPython specific code (and the point is not to show off wxPython anyway). I've also had to make a small change to the Clips code. It turned out that pyClips had trouble converting a MultiField return value containing Fact Addresses, so I added a function that instead returns the Fact Indexes.

Last, but not least, I designed the GUI using a wxPython XRC editor. That way I didn't have to write all that boilerplate GUI code to create, add and configure all of the widgets in the application.

I have kept the code for asserting facts exactly as in the ClipsJNI example even though that's not really the way to do it in Python.

All of the above are things that have been added or more complicated in Python/pyClips but there are other things as well. Things that could have been done easier. For example, there's no point in sorting the Facts in Clips, that can be done automatically in the ListCtrl widget (if you want).

The code is here. At least for now, I'm hoping it can be hosted on SourceForge together with the pyClips project but that's up to Franz so I'll have to wait and see what he says first. If you find any bugs or have any other comments, please let me know.

Enjoy!

2007-12-30

WineDemo.wx.py

Today I found, buried deep in the Playground folder on my hard disk, a half finished wxPython implementation of the WineDemo from Gary's ClipsJNI package. I'd completely forgotten about it but I still think it's worth finishing. Not having a good example in Python/pyClips is actually very annoying. Especially if you're, like me, trying to promote Python as a good way to provide a GUI for Clips programs.

So I started going through the code, trying to finish it earlier today but that made me remember why I stopped in the first place. I'm having a lot of trouble converting these two lines of Java into Python:

String evalStr = "(WINES::get-wine-list)";
MultifieldValue pv = (MultifieldValue) clips.eval(evalStr);
The conversion itself is quite simple but I can't get pyClips to evaluate the function, I keep getting this:
>>> clips.Eval("(WINES::get-wine-list)")

Traceback (most recent call last):
File "", line 1, in
clips.Eval("(WINES::get-wine-list)")
File "C:\Python25\lib\site-packages\clips\_clips_wrap.py", line 3430, in Eval
return _cl2py(_c.eval(expr))
ClipsError: C10: unable to evaluate expression
I guess I should I have reported it as a bug.

2006-10-03

Continuing the wxBrowser experiment?

Daniel Nogradi asked (on comp.lang.py) whether or not there was a way to generate (from one source) both a web application and a standalone desktop application.

Since this sounds similar to my wxBrowser experiment I pointed him to it and included all sorts of warnings and disclaimers. It turns out he wants, almost, but not quite what I had done. It raised, at least in my mind, yet again the question of whether or not it would be a good idea to include script tags in XRC. That has been discussed before but noone, at least noone that I've heard of, has stepped up and provided working code. I know that the wxBrowser can ("easily") be adapted to provide the same thing but it doesn't use XRC.

I might have to spend some time on this...