다음은 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
'프로그래밍 > Python' 카테고리의 다른 글
wxPython을 이용한 간단한 웹 브라우저 소스 몇 가지 (0) | 2020.11.29 |
---|---|
wxPython 4.1.1 (현재 최신 버전) 설치하기 (0) | 2020.11.28 |
Python 3.3.5 및 3.4.1 에 IPython 과 Matplotlib 설치하기 (0) | 2014.08.04 |
Python 버전 알아내기 (0) | 2014.05.08 |
pyqtgraph 를 이용한 그래프 그리기 예제 (0) | 2014.02.28 |