??xml version="1.0" encoding="utf-8" standalone="yes"?>
OK, Let's give a shot!
1. of course, 先要现在DjangoQ?font size="2" face="Courier New">不过我还是推荐用svn中的代码?div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;">svn co http://code.djangoproject.com/svn/django/trunk/ django-dev 2. 接着p下蝲Jython?jin),当前的stable版本?.2.1Q而我们需要的?.5Q该版本q是alpha阶段Q所以,q是从svn中获取?br />
ant
jython setup.py build
jython setup.py install
Jython 2.5a3+ (trunk, ???? 16 2008, 18:50:22)
[Java HotSpot(TM) Client VM (Sun Microsystems Inc.)] on java1.6.0_10-beta
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.get_version()
u'1.0-post-release-SVN-SVN-unknown'
cd django-jython
jython setup.py build
jython setup.py install
万事俱备Q让我们开始真正的Django on Jython之旅吧?br /> q里q需要说明一点,在完成Django的安装之后,在jython/bin下会(x)有一个django-admin.pyQ这个是Django命o(h)的工PZ(jin)同CPython下的Djangoq行区别Q我在这里将光命名为django-admin-jy.py?br /> 好,切换到工作目录?br />
jython manage.py runserver
2 from django.contrib.auth.models import User
3
4 class Entry(models.Model):
5 STATUS_CHOICES = (
6 (0, 'live'),
7 (1, 'draft'),
8 (2, 'cancel'),
9 )
10 author = models.ForeignKey(User)
11 title = models.CharField(max_length=255)
12 slug = models.SlugField()
13 content = models.TextField()
14 create_at = models.DateTimeField(auto_now_add=True)
15 status = models.IntegerField(default=0, choices=STATUS_CHOICES)
16
17 def __unicode__(self):
18 return self.title
19
20 def get_absolute_url(self):
21 return '/blog/%s' % (self.slug)
22
23 class Meta:
24 ordering = ['-create_at']
2
3 from djangonjython.blog.models import Entry
4
5 class EntryAdmin(admin.ModelAdmin):
6 list_display = ('title', 'author', 'create_at', 'status',)
7 ordering = ['-create_at']
8 list_filter = ('author', 'status',)
9 prepopulated_fields = {'slug': ('title',),}
10
11 admin.site.register(Entry, EntryAdmin)
取消q几行的注释Q?div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;">from django.contrib import admin
admin.autodiscover()
(r'^admin/(.*)', admin.site.root),
接着是settings.pyQ?div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;">DATABASE_ENGINE = 'doj.backends.zxjdbc.postgresql' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'blog' # Or path to database file if using sqlite3.
DATABASE_USER = 'yourname' # Not used with sqlite3.
DATABASE_PASSWORD = 'yourpassword' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'djangonjython.blog',
'doj',
)
对上面的代买q行一些说明:(x)
doj.backends.zxjdbc.postgresql是之前安装的django-jython提供的数据支持,当然Q要使用q个Q必ddojq个库添加到PYTHONPATH中,所以在下面的INSTALLED_APPS里,加入?jin)dojQ而djangonjyton.blog是之前创徏的app?br /> 好,完成?jin)这些,可以开始数据库的创Z(jin)。熟(zhn)的命o(h)Q?br />
好了(jin)Q在q里可以添加一些entry?jin)。完成了(jin)后台的管理,让我们添加一些前台的昄吧?/font>
在这里,我打用django自带的generic viewsQ用v来非常的单。ؓ(f)?jin)同目的urls.py区别开Q在blog下创Z个新的urls.pyQ内容如下:(x)
2
3 from djangonjython.blog.models import Entry
4
5 entry_dict = {
6 'queryset': Entry.objects.all(),
7 'template_object_name': 'entry',
8 }
9
10 urlpatterns = patterns('django.views.generic.list_detail',
11 (r'^blog/$', 'object_list', entry_dict),
12 (r'^blog/(?P<slug>.*)/$', 'object_detail', entry_dict),
13 )
14
entry_list.html
2 {% for entry in entry_list %}
3 <a href="/blog/{{ entry.slug }}"><h3>{{ entry.title }}</h3></a> Post at: {{ entry.create_at|date:"Y-b-d" }}<hr/>
4 {% endfor %}
5 {% endif %}
2 <span style="color: green;">{{ entry.title }}</span><br/><br/>
3 post by: <b>{{ entry.author.username }}</b><br/><br/>
4 <div style="color: blue">{{ entry.content|safe }}</div>
5 {% endif %}
PROJECT_ROOT = os.path.abspath(__file__)
TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, 'blog/templates'),
)
到这里,javaE序员就可以使用熟?zhn)的java web serverq行部v?jin)!部v完成后,输入http://localhost:8080/djangonjython/blog/可以进行访问了(jin)?br /> q里l出一些在tomcat上运行的截图Q?br />
]]>
今天看到, django对docsq行?jin)重? 现在大家可以这些文件下载到本地, 然后q行~译, 生成相应的文? 览h?x)非常方? 舒服.
? 我们单的看一看该如何操作:
1. 从svn库中checkout:
2. 安装Sphinx:
熟?zhn)python的朋友应该知? Sphinx是非常好的一个工? 可以简单文本格式{换ؓ(f)html格式, 当然, 文本内容需要按照Sphinx的语法进行编? Python现在的在Udocuments是使用Sphinxq行~译?感兴的朋友可以?a >Sphinx?jin)解更多内?
3. ~译:
到这? 完成了(jin)django_docs的编译工? 在django_docs/_build/html下就是编译的l果. 重构后的文档的css也有?jin)新的变? 现在的非常像django_book的样?
OK, 以后我们可以在本地q行文档的阅M(jin), 怿?x)给开发带来事半功倍的效果.
q里我附上一份我~译好的, 供大家下? django_docs
]]>
布局是GUIE序开发中非常重要的一个环? 而布局理是要规划如何在H口中放|需要的部g. PyQt4中就有两U方法来完成布局d,一个是l对位置(absolute positioning), 另一个就是用布局c?layout classes).
l对位置(absolute positioning)
q种Ҏ(gu)需要程序员在程序中指定每个部g的坐标位|和大小. 在这里有几个注意事项.
2
3 # absolute.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class Absolute(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setWindowTitle('Communication')
13
14 label = QtGui.QLabel('Could\'t', self)
15 label.move(15, 10)
16
17 label = QtGui.QLabel('care', self)
18 label.move(35, 40)
19
20 label = QtGui.QLabel('less', self)
21 label.move(55, 65)
22
23 label = QtGui.QLabel('And', self)
24 label.move(115, 65)
25
26 label = QtGui.QLabel('then', self)
27 label.move(135, 45)
28
29 label = QtGui.QLabel('you', self)
30 label.move(115, 25)
31
32 label = QtGui.QLabel('kissed', self)
33 label.move(145, 10)
34
35 label = QtGui.QLabel('me', self)
36 label.move(215, 10)
37
38 self.resize(250, 150)
39
40 app = QtGui.QApplication(sys.argv)
41 qb = Absolute()
42 qb.show()
43 sys.exit(app.exec_())
在这? 是单的调用move()Ҏ(gu)来指定部件的攄坐标. 坐标的顶点就在窗口的左上? x由左向右不断增大, y׃C不断增大.
Figure: absolute positioning
Box Layout
使用布局c进行布局理是一仉常轻杄事情. 最基本的布局cd是QHboxLayout和VHBoxLayout. 他们部件线性的水^或垂直排?
q里假设我们要将两个按钮攑֜H口的右下方, 要实现这L(fng)布局, 使用一个QHBoxLayout和一个QVBoxLayout, 而其他的I间, 通过dstretch factor来实?
2
3 # boxlayout.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class BoxLayout (QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setWindowTitle('boxlayout')
13
14 ok = QtGui.QPushButton('OK')
15 cancel = QtGui.QPushButton('Cancel')
16
17 hbox = QtGui.QHBoxLayout()
18 hbox.addStretch(1)
19 hbox.addWidget(ok)
20 hbox.addWidget(cancel)
21
22 vbox = QtGui.QVBoxLayout()
23 vbox.addStretch(1)
24 vbox.addLayout(hbox)
25
26 self.setLayout(vbox)
27
28 self.resize(300, 150)
29
30 app = QtGui.QApplication(sys.argv)
31 qb = BoxLayout()
32 qb.show()
33 sys.exit(app.exec_())
cancel
=
QtGui.QPushButton(
'
Cancel
'
)
hbox.addStretch(
1
)
hbox.addWidget(ok)
hbox.addWidget(cancel)
vbox.addStretch(
1
)
vbox.addLayout(hbox)
Figure: box layout
QGridLayout
最常用的布局cd当是QGridLayout, 他将H口分成不同的行和列.
2
3 # gridlayout.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class GridLayout(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setWindowTitle('grid layout')
13
14 names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/',
15 '4', '5', '6', '*', '1', '2', '3', '-',
16 '0', '.', '=', '+']
17
18 grid = QtGui.QGridLayout()
19
20 j = 0
21 pos = [
22 (0, 0), (0, 1), (0, 2), (0, 3),
23 (1, 0), (1, 1), (1, 2), (1, 3),
24 (2, 0), (2, 1), (2, 2), (2, 3),
25 (3, 0), (3, 1), (3, 2), (3, 3),
26 (4, 0), (4, 1), (4, 2), (4, 3)
27 ]
28
29 for i in names:
30 button = QtGui.QPushButton(i)
31 if j == 2:
32 grid.addWidget(QtGui.QLabel(''), 0, 2)
33 else:
34 grid.addWidget(button, pos[j][0], pos[j][1])
35 j = j + 1
36
37 self.setLayout(grid)
38
39 app = QtGui.QApplication(sys.argv)
40 qb = GridLayout()
41 qb.show()
42 sys.exit(app.exec_())
grid
=
addWidget(QtGui.QLabel(
''
), 0,
2
)
else
:
grid
=
addWidget(button, pos[j][0], pos[j][i])
Figure: grid layout
需要说明一? 部g也可以多行和多列. 下面的列子就演示?jin)之一?
2
3 # gridlayout2.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class GridLayout2(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setWindowTitle('grid layout2')
13
14 title = QtGui.QLabel('Title')
15 author = QtGui.QLabel('Author')
16 review = QtGui.QLabel('Review')
17
18 titleEdit = QtGui.QLineEdit()
19 authorEdit = QtGui.QLineEdit()
20 reviewEdit = QtGui.QTextEdit()
21
22 grid = QtGui.QGridLayout()
23 grid.setSpacing(10)
24
25 grid.addWidget(title, 1, 0)
26 grid.addWidget(titleEdit, 1, 1)
27
28 grid.addWidget(author, 2, 0)
29 grid.addWidget(authorEdit, 2, 1)
30
31 grid.addWidget(review, 3, 0)
32 grid.addWidget(reviewEdit, 3, 1, 5, 1)
33
34 self.setLayout(grid)
35 self.resize(350, 300)
36
37 app = QtGui.QApplication(sys.argv)
38 qb = GridLayout2()
39 qb.show()
40 sys.exit(app.exec_())
41
grid.setSpacing(
10
)
Figure: grid layout 2
]]>
QMainWindowcȝ我们提供?jin)一个程序主H口Q得我们能够创Z个标准的E序框架Q包括了(jin)状态栏Q工h和菜单栏?br />
状态栏(Statusbar)
状态栏是一U用来显C状态信息的部?
2
3 # statusbar.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class MainWindow(QtGui.QMainWindow):
9 def __init__(self):
10 QtGui.QMainWindow.__init__(self)
11
12 self.resize(250, 150)
13 self.setWindowTitle('statusbar')
14
15 self.statusBar().showMessage('Ready')
16
17 app = QtGui.QApplication(sys.argv)
18 main = MainWindow()
19 main.show()
20 sys.exit(app.exec_())
21
菜单?Menubar)
菜单是应用程序中最常见的一U组?通常每个菜单都是完成不同的Q?
2
3 # menubar.py
4
5 import sys
6 from PyQt4 import QtGui, QtCore
7
8 class MainWindow(QtGui.QMainWindow):
9 def __init__(self):
10 QtGui.QMainWindow.__init__(self)
11
12 self.resize(250, 150)
13 self.setWindowTitle('menubar')
14
15 exit = QtGui.QAction(QtGui.QIcon('icons/web.png'), 'Exit', self)
16 exit.setShortcut('Ctrl+Q')
17 exit.setStatusTip('Exit application')
18 self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
19
20 self.statusBar()
21
22 menubar = self.menuBar()
23 file = menubar.addMenu('&File')
24 file.addAction(exit)
25
26 app = QtGui.QApplication(sys.argv)
27 main = MainWindow()
28 main.show()
29 sys.exit(app.exec_())
30
file
=
menubar.addMenu(
'
&File
'
)
file.addAction(exit)
工具?Toolbar)
菜单可以不同的命o(h)按组分类,然?有些常用的命令就可以通过工具栏来攄,q样更便于?
2
3 # toolbar.py
4
5 import sys
6 from PyQt4 import QtGui, QtCore
7
8 class MainWindow(QtGui.QMainWindow):
9 def __init__(self):
10 QtGui.QMainWindow.__init__(self)
11
12 self.resize(250, 150)
13 self.setWindowTitle('toolbar')
14
15 self.exit = QtGui.QAction(QtGui.QIcon('icons/web.png'), 'Exit', self)
16 self.exit.setShortcut('Ctrl+Q')
17 self.connect(self.exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
18
19 self.toolbar = self.addToolBar('Exit')
20 self.toolbar.addAction(self.exit)
21
22 app = QtGui.QApplication(sys.argv)
23 main = MainWindow()
24 main.show()
25 sys.exit(app.exec_())
self.exit.setShortcut(
'
Ctrl+Q
'
)
self.toolbar.addAction(self.exit)
Figure: toolbar
一个完整的E序
最后这个部?menubar, toolbar和statusbar攑֜一?
2
3 # mainwindow.py
4
5 import sys
6 from PyQt4 import QtGui, QtCore
7
8 class MainWindow(QtGui.QMainWindow):
9 def __init__(self):
10 QtGui.QMainWindow.__init__(self)
11
12 self.resize(350, 250)
13 self.setWindowTitle('mainwindow')
14
15 textEdit = QtGui.QTextEdit()
16 self.setCentralWidget(textEdit)
17
18 exit = QtGui.QAction(QtGui.QIcon('icons/web.png'), 'Exit', self)
19 exit.setShortcut('Ctrl+Q')
20 exit.setStatusTip('Exit application')
21 self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))
22
23 self.statusBar()
24
25 menubar = self.menuBar()
26 file = menubar.addMenu('&File')
27 file.addAction(exit)
28
29 toolbar = self.addToolBar('Exit')
30 toolbar.addAction(exit)
31
32 app = QtGui.QApplication(sys.argv)
33 main = MainWindow()
34 main.show()
35 sys.exit(app.exec_())
36
self.setCentralWidget(textEdit)
]]>
最单的example
下面的示例会(x)非常的简单,仅仅昄一个小H口Q但是将来我们可以通过q个窗口做很多事情。我们可以对它进行羃放,最大化Q最化。而这些就需要比较多的代码了(jin)。但是开发h员已l帮我们完成?jin)这些功能,因?f)q些功能在大多场合都?x)用到Q所以没有必要让我们重复。PyQt是一个高U别的工具库Q如果用别相对较低的库开发下面的功能Q就非常可能需要更多的代码?jin)?br />#!/usr/bin/python
2
3# simple.py
4
5import sys
6from PyQt4 import QtGui
7
8app = QtGui.QApplication(sys.argv)
9
10widget = QtGui.QWidget()
11widget.resize(250, 150)
12widget.setWindowTitle('simple')
13widget.show()
14
15sys.exit(app.exec_())
下面对代码进行分?br />
from PyQt4 import QtGui
?Qsimple
d图标
应用E序的图标一般就是一个在E序标题栏左上角昄的小囄Q下面的例子我们展示如何使用PyQt4来显C图标,同时引入一些新的方法?/font>
2
3 # icon.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class Icon(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setGeometry(300, 300, 250, 150)
13 self.setWindowTitle('Icon')
14 self.setWindowIcon(QtGui.QIcon('icons/web.png'))
15
16 app = QtGui.QApplication(sys.argv)
17 icon = Icon()
18 icon.show()
19 sys.exit(app.exec_())
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle('Icon') self.setWindowIcon(QtGui.QIcon('icons/web.png'))
?QIcon
展示信息提示(tooltip)
我们可以使用PyQt4lQ何的部gd信息提示功能?/font>
2
3 # tooltip.py
4
5 import sys
6 from PyQt4 import QtGui
7 from PyQt4 import QtCore
8
9 class Tooltip(QtGui.QWidget):
10 def __init__(self, parent=None):
11 QtGui.QWidget.__init__(self, parent)
12
13 self.setGeometry(300, 300, 250, 150)
14 self.setWindowTitle('Tooltip')
15
16 self.setToolTip('This is a <b>QWidget</b> widget')
17 QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
18
19 app = QtGui.QApplication(sys.argv)
20 tooltip = Tooltip()
21 tooltip.show()
22 app.exec_()
?QTooltip
关闭H口
之前的例子中Q我们关闭程序都是用标题栏上的X按钮q行关闭的。下面的例子里,我们使用~程的方式来关闭H口。而在q里Q我们就要开始了(jin)解一些Qt中非帔R要的概念?jin),信?signals)和槽(slots)?br /> 下面一行是QPushButton的构造方法?/font>
2
3 # quitbutton.py
4
5 import sys
6 from PyQt4 import QtGui, QtCore
7
8 class QuitButton(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setGeometry(300, 300, 250, 150)
13 self.setWindowTitle('Icon')
14
15 quit = QtGui.QPushButton('Close', self)
16 quit.setGeometry(10, 10, 60, 35)
17
18 self.connect(quit, QtCore.SIGNAL('clicked()'), \
19 QtGui.qApp, QtCore.SLOT('quit()'))
20
21 app = QtGui.QApplication(sys.argv)
22 qb = QuitButton()
23 qb.show()
24 sys.exit(app.exec_())
quit.setGeometry(10, 10, 60, 35)
QtGui.qApp, QtCore.SLOT('quit()'))
?Qquit button
对话?/font>
默认情况下,如果我们点击?jin)标题栏的X按钮Q就?x)将H口关闭Q而有些时候,需要修改这L(fng)行ؓ(f)。比如说在文本编辑器中,如个要关闭一个正在修改的文gQ就?x)弹Z个对话框来确认?/font>
2
3 # messagebox.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class MessageBox(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setGeometry(300, 300, 250, 150)
13 self.setWindowTitle('message box')
14
15 def closeEvent(self, event):
16 reply = QtGui.QMessageBox.question(self, 'Message', \
17 'Are you sure to quit?',\
18 QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
19 if reply == QtGui.QMessageBox.Yes:
20 event.accept()
21 else:
22 event.ignore()
23
24
25 app = QtGui.QApplication(sys.argv)
26 mb = MessageBox()
27 mb.show()
28 sys.exit(app.exec_())
'Are you sure to quit?',\
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
event.accept()
else:
event.ignore()
?Qmessage box
H口居中
下面的代码展CZ(jin)如何创建的H口在屏q中居中?/font>
2
3 # center.py
4
5 import sys
6 from PyQt4 import QtGui
7
8 class Center(QtGui.QWidget):
9 def __init__(self, parent=None):
10 QtGui.QWidget.__init__(self, parent)
11
12 self.setWindowTitle('center')
13 self.resize(250, 150)
14 self.center()
15
16 def center(self):
17 screen = QtGui.QDesktopWidget().screenGeometry()
18 size = self.geometry()
19 self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
20
21
22 app = QtGui.QApplication(sys.argv)
23 c = Center()
24 c.show()
25 sys.exit(app.exec_())
]]>
q是一个PyQt4的简单教E,目的是Z(jin)让大家对PyQt4有个初步的了(jin)解?/font>