다음은 Pythob 2.7.* 에 PyGTK 를 설치하여 실행되는 RPN 계산기 소스이다.

 

#!/usr/bin/env python

# Filename: rpnCalc.py
#           0,3
#
#   RPN Calculator using PyGTK
#   Modified from PyGTK/example/textview-basic.py

import pygtk
pygtk.require('2.0')
import gtk

class TextViewExample:
    def callback(self, widget, data=None):
        print "Hello again - %s was pressed" % data
        if data != None:
            self.textbuffer.insert(self.textbuffer.get_end_iter(), data + "\n")
               
    def enter_callback(self, widget, entry):
        entry_text = entry.get_text()
        print "Entry contents: %s\n" % entry_text
  
    def create_model(self):
        '''create the model - a ListStore'''
        self.store = gtk.ListStore(float)
        return self.store
 
    def create_columns(self, treeView):
        ''' create the columns '''
        rendererText = gtk.CellRendererText()
        rendererText.set_property('xalign', 1.0)   # work for right align
        column = gtk.TreeViewColumn(None, rendererText, text=0)
        column.set_sort_column_id(0)
        column.set_alignment(0.5)   # work for center align

        # append the column
        treeView.append_column(column)

    def reset(self, widget, entry):
        entry.set_text("")

    def calcIt(self, widget, entry):
        CONTINUE_FLAG = 1

        while CONTINUE_FLAG == 1:
            param = entry.get_text()
            tokens = self.tokenize(param)
            token_len = len(tokens)

            self.textbuffer.insert(self.textbuffer.get_end_iter(), "RPN> " + param + "\n")

            for i in range(0, token_len):
                    str = "" + tokens[i]
                    if len(str) == 0:
                        continue

                    a = str[0:1]

                    if a == 'Q' or a == 'q':
                        self.showMessage("Quit")
                        self.clear()
                        CONTINUE_FLAG = 0
                        break

                    if a in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.']:
                            self.push(eval(str))
                    elif a == '+':
                            if len(str) > 1:
                                self.push(eval(str))
                            else:
                                self.push(self.pop() + self.pop())
                    elif a == '-':
                            if len(str) > 1:
                                self.push(eval(str))
                            else:
                                op2 = self.pop();
                                self.push(self.pop() - op2)
                    elif a == '*':
                         if str == "**":
                                op2 = self.pop()
                                self.push(pow(self.pop(), op2))
                         else:
                                self.push(self.pop() * self.pop())
                    elif a == '/':
                            op2 = self.pop()
                            if op2 != 0.0:
                                self.push(self.pop() / op2)
                            else:
                                self.showMessage("zero divisor popped")
                    elif a == '^':
                            op2 = self.pop()
                            self.push(pow(self.pop(), op2))
                    elif a == '=' or a == 'p':
                            listmodel = self.listView.get_model()
                            y = listmodel.get_value(listmodel.get_iter_first(), 0)
                            self.showMessage("%s" % y)
                    elif a == 'c':
                            self.showMessage("Clear")
                            self.clear()
                    else:
                            self.showMessage("Unknown Command: " + a)
            CONTINUE_FLAG = 0
            entry.set_text("")


    # push f onto value stack
    def push(self, f):
        self.store.insert(0, [f])

    # pop top value from stack
    def pop(self):
        try:
             listmodel = self.listView.get_model()
             y = listmodel.get_value(listmodel.get_iter_first(), 0)
             self.store.remove(self.store.get_iter_first())
             return y
        except:
             raise "pop error on empty stack"
        return None

    # clear stack
    def clear(self):
        self.store.clear()


    # Tokenize the input string.
    def tokenize(self, s):
        self.len = len(s)
        t = ""
        tokens = []    # list of tokens

        for i in range(0, self.len):
            c = s[i:i+1]
            if c == ' ' or c == '\t' or c == '\r' or c == '\n':
                    if len(t) > 0:
                            tokens.append(t)
                            t = ""
            elif c == '+' or c == '-':
                    if len(t) > 0:
                            tokens.append(t)
                            t = c
                    elif len(t) == 0:
                            t = c
            elif c == '*':
                    if len(t) > 1:
                            tokens.append(t)
                            tokens.append(c)
                            t = ""
                    elif len(t) == 1:
                         if t == "*":
                                tokens.append("**")
                                t = ""
                         else:
                                tokens.append(t)
                                tokens.append(c)
                                t = ""
                    elif len(t) == 0:
                            t = c
            elif c == '/' or c == '^' or c == '=' or c == 'p' or c == 'q' or c == 'Q':
                    if len(t) > 0:
                            tokens.append(t)
                            tokens.append(c)
                            t = ""
                    elif len(t) == 0:
                            tokens.append(c)
            else:
                    t += c

        if len(t) > 0:
                tokens.append(t)
                t = ""
        return tokens


    def showMessage(self, m):
        if m != None:
            self.textbuffer.insert(self.textbuffer.get_end_iter(), "%s\n" % m)


    def close_application(self, widget):
        gtk.main_quit()

    def __init__(self):
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_resizable(True) 
        window.connect("destroy", self.close_application)
        window.set_title("RPN Calculator")
        window.set_default_size(500, 300)
        window.set_border_width(0)

        box2 = gtk.VBox(False, 10)
        box2.set_border_width(10)
        window.add(box2)
        box2.show()

        hbox1 = gtk.HBox()
        box2.pack_start(hbox1, True, True, 0)
        hbox1.show()


        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        textview = gtk.TextView()
        self.textbuffer = textview.get_buffer()
        sw.add(textview)
        sw.show()
        textview.show()

        hbox1.pack_start(sw, True, True, 10)


        # create a scrollable window and integrate it into the vbox
        sw2 = gtk.ScrolledWindow()
        sw2.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        sw2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
 
        # create a TreeView object which will work with our model (ListStore)
        store = self.create_model()
        self.listView = gtk.TreeView(store)
        self.listView.set_rules_hint(True)
        self.listView.set_headers_clickable(False)
        self.listView.set_property("headers-visible", False)
 
        # add the TreeView to the scrolled window
        sw2.add(self.listView)
 
        sw2.show()
        self.listView.show()

        # create the columns
        self.create_columns(self.listView)
        sw2.set_size_request(150, 300)
        hbox1.pack_start(sw2, False, False, 10)


        # check button to toggle editable mode
        textview.set_editable(False)
        textview.set_cursor_visible(False)
       
        hbox2 = gtk.HBox()
        box2.pack_start(hbox2, False, True, 0)
        hbox2.show()

        entry = gtk.Entry()
        entry.set_max_length(50)
        entry.connect("activate", self.enter_callback, entry)
        hbox2.pack_start(entry, True, True, 10)
        entry.show()

        hbox3 = gtk.HButtonBox()
        hbox2.pack_start(hbox3, False, False, 0)
        hbox3.show()

        btnCalc = gtk.Button("Calculate")
        btnCalc.connect("clicked", self.calcIt, entry)
        hbox3.pack_start(btnCalc, True, True, 5)
        btnCalc.set_flags(gtk.CAN_DEFAULT)
        btnCalc.grab_default()
        btnCalc.show()
       

        btnReset = gtk.Button("Reset")
        btnReset.connect("clicked", self.reset, entry)
        hbox3.pack_start(btnReset, True, True, 5)
        btnReset.set_flags(gtk.CAN_DEFAULT)
        btnReset.grab_default()
        btnReset.show()

        window.show()

def main():
    gtk.main()
    return 0      

if __name__ == "__main__":
    TextViewExample()
    main()

 

프롬프트> python rpnCalc.py

 

 

 

Posted by Scripter

댓글을 달아 주세요