Jython 简明教程

Jython - Quick Guide

Jython - Overview

Jython是Python编程语言的JVM实现。它设计用于在Java平台上运行。Jython程序可以导入并使用任何Java类。就像Java一样,Jython程序编译为 bytecode 。其中一个主要优点是使用Python设计的用户界面可以使用 AWTSwingSWT Package 的GUI元素。

Jython最初被称为JPython,后来更名为Jython,它紧密遵循标准Python实现,称为 CPython ,由 Guido Van Rossum 创建。Jython由 Jim Hugunin 创建于1997年。Jython 2.0于1999年发行。从那时起,Jython 2.x版本对应于等效的CPython版本。2015年5月发布的Jython 2.7.0对应于CPython 2.7。Jython 3.x的开发正在进行中。

Difference between Python and Java

以下是Python和Java之间的差异−

  1. Python是一种动态类型语言。因此,不需要变量的类型声明。另一方面,Java是一种静态类型语言,这意味着变量的类型声明是必需的,并且不可更改。

  2. Python仅具有未检查的异常,而Java同时具有检查的异常和未检查的异常。

  3. Python使用缩进来进行范围限定,而Java使用匹配的花括号。

  4. 由于Python是一种基于解释器的语言,因此它没有单独的编译步骤。然而,Java程序需要编译成字节码,并由JVM执行。

  5. Python支持多重继承,但是在Java中,多重继承是不可能的。然而,它实现了接口。

  6. 与Java相比,Python具有更丰富的内置数据结构(列表、字典、元组,所有内容都是对象)。

Difference between Python and Jython

以下是Python和Jython之间的差异−

  1. Python的参考实现称为CPython,是用C语言编写的。另一方面,Jython完全用Java编写,并且是JVM实现。

  2. 标准Python可在多个平台上使用。Jython可用于安装了JVM的任何平台。

  3. 标准Python代码编译为 .pyc 文件,而Jython程序编译为 .class 文件。

  4. 可以使用 C 语言编写 Python 扩展。Jython 的扩展使用 Java 编写。

  5. Jython 本质上是真的多线程的。然而,Python 为此使用 Global Interpreter Lock 机制。

  6. 这两种实现具有不同的垃圾回收机制。

在下一章节,我们将学习如何导入 Jython 中的 Java 库。

Jython - Installation

在安装 Jython 2.7 之前,请确保系统已安装 JDK 7 或更多版本。Jython 以可执行 jar 文件的形式提供。从以下网址下载它 - https://www.jython.org/download.html ,然后双击其图标或运行以下命令:

java -jar jython_installer-2.7.0.jar

将启动安装向导,需要给出安装选项。以下是系统安装程序。

向导中的第一步要求你选择语言。

wizard

第二步提示你接受许可协议。

licence agreement

在下一步中,选择安装类型。建议选择“标准”安装。

installation type

下一个屏幕要求你确认你的选项,然后继续完成安装。

overview

安装过程可能需要一些时间才能完成。

installation in process

安装完成后,从目标目录中的 bin 目录调用 jython.exe 。假设 Jython 已安装在 C:\jython27 中,则从命令行执行以下命令。

C:\jython27\bin\jython

将出现 Python 提示符 (>>>),在此之前可以执行任何 Python 语句或 Python 脚本。

python prompt

Jython - Importing Java Libraries

Jython 最重要的特性之一是能够在 Python 程序中导入 Java 类。我们可以像在 Java 程序中一样在 Jython 中导入任何 Java 包或类。以下示例显示了如何在 Python(Jython)脚本中导入 java.util 包以声明 Date 类的一个对象。

from java.util import Date
d = Date()
print d

从命令行保存并运行 UtilDate.py 作为上述代码。将显示当前日期和时间的实例。

C:\jython27\bin>jython UtilDate.py
Sun Jul 09 00:05:43 IST 2017

Java 库中的以下包更经常在 Jython 程序中导入,主要是因为标准 Python 库要么没有其等效项,要么不够好。

  1. Servlets

  2. JMS

  3. J2EE

  4. Javadoc

  5. Swing 被认为优于其他 GUI 工具包

实际上可以在 Jython 脚本中导入任何 Java 包。在这里,以下 Java 程序存储并在名为 foo 的包中编译。

package foo;
public class HelloWorld {
   public void hello() {
      System.out.println("Hello World!");
   }
   public void hello(String name) {
      System.out.printf("Hello %s!", name);
   }
}

这个 HelloWorld.class 在以下 Jython 脚本中被导入。可以从 Jython 脚本 importex.py 调用此类中的方法。

from foo import HelloWorld
h = HelloWorld()
h.hello()
h.hello("TutorialsPoint")

保存并从命令行执行上述脚本以获得以下输出。

C:\jython27\bin>jython importex.py
Hello World!
Hello TutorialsPoint!

Jython - Variables and Data Types

变量是计算机内存中的命名位置。每个变量都可以在其中保存一个数据片段。与Java不同,Python是一种动态类型语言。因此,在使用Jython时;也不进行变量数据类型的先前声明。决定可以在其中存储哪些数据的,不是变量的类型,而是数据。

在以下示例中,已为变量指定了整数值。使用type()内置函数,我们可以验证变量的类型是否为整数。但是,如果为同一个变量指定了一个字符串,那么type()函数将会把同一个变量的类型作为字符串。

> x = 10
>>> type(x)
<class 'int'>

>>> x = "hello"
>>> type(x)
<class 'str'>

这解释了为什么Python被称为动态类型语言。

以下Python内置数据类型也可以在Jython中使用 −

  1. Number

  2. String

  3. List

  4. Tuple

  5. Dictionary

Python 将数值数据识别为一个数字,它可以是整数、带有浮点的实数或复数。字符串、列表和元组数据类型被称为序列。

Jython Numbers

在 Python 中,任何带符号整数都表示为类型“int”。若要表示长整数,则在其后附加字母“L”。数字用小数点将整数部分与小数部分分开,称为“浮点数”。小数部分可能包含指数,该指数以科学计数法表示,使用“E”or“e”。

在 Python 中复数也被定义为数值数据类型。一个复数有一个实部(一个浮点数)和一个包含“j”的虚部。

为了表示八进制或十六进制中的一个数字,在其前加上“ 0O ”或“ 0X ”。以下代码块给出了 Python 中不同数字表示形式的示例。

int     -> 10, 100, -786, 80
long    -> 51924361L, -0112L, 47329487234L
float   -> 15.2, -21.9, 32.3+e18, -3.25E+101
complex -> 3.14j, 45.j, 3e+26J, 9.322e-36j

Jython Strings

字符串是任何一系列字符,被单引号(例如“hello”)、双引号(比如“hello”)或三重引号(例如““hello””或“““hello”””)括起来。如果字符串的内容跨越多行,三重引号尤其有用。

转义序列字符可以原样包含在三重引号字符串中。以下示例展示了在 Python 中声明字符串的不同方法。

str = ’hello how are you?’
str = ”Hello how are you?”
str = """this is a long string that is made up of several lines and non-printable
characters such as TAB ( \t ) and they will show up that way when displayed. NEWLINEs
within the string, whether explicitly given like this within the brackets [ \n ], or just
a NEWLINE within the variable assignment will also show up.
"""

当打印第三个字符串时,将生成以下输出。

this is a long string that is made up of
several lines and non-printable characters such as
TAB ( 	 ) and they will show up that way when displayed.
NEWLINEs within the string, whether explicitly given like
this within the brackets [
], or just a NEWLINE within
the variable assignment will also show up.

Jython Lists

列表是一种序列数据类型。它是由逗号分隔的项组成的集合,不一定相同类型,存储在方括号中。可以使用基于 0 的索引访问列表中的各个项。

以下代码块总结了 Python 中列表的用法。

list1 = ['physics', 'chemistry', 1997, 2000];
list2 = [1, 2, 3, 4, 5, 6, 7 ];
print "list1[0]: ", list1[0]
print "list2[1:5]: ", list2[1:5]

下表描述了与 Jython 列表相关的一些最常见的 Jython 表达式。

Jython Expression

Description

len(List)

Length

List[2]=10

Updation

Del List[1]

Deletion

List.append(20)

Append

List.insert(1,15)

Insertion

List.sort()

Sorting

Jython Tuples

元组是一个不可变的集合,其中逗号分隔的数据项存储在括号中。不能删除或修改元组中的元素,也不能向元组集合中添加元素。以下代码块显示了元组操作。

tup1 = ('physics','chemistry‘,1997,2000);
tup2 = (1, 2, 3, 4, 5, 6, 7 );
print "tup1[0]: ", tup1[0]
print "tup2[1:5]: ", tup2[1:5]

Jython Dictionary

Jython 字典类似于 Java 集合框架中的 Map 类。它是键值对集合。以逗号分隔的键值对括在花括号中。字典对象不会遵循基于 0 的索引来检索其内部的元素,因为它们是通过散列技术存储的。

相同的键不会在字典对象中出现多次。但是,多个键可以具有相同的值。下面解释了字典对象可用的不同函数。

dict = {'011':'New Delhi','022':'Mumbai','033':'Kolkata'}
print "dict[‘011’]: ",dict['011']
print "dict['Age']: ", dict['Age']

下表描述了与字典相关的一些最常见的 Jython 表达式。

Jython Expression

Description

dict.get(‘011’)

Search

len(dict)

Length

dict[‘044’] = ‘Chennai’

Append

del dict[‘022’]

Delete

dict.keys()

list of keys

dict.values()

List of values

dict.clear()

Removes all elements

Jython - Using Java Collection Types

除了 Python 的内置数据类型,Jython 还具有通过导入 java.util package 使用 Java 集合类的好处。以下代码介绍了给定的类 −

  1. 具有 add() 的 Java ArrayList 对象

  2. remove()

  3. ArrayList类的get()和set()方法。

import java.util.ArrayList as ArrayList
arr = ArrayList()
arr.add(10)
arr.add(20)
print "ArrayList:",arr
arr.remove(10) #remove 10 from arraylist
arr.add(0,5) #add 5 at 0th index
print "ArrayList:",arr
print "element at index 1:",arr.get(1) #retrieve item at index 1
arr.set(0,100) #set item at 0th index to 100
print "ArrayList:",arr

上述Jython脚本生成以下输出−

C:\jython27\bin>jython arrlist.py
ArrayList: [10, 20]
ArrayList: [5, 20]
element at index 1: 20
ArrayList: [100, 20]

Jarray Class

Jython还实现了 Jarray Object ,它允许在Python中构建Java数组。为了使用jarray,只需在Jython中定义一个序列类型,然后将该类型与序列中包含的对象类型一起传递给jarrayobject。jarray中的所有值必须是相同的类型。

下表显示了与jarray一起使用的字符类型代码。

Character Typecode

Corresponding Java Type

Z

Boolean

C

char

B

byte

H

short

I

int

L

long

F

float

D

double

以下示例显示了jarray的构建。

my_seq = (1,2,3,4,5)
from jarray import array
arr1 = array(my_seq,'i')
print arr1
myStr = "Hello Jython"
arr2 = array(myStr,'c')
print arr2

此处 my_seq 被定义为整数的元组。它被转换为Jarray arr1。第二个示例显示Jarray arr2是从 mySttr string 序列构建的。上述脚本 jarray.py 的输出如下−

array('i', [1, 2, 3, 4, 5])
array('c', 'Hello Jython')

Jython - Decision Control

决策制定结构有一个或多个条件,由程序进行评估或测试,以及一条或多条语句,在确定条件为真时执行这些语句,或者选择性地执行其他语句,在确定条件为假时执行这些语句。

下列插图显示了在大多数编程语言中发现的典型决策制定结构的一般形式 -

decision control

Jython 不使用大括号指示在条件为真或假时要执行的语句块(就像在 Java 中一样)。相反,使用统一缩进(从左边缘开始的空格)来形成语句块。这种统一缩进块使条件代码在给定在“if”语句中的条件为真时执行。

类似的块可能会在可选的“else”语句之后出现。Jython 还提供了 elif statement ,使用它可以测试连续的条件。在此情况下, else clause 将最后出现,并且仅在所有前面的条件都失败时执行。使用 if..elif..else 的一般语法如下。

if expression1:
   statement(s)
elif expression2:
   statement(s)
elif expression3:
   statement(s)
else:
   statement(s)

在以下示例中,如果使用 ..elif ..else 构造来计算用户输入的金额的不同值折扣。

discount = 0
amount = input("enter Amount")
if amount>1000:
   discount = amount*0.10
elif amount>500:
   discount = amount*0.05
else:
   discount = 0
print 'Discount = ',discount
print 'Net amount = ',amount-discount

以上代码的输出如下所示。

enter Amount1500
Discount = 150.0
Net amount = 1350.0
enter Amount600
Discount = 30.0
Net amount = 570.0
enter Amount200
Discount = 0
Net amount = 200

Jython - Loops

通常情况下,程序中的语句按顺序执行:函数中的第一个语句首先执行,然后执行第二个语句,依此类推。有时您需要执行多次代码块。提供这种重复功能的语句称为 looping statements

在 Jython 中,可以使用两个语句来形成一个循环,即 −

  1. The while statement and

  2. The for statement

The WHILE Loop

Jython 中的 while 循环语句类似于 Java 中的语句。只要给定的条件为真,它将重复执行一个语句块。以下流程图描述了 while 循环的行为。

while loop

while 语句的语法如下所示。

while expression:
   statement(s)

以下 Jython 代码使用 while 循环重复增加并打印一个变量的值,直到它小于零。

count = 0
while count<10:
   count = count+1
   print "count = ",count
print "Good Bye!"

Output - 输出如下所示。

count =  1
count =  2
count =  3
count =  4
count =  5
count =  6
count =  7
count =  8
count =  9
count =  10
Good Bye!

The FOR Loop

Jython 中的 FOR 循环不是 Java 中的计数循环。相反,它有能力遍历字符序列、列表或元组等类型中的元素。Jython 中 FOR 语句的语法如下所示 −

for iterating_var in sequence:
   statements(s)

我们可以使用 FOR 语句来显示字符串中的每个字符以及列表或元组中的每个项目,如下所示 −

#each letter in string
for letter in 'Python':
   print 'Current Letter :', letter

Output - 输出如下所示。

Current Letter : P
Current Letter : y
Current Letter : t
Current Letter : h
Current Letter : o
Current Letter : n

让我们考虑另一个如下实例。

#each item in list
libs = [‘PyQt’, 'WxPython',  'Tkinter']
for lib in libs:        # Second Example
   print 'Current library :', lib

Output - 输出如下所示。

Current library : PyQt
Current library : WxPython
Current library : Tkinter

下面是另一个需要考虑的实例。

#each item in tuple
libs = (‘PyQt’, 'WxPython',  'Tkinter')
for lib in libs:        # Second Example
   print 'Current library :', lib

Output - 以上程序的输出如下所示。

Current library : PyQt
Current library : WxPython
Current library : Tkinter

在 Jython 中, for 语句也用于在 range() 函数生成的一系列数字上进行迭代。range() 函数采用如下形式 −

range[([start],stop,[step])

默认情况下,start 和 step 参数是 0 和 1。生成的最后一个数字是 stop step。FOR 语句遍历 range() function 形成的列表。例如 −

for num in range(5):
   print num

产出如下所示 −

0
1
2
3
4

Jython - Functions

复杂编程逻辑被打分成一个或多个独立且可重复使用的语句块,称为函数。Python 的标准库包含大量内置函数。人们还可以使用 def 关键字定义自己的函数。用户定义的函数名称后面紧跟一个语句块,该语句块构成其主体,以 return 语句结束。

一旦定义,它可以从任何环境中多次调用。让我们考虑以下代码来说明这一点。

#definition of function
defSayHello():
   "optional documentation string"
   print "Hello World"
   return

#calling the function
SayHello()

可以设计一个函数从调用环境接收一个或多个参数/参数。在调用此类参数化函数时,您需要提供与函数定义中使用的数据类型类似的相同数量的参数,否则 Jython 解释器会抛出 TypeError 异常。

Example

#defining function with two arguments
def area(l,b):
   area = l*b
   print "area = ",area
   return

#calling function
length = 10
breadth = 20
#with two arguments. This is OK
area(length, breadth)
#only one argument provided. This will throw TypeError
area(length)

output 将如下:

area = 200
Traceback (most recent call last):
   File "area.py", line 11, in <module>
   area(length)
TypeError: area() takes exactly 2 arguments (1 given)

执行其中定义的步骤后,被调函数返回到调用环境。如果在函数定义中的 return 关键字前面提到了表达式,它可以返回数据。

#defining function
def area(l,b):
   area = l*b
   print "area = ",area
   return area

#calling function
length = 10
breadth = 20
#calling function and obtaining its reurned value
result = area(length, breadth)
print "value returned by function : ", result

如果从 Jython 提示符执行上述脚本,将获得以下输出。

area = 200
value returned by function : 200

Jython - Modules

模块是一个 Jython 脚本,其中定义了一个或多个相关的函数、类或变量。这允许对 Jython 代码进行逻辑组织。可以在另一个 Jython 脚本中使用在模块中定义的程序元素,方法是从其中导入模块或特定元素(函数/类)。

在以下代码(hello.py)中,定义了一个函数 SayHello()

#definition of function
defSayHello(str):
   print "Hello ", str
   return

要从另一个脚本中使用 SayHello() 函数,请在其中导入 hello.py module

import hello
hello.SayHello("TutorialsPoint")

但是,这将导入模块中定义的所有函数。要从模块导入特定函数,请使用以下语法。

from modname import name1[, name2[,... nameN]

例如,要仅导入 SayHello() 函数,请将上述脚本更改如下。

from hello import SayHello
SayHello("TutorialsPoint")

在调用函数时,无需前缀模块的名称。

Jython - Package

包含一个或多个 Jython 模块的任何文件夹都被识别为一个包。但是,它必须有一个名为 $\{\s0\}$ 的特殊文件,该文件提供要使用的函数索引。

我们现在了解一下如何创建和导入包。

$\{\s1}$ − 创建名为 $\{\s2\}$ 的文件夹,然后创建并保存以下 $\{\s3\}$ 模块:

#fact.py
def factorial(n):
   f = 1
   for x in range(1,n+1):
      f = f*x
   return f
#sum.py
def add(x,y):
   s = x+y
   return s
#mult.py
def multiply(x,y):
   s = x*y
   return s

$\{\s4}$ − 在 package1 文件夹中创建并保存 $\{\s5\}$ 文件,其内容如下:

#__init__.py
from fact import factorial
from sum import add
from mult import multiply

$\{\s6}$ − 在 package1 文件夹外创建以下 Jython 脚本,名为 $\{\s7\}$。

# Import your Package.
import package1

f = package1.factorial(5)
print "factorial = ",f
s = package1.add(10,20)
print "addition = ",s
m = package1.multiply(10,20)
print "multiplication = ",m

$\{\s8}$ − 从 Jython 提示符执行 test.py。将获得以下输出。

factorial = 120
addition = 30
multiplication = 200

Jython - Java Application

下载 jython-standalone-2.7.0.jar - 从他们的官方下载页面嵌入 Jython 入 Java 应用程序: http://www.jython.org/downloads.html ,并将此 jar 文件包含在 Java CLASSPATH 环境变量中。

此库包含 PythonInterpreter 类。使用此类的对象,可以使用 execfile() 方法执行任何 Python 脚本。PythonInterpreter 使您能够直接使用 PyObjects 。Jython 运行时系统已知的所有对象均由 PyObject 类的实例或其一个子类表示。

PythonInterpreter 类有一些常用方法,在下面给出的表中对此进行了说明。

Sr.No.

Method & Description

1

setIn(PyObject) 设置用于标准输入流的 Python 对象

2

setIn(java.io.Reader) 设置一个用于标准输入流的 java.io.Reader

3

setIn(java.io.InputStream) 设置一个用于标准输入流的 java.io.InputStream

4

setOut(PyObject) 设置用于标准输出流的 Python 对象

5

setOut(java.io.Writer) 设置用于标准输出流的 java.io.Writer

6

setOut(java,io.OutputStream) 设置用于标准输出流的 java.io.OutputStream

7

setErr(PyObject) 设置用于标准错误流的 Python 错误对象

8

setErr(java.io.Writer 设置一个用于标准错误流的 java.io.Writer

9

setErr(java.io.OutputStream) 设置一个用于标准错误流的 java.io.OutputStream

10

eval(String) 将字符串作为 Python 来源进行评估并返回结果

11

eval(PyObject) 评估一个 Python 代码对象并返回结果

12

exec(String) 在本地命名空间中执行一个 Python 来源字符串

13

exec(PyObject) 在本地命名空间中执行一个 Python 代码对象

14

execfile(String filename) 在本地命名空间中执行一个 Python 来源文件

15

execfile(java.io.InputStream) 在本地命名空间中执行一个 Python 来源的输入流

16

compile(String) 将 Python 源字符串编译为表达式或模块

17

compile(script, filename) 将 Python 源脚本编译为表达式或模块

18

set(String name, Object value) 设置局部命名空间中的 Object 类型变量

19

set(String name, PyObject value) 设置局部命名空间中的 PyObject 类型变量

20

get(String) 获取局部命名空间中变量的值

21

get(String name, Class javaclass 获取局部命名空间中变量的值。此值将作为给定 Java 类的实例返回。

以下代码块是 Java 程序,它嵌入了 PythonInterpreter 对象的 “hello.py”.usingexecfile() 方法的 Jython 脚本。它还展示了如何使用 set() 和 get() 方法设置或读取 Python 变量。

import org.python.util.PythonInterpreter;
import org.python.core.*;

public class SimpleEmbedded {
   public static void main(String []args) throws PyException {
      PythonInterpreter interp = new PythonInterpreter();
      System.out.println("Hello, world from Java");
      interp.execfile("hello.py");
      interp.set("a", new PyInteger(42));
      interp.exec("print a");
      interp.exec("x = 2+2");
      PyObject x = interp.get("x");
      System.out.println("x: "+x);
      System.out.println("Goodbye ");
   }
}

编译并运行上述 Java 程序以获取以下输出。

Hello, world from Java
hello world from Python
42
x: 4
Goodbye

Jython - Eclipse Plugin

PyDev 是 Eclipse IDE 的一个开源插件,它支持使用 Python、Jython 以及 IronPython 开发项目。它托管在 https://pydev.org 。在 Eclipse IDE 中安装 PyDev 插件的分步过程如下。

Step 1 − 打开 Eclipse IDE,并从帮助菜单选择 Install New Software 选项。

install new software

Step 2 − 在与使用标签相对的文本框中输入 http://pydev.org/updates ,然后单击添加。选择列表中的所有可用条目,然后单击下一步。向导将花费几分钟完成安装,它将提示重新启动 IDE。

available software

Step 3 − 现在从窗口菜单中选择首选项选项。首选项对话框如下所示

preferences

Step 4 − 展开解释器节点,然后在左窗格中选择 Jython 解释器。在右窗格中,单击新建以提供 jython.jar file 的路径。

jython jar

现在,我们已准备好使用 Eclipse 启动一个 Jython 项目。

Jython - A Project in Eclipse

要在eclipse中制作一个项目,我们应该按照下面给出的步骤进行。

Step 1 – 选择File ? New ? Project。从筛选对话框中选择 PyDev 。 给出项目名称、项目类型,然后单击Finish。

pydev

Step 2 – Hello项目现在将显示在左侧的项目浏览器中。右键单击添加hello.py。

hellopy

Step 3 –一个空的hello.py将会出现在编辑器中。写Jython代码并保存。

empty hellopy

Step 4 –单击菜单栏上的Run按钮。输出将以如下所示出现在控制台窗口中。

run button

Jython - NetBeans Plugin and Project

Python 和 Jython 对 NetBeans 的支持可通过 nbPython plugin 获得。从以下 URL 下载插件 - http://plugins.netbeans.org/plugin/56795 。将下载的压缩文件解压到某个文件夹中。例如 - d:\nbplugin 。要安装 NetBeans 插件,请按照以下步骤操作。

Step 1 - 启动 Netbeans IDE ,然后转到“工具/插件”以打开插件管理器。选择“已下载”标签并浏览到已解压下载文件中的文件夹。NetBeans 窗口将按如下所示显示。

netbeans ide

Step 2 - 下一步是选择所有 .nbm 文件并单击“打开”。

nbm

Step 3 - 单击“安装”按钮。

install button

Step 4 - 接受以下许可协议以继续。

agreement

忽略有关插件的来源不可信的警告,并重新启动 IDE 以继续。

Jython Project in NetBeans

重新启动后,通过选择“文件/新建”来启动一个新项目。现在,类别列表中将提供 Python 类别。选择它来继续。

category

如果系统已安装 Python,其版本/版本将被自动检测,并显示在 Python 平台下拉列表中。但是,Jython 不会被列出。单击管理按钮进行添加。

python

点击“新建”按钮添加 Jython 可执行文件中的平台名称和路径。

jython executable

Jython 现在可用于平台列表中。从下拉列表中选择,具体如以下屏幕截图所示。

dropdown list

我们现在可以在下一个窗口中填写项目名称、位置和主文件。

project name

项目结构将显示在 NetBeans IDE 的项目窗口中,编辑器窗口中将显示一个模板 Python 代码。

projects window
template python code

构建并执行 Jython 项目以在 NetBeans IDE 的输出窗口获得以下结果。

output window

Jython - Servlets

Java servlet 是使用最广泛的 Web 开发技术。我们可以使用 Jython 来编写 servlet,这增加了 Java 提供的功能之外的许多更多优势,因为现在我们还可以利用 Python 语言功能。

我们将使用 NetBeans IDE 使用 Jython servlet 开发 Java Web 应用程序。确保 nbPython plugin 已安装在 NetBeans 安装中。通过选择以下路径启动一个新项目以构建 Web 应用程序 - File → New Project → Java web → New Web Application

提供项目名称和位置。IDE 将创建项目文件夹结构。在 Projects 窗口中的源包节点下添加 Java servlet 文件 (ServletTest.java)。这会在项目的 lib 文件夹中添加 servlet-api.jar 。此外,让 IDE 创建 web.xml descriptor file 。在 ServletTest.java 中添加以下代码。

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletTest extends HttpServlet {

   public void doGet (HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      doPost(request, response);
   }

   public void doPost (HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
      response.setContentType ("text/html");
      PrintWriter toClient = response.getWriter();

      toClient.println (
         "<html>
            <head>
               <title>Servlet Test</title>" + "
            </head>
            <body>
               <h1>Servlet Test</h1>
            </body>
         </html>"
      );
   }
}

NetBeans 创建的 web.xml 文件将如下所示:

<web-app>
   <servlet>
      <servlet-name>ServletTest</servlet-name>
      <servlet-class>ServletTest</servlet-class>
   </servlet>

   <servlet-mapping>
      <servlet-name>ServletTest</servlet-name>
      <url-pattern>/ServletTest</url-pattern>
   </servlet-mapping>
</web-app>

构建并运行项目以获取浏览器窗口中 <h1> 标签中显示的文本 Servlet Test 。因此,我们在应用程序中添加了一个常规 Java servlet。

现在,我们将添加 Jython Servlet。Jython servlet 通过一个中间 Java servlet(也称为 PyServlet)来工作。PyServlet.class 存在于 jython standalone.jar 中。将其添加到 WEB-INF/lib 文件夹中。

下一步是配置 web.xml 以便在每次提出对任何 *.py file 的请求时调用 PyServlet。这应通过在其中添加以下 xml 代码来完成。

<servlet>
   <servlet-name>PyServlet</servlet-name>
   <servlet-class>org.python.util.PyServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
   <servlet-name>PyServlet</servlet-name>
   <url-pattern>*.py</url-pattern>
</servlet-mapping>

完整的 web.xml 代码如下所示。

<web-app>
   <servlet>
      <servlet-name>ServletTest</servlet-name>
      <servlet-class>ServletTest</servlet-class>
   </servlet>

   <servlet>
      <servlet-name>PyServlet</servlet-name>
      <servlet-class>org.python.util.PyServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>

   <servlet-mapping>
      <servlet-name>ServletTest</servlet-name>
      <url-pattern>/ServletTest</url-pattern>
   </servlet-mapping>

   <servlet-mapping>
      <servlet-name>PyServlet</servlet-name>
      <url-pattern>*.py</url-pattern>
   </servlet-mapping>
</web-app>

将以下 Jython 代码放在项目文件夹中的 WEB-INF 文件夹中,作为 JythonServlet.py,它等效于之前的 ServletTest.java。

from javax.servlet.http import HttpServlet
class JythonServlet1 (HttpServlet):
   def doGet(self,request,response):
      self.doPost (request,response)
   def doPost(self,request,response):
      toClient = response.getWriter()
      response.setContentType ("text/html")

      toClient.println (
         "<html>
            <head>
               <title>Servlet Test</title>" + "
            </head>
            <body>
               <h1>Servlet Test</h1>
            </body>
         </html>"
      )

构建项目并在浏览器中打开以下 URL:

浏览器将显示 Servlet Test 中的 <h1> 标签,如同 Java Servlet 输出一样。

Jython - JDBC

Jython 使用 zxJDBC package ,这是一个易于使用的 Python 围绕 JDBC 的封装器。zxJDBC 桥接两个标准: JDBC 是 Java 中用于数据库访问的标准平台; DBI 是 Python 应用程序的标准数据库 API。

ZxJDBC 提供一个符合 DBI 2.0 标准的 JDBC 接口。JDBC 可用 200 多个驱动程序,它们均可与 zxJDBC 配合使用。所有主要关系数据库都可以使用高性能驱动程序,包括 −

  1. DB2

  2. Derby

  3. MySQL

  4. Oracle

  5. PostgreSQL

  6. SQLite

  7. SQL Server and

  8. Sybase.

可从 https://sourceforge.net/projects/zxjdbc/http://www.ziclix.com/zxjdbc/ 下载 ZxJDBC 包。下载的归档文件包含 ZxJDBC.jar,应当将其添加到 CLASSPATH 环境变量中。

我们打算使用 MySQL 数据库建立数据库连接。为此,需要 MySQL 的 JDBC 驱动程序。从以下链接下载 MySQL J connector - https://dev.mysql.com/downloads/connector/j/ ,并将 mysql connector java-5.1.42-bin.jar 包含在 CLASSPATH 中。

登录到 MySQL 服务器,并使用下列结构在 test 数据库中创建一个 student 表 −

Field

Type

Width

Name

Varchar

10

Age

Int

3

Marks

Int

3

在其中添加一些记录。

Name

Age

Marks

Ravi

21

78

Ashok

20

65

Anil

22

71

将以下 Jython 脚本作为 dbconnect.py 创建。

url = "jdbc:mysql://localhost/test"
user = "root"
password = "password"
driver = "com.mysql.jdbc.Driver"
mysqlConn = zxJDBC.connect(url, user, password, driver)
mysqlConn = con.cursor()
mysqlConn.execute(“select * from student)
for a in mysql.fetchall():
   print a

从 Jython 提示符处执行上述脚本。student 表中的记录将如下所示 −

(“Ravi”, 21, 78)
(“Ashok”, 20, 65)
(“Anil”,22,71)

这就说明了 Jython 中建立 JDBC 的过程。

Jython - Using the Swing GUI library

Jython 的主要功能之一是它能够在 JDK 中使用 Swing GUI 库。标准 Python 发行版(通常称为 CPython)随附 $\{\s9\}$。其他 GUI 库,如 $\{\s10\}$ 和 $\{\s11\}$,也可以与它一起使用,但 Swing 库提供了与平台无关的 GUI 工具包。

在 Jython 中使用 Swing 库比在 Java 中使用它要容易得多。在 Java 中,必须使用匿名类来创建事件绑定。在 Jython 中,我们可以简单地为相同目的传递一个函数。

通过声明 $\{\s12\}$ 的一个对象并将其可见属性设置为 true 来创建基本顶级窗口。为此,需要从 swing 包中导入 Jframe 类。

from javax.swing import JFrame

JFrame 类具有多个具有不同数量参数的构造器。我们将使用其中一个,它将一个字符串作为参数并将其设置为标题。

frame = JFrame(“Hello”)

在将其可见属性设置为 true 之前,设置帧的大小和位置属性。将以下代码存储为 $\{\s13\}$。

from javax.swing import JFrame

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(300,200)
frame.setVisible(True)

从命令提示符运行上面的脚本。它将显示以下显示一个窗口的输出。

window

Swing GUI 库以 Java 中的 javax.swing 包形式提供。它的主要容器类 JFrameJDialog 分别派生自 AWT 库中的 Frame 和 Dialog 类。 JLabel, JButton, JTextField, 等其他 GUI 控件派生自 JComponent 类。

以下插图显示了 Swing 包类层次结构。

swing package class hierarchy

下表总结了 Swing 库中的不同 GUI 控件类−

Sr.No.

Class & Description

1

JLabel JLabel 对象是一个用于在容器中放置文本的组件。

2

JButton 此类创建有标签的按钮。

3

JColorChooser JColorChooser 提供一个控件面板,旨在允许用户操作和选择颜色。

4

JCheckBox JCheckBox 是一个图形组件,可以处于 on (真)或 off (假)状态。

5

JRadioButton JRadioButton 类是一个图形组件,它可以在一组中处于打开(真)或关闭(假)状态。

6

JList JList 组件向用户显示一个可滚动的文本项目列表。

7

JComboBox JComboBox 组件向用户显示一个下拉项目列表

8

JTextField JTextField 对象是一个文本组件,允许编辑单行文本。

9

JPasswordField JPasswordField 对象是一个专门用于密码输入的文本组件。

10

JTextArea JTextArea 对象是一个文本组件,允许编辑多行文本。

11

ImageIcon ImageIcon 控件是 Icon 界面的实现,可从图像绘制 Icon

12

JScrollbar Scrollbar 控件表示滚动条组件,以便用户可以从值范围中进行选择。

13

JOptionPane JOptionPane 提供了一组标准对话框,提示用户输入值或告知其某些信息。

14

JFileChooser JFileChooser 控件表示一个对话框窗口,用户可以从中选择文件。

15

JProgressBar 随着任务接近完成,进度条显示任务的完成百分比。

16

JSlider A JSlider 控件通过在一个有界区间内滑动旋钮让用户以图形方式选择一个值。

17

JSpinner A JSpinner 控件是一个单行输入字段,允许用户从一个有序序列中选择一个数字或对象值。

我们会在后续示例中使用其中一些控件。

Jython - Layout Management

Java 中的布局管理器是一类,它们管理控件在容器对象中的放置,如 Frame, DialogPanel 。布局管理器维护控件在框架中的相对位置,即使分辨率更改或框架本身调整大小。

这些类实现了 Layout interface 。以下布局管理器定义在 AWT library 中:

  1. BorderLayout

  2. FlowLayout

  3. GridLayout

  4. CardLayout

  5. GridBagLayout

以下布局管理器定义在 Swing library 中:

  1. BoxLayout

  2. GroupLayout

  3. ScrollPaneLayout

  4. SpringLayout

我们将在以下示例中使用 AWT 布局管理器和 swing 布局管理器。

  1. Absolute Layout

  2. Flow Layout

  3. Grid Layout

  4. Border Layout

  5. Box Layout

  6. Group Layout

让我们现在详细讨论每一个这些。

Absolute Layout

在我们探索以上所有布局管理器之前,必须查看容器中控件的绝对定位。我们必须将框架对象的布局方法设置为“None”。

frame.setLayout(None)

然后通过调用 setBounds() 方法放置控件。它有四个参数 - x 位置、y 位置、宽度和高度。

例如 - 要将一个按钮对象放置在绝对位置并使用绝对大小。

btn = JButton("Add")
btn.setBounds(60,80,60,20)

类似地,所有控件都可以通过正确分配位置和大小来放置。这种布局相对易于使用,但当窗口调整大小,或者在屏幕分辨率更改时执行程序时,它无法保留其外观。

在以下 Jython 脚本中,三个 Jlabel 对象分别用来显示文本“phy”、“maths”和“Total”。在前三个前面放置 JTextField 对象。一个 Button 对象被放置在“Total”标签上方。

首先,创建 JFrame 窗口,并将布局设置为 none。

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(300,200)
frame.setLayout(None)

然后根据其绝对位置和大小添加不同的控件。下面给出了完整的代码 −

from javax.swing import JFrame, JLabel, JButton, JTextField

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(300,200)
frame.setLayout(None)

lbl1 = JLabel("Phy")
lbl1.setBounds(60,20,40,20)
txt1 = JTextField(10)
txt1.setBounds(120,20,60,20)
lbl2 = JLabel("Maths")
lbl2.setBounds(60,50,40,20)
txt2 = JTextField(10)
txt2.setBounds(120, 50, 60,20)
btn = JButton("Add")
btn.setBounds(60,80,60,20)
lbl3 = JLabel("Total")
lbl3.setBounds(60,110,40,20)
txt3 = JTextField(10)
txt3.setBounds(120, 110, 60,20)

frame.add(lbl1)
frame.add(txt1)
frame.add(lbl2)
frame.add(txt2)
frame.add(btn)
frame.add(lbl3)
frame.add(txt3)
frame.setVisible(True)

以上代码的输出如下。

add

Jython FlowLayout

FlowLayout 是容器类的默认布局管理器。它从左到右、然后从上到下的方向排列控件。

在以下示例中,一个 Jlabel 对象、一个 JTextField 对象和一个 JButton 对象将使用 FlowLayout 管理器显示在 JFrame 中。首先,让我们从 javax.swing 包和 java.awt 包导入所需的类。

from javax.swing import JFrame, JLabel, JButton, JTextField
from java.awt import FlowLayout

然后创建一个 JFrame 对象并设置它的位置以及大小属性。

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(200,200)
Set the layout manager for the frame as FlowLayout.
frame.setLayout(FlowLayout())

现在为 JLabel、JTextfield 和 JButton 类声明对象。

label = JLabel("Welcome to Jython Swing")
txt = JTextField(30)
btn = JButton("ok")

最后,通过调用 JFrame 类的 add() 方法将这些控件添加到框架中。

frame.add(label)
frame.add(txt)
frame.add(btn)

要显示框架,将它的 visible 属性设置为 true。完整的 Jython 脚本及其输出如下 −

from javax.swing import JFrame, JLabel, JButton, JTextField
from java.awt import FlowLayout

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(200,200)

frame.setLayout(FlowLayout())

label = JLabel("Welcome to Jython Swing")
txt = JTextField(30)
btn = JButton("ok")

frame.add(label)
frame.add(txt)
frame.add(btn)
frame.setVisible(True)
welcome to jython swing

Jython GridLayout

Gridlayout 管理器允许将控件放置在矩形网格中。一个控件放置在网格的每个单元格中。

在以下示例中,GridLayout 应用于一个 JFrame 对象,将其划分为 4 行 4 列。一个 JButton 对象将被放置在网格的每个单元格中。

我们首先导入所需的库 −

from javax.swing import JFrame, JButton
from java.awt import GridLayout

然后创建 JFrame 容器 −

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(400,400)

现在,应用 GridLayout 并将其维度指定为 4 乘 4。

frame.setLayout(GridLayout(4,4))

我们现在应该使用两个 FOR 循环,每个循环从 1 到 4,以便 16 个 JButton 对象被放置在后续单元格中。

k = 0
frame.setLayout(GridLayout(4,4))
for i in range(1,5):
   for j in range(1,5):
      k = k+1
      frame.add(JButton(str(k)))

最后将框架的可见性设置为真。完整的 Jython 代码如下所示。

from javax.swing import JFrame, JButton
from java.awt import GridLayout

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(400,400)

frame.setLayout(GridLayout(4,4))

k = 0
for i in range(1,5):
   for j in range(1,5):
      k = k+1
      frame.add(JButton(str(k)))

frame.setVisible(True)

以上代码的输出如下所示 -

jython code

Jython BorderLayout

BorderLayout 管理器将容器划分为五个地理区域并在每个区域放置一个组件。这些区域由确定的常量表示,如下所示:

  1. BorderLayout.NORTH

  2. BorderLayout.SOUTH

  3. BorderLayout.EAST

  4. BorderLayout.WEST

  5. BorderLayout.CENTER

我们考虑以下示例:

jython borderlayout

Jython BoxLayout

BoxLayout 类在 javax.swing package 中定义。它用于在容器中垂直或水平排列组件。方向由以下常量决定:

  1. X_AXIS

  2. Y_AXIS

  3. LINE_AXIS

  4. PAGE_AXIS

整型常量指定容器组件应沿其布局的轴。当容器具有默认组件方向时,LINE_AXIS 指定组件从左到右布局,PAGE_AXIS 指定组件从上到下布局。

在以下示例中,将面板(来自 JPanel 类)添加到 JFrame 对象中。对其应用垂直 BoxLayout,并添加更多两个面板(顶部和底部)。这两个内部面板各有两个按钮,水平 Boxlayout 中添加了这俩个按钮。

让我们首先创建顶层 JFrame 窗口。

frame = JFrame()
frame.setTitle("Buttons")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setSize(300, 150)

声明 JPanel 对象,它具有垂直 BoxLayout。将其添加到顶层框架。

panel = JPanel()
panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))
frame.add(panel)

在此面板中,添加更多两个面板(顶部和底部)。每一个都添加了两个 JButton 对象,并在它们之间添加了占位符,占位符为 25 像素。

###top panel
top = JPanel()
top.setLayout(BoxLayout(top, BoxLayout.X_AXIS))
b1 = JButton("OK")
b2 = JButton("Close")
top.add(Box.createVerticalGlue())
top.add(b1)
top.add(Box.createRigidArea(Dimension(25, 0)))
top.add(b2)

同样构造底部面板。

###bottom panel
bottom = JPanel()
bottom.setLayout(BoxLayout(bottom, BoxLayout.X_AXIS))
b3 = JButton("Open")
b4 = JButton("Save")
bottom.add(b3)
bottom.add(Box.createRigidArea(Dimension(25, 0)))
bottom.add(b4)
bottom.add(Box.createVerticalGlue())

请注意, createRigidArea() 函数用于在两个按钮之间创建 25 像素的空间。 createVerticalGlue() 函数还占据布局的前导或尾随空间。

首先,添加顶部和底部面板,并将 frame 的可见性属性设置为真。完整的代码如下所示:

from java.awt import Dimension
from javax.swing import JButton, JFrame,JPanel,BoxLayout,Box

frame = JFrame()
frame.setTitle("Buttons")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setSize(300, 150)

panel = JPanel()
panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))
frame.add(panel)

###top panel
top = JPanel()
top.setLayout(BoxLayout(top, BoxLayout.X_AXIS))
b1 = JButton("OK")
b2 = JButton("Close")
top.add(Box.createVerticalGlue())
top.add(b1)
top.add(Box.createRigidArea(Dimension(25, 0)))
top.add(b2)

###bottom panel
bottom = JPanel()
bottom.setLayout(BoxLayout(bottom, BoxLayout.X_AXIS))
b3 = JButton("Open")
b4 = JButton("Save")
bottom.add(b3)
bottom.add(Box.createRigidArea(Dimension(25, 0)))
bottom.add(b4)
bottom.add(Box.createVerticalGlue())

panel.add(bottom)
panel.add(top)
frame.setVisible(True)

以上代码将生成以下输出。

jython boxlayout

Jython GroupLayout

GroupLayout 管理器以分层的方式对组件进行分组。分组由两个类 SequentialGroupParallelGroup 完成,两者都实现了 Java 中的 Group 接口。

布局过程分为两个步骤。第一步,组件与水平轴一起放置,第二步与垂直轴一起放置。每个组件必须在布局中定义两次。

有两种排列类型,顺序排列和并行排列。在这两种排列方式中,我们都可以按顺序或并行排列组件。在水平排列中,行称为顺序组,列称为并行组。另一方面,在并行排列中,元素行是并行组,而列(顺序组)是顺序组。

在以下示例中,五个按钮以这样的方式排列,即每一行和每一列中各出现三个按钮。首先,在 JFrame 窗口中添加一个 Jpanel 对象,并将其布局设置为 Grouplayout。

frame =  JFrame()
panel =  JPanel()
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
layout =  GroupLayout(panel)
panel.setLayout(layout)

然后构造 JButton 对象:

buttonD = JButton("D")
buttonR = JButton("R")
buttonY = JButton("Y")
buttonO = JButton("O")
buttonT = JButton("T")

接下来,我们创建一个名为 LeftToRightSequentialGroup ,其中添加了 buttonD 和 buttonY。在其间,放置了一个并行组 ColumnMiddle(垂直添加了其他三个按钮)。

leftToRight = layout.createSequentialGroup()
leftToRight.addComponent(buttonD)
columnMiddle = layout.createParallelGroup()
columnMiddle.addComponent(buttonR)
columnMiddle.addComponent(buttonO)
columnMiddle.addComponent(buttonT)
leftToRight.addGroup(columnMiddle)
leftToRight.addComponent(buttonY)

现在定义一个名为 TopToBottom 的垂直 SequentialGroup。添加一个包含三个按钮的 ParallelGroup 行,然后垂直搁置两个按钮。

topToBottom = layout.createSequentialGroup()
rowTop = layout.createParallelGroup()
rowTop.addComponent(buttonD)
rowTop.addComponent(buttonR)
rowTop.addComponent(buttonY)
topToBottom.addGroup(rowTop)
topToBottom.addComponent(buttonO)
topToBottom.addComponent(buttonT)

最后,将 LeftToRight 组水平设置到布局对象,将 TopToBottom 组垂直设置到布局对象。完整的代码如下 −

from javax.swing import JButton, JFrame,JPanel,GroupLayout

frame = JFrame()
panel = JPanel()
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
layout = GroupLayout(panel)
panel.setLayout(layout)

buttonD = JButton("D")
buttonR = JButton("R")
buttonY = JButton("Y")
buttonO = JButton("O")
buttonT = JButton("T")

leftToRight = layout.createSequentialGroup()
leftToRight.addComponent(buttonD)
columnMiddle = layout.createParallelGroup()
columnMiddle.addComponent(buttonR)
columnMiddle.addComponent(buttonO)
columnMiddle.addComponent(buttonT)
leftToRight.addGroup(columnMiddle)
leftToRight.addComponent(buttonY)

topToBottom = layout.createSequentialGroup()
rowTop = layout.createParallelGroup()
rowTop.addComponent(buttonD)
rowTop.addComponent(buttonR)
rowTop.addComponent(buttonY)
topToBottom.addGroup(rowTop)
topToBottom.addComponent(buttonO)
topToBottom.addComponent(buttonT)

layout.setHorizontalGroup(leftToRight)
layout.setVerticalGroup(topToBottom)

frame.add(panel)
frame.pack()
frame.setVisible(True)

以上代码的输出如下所示 -

jython grouplayout

Jython - Event Handling

Java swing 中的事件处理要求控件(例如 JButton 或 JList 等)向相应的事件侦听器注册。需要使用其事件处理方法覆盖事件侦听器接口或相应的适配器类来实现或创建它们的子类。在 Jython 中,事件处理非常简单。我们可以将任何函数作为控件对应的事件处理函数的属性传递。

让我们首先了解如何在 Java 中处理单击事件。

首先,我们必须导入 java.awt.event package 。接下来,扩展 JFrame 的类必须实现 ActionListener 接口。

public class btnclick extends JFrame implements ActionListener

然后,我们必须声明 JButton 对象,将其添加到框架的 ContentPane 中,然后通过 addActionListener() 方法向其注册 ActionListener。

JButton b1 = new JButton("Click here");
   getContentPane().add(b1);
   b1.addActionListener(this);

现在,必须覆盖 ActionListener 接口的 actionPerformed() 方法来处理 ActionEvent。

以下是完整的 Java 代码 −

import java.awt.event.*;
import javax.swing.*;
public class btnclick extends JFrame implements ActionListener {
   btnclick() {
      JButton b1 = new JButton("Click here");
      getContentPane().add(b1);
      b1.addActionListener(this);
   }

   public void actionPerformed(ActionEvent e) {
      System.out.println("Clicked");
   }

   public static void main(String args[]) {
      btnclick b = new btnclick();
      b.setSize(300,200);
      b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      b.setVisible(true);
   }
}

现在,我们将编写与上述代码同等的 Jython 代码。

首先,我们不需要导入 ActionEvent 或 ActionListener,因为 Jython 的动态类型允许我们在代码中不提这两个类。

其次,不需要实现或创建 ActionListener 的子类。而是直接向 JButton 构造函数提供任何用户定义的函数作为 actionPerformed bean 属性的值。

button = JButton('Click here!', actionPerformed = clickhere)

clickhere() 函数定义为常规的 Jython 函数,用于处理按钮上的单击事件。

def change_text(event):
print clicked!'

以下是 Jython 同等代码。

from javax.swing import JFrame, JButton

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(300,200)

def clickhere(event):
   print "clicked"

btn = JButton("Add", actionPerformed = clickhere)
frame.add(btn)

frame.setVisible(True)

Java 和 Jython 代码的输出相同。当单击按钮时,它将在控制台上打印“clicked”消息。

java and jython

在以下 Jython 代码中,在 JFrame 窗口上提供了两个 JTextField 对象来输入“phy”和“maths”中的分数。当单击 JButton 对象时,它会执行 add() 函数。

btn = JButton("Add", actionPerformed = add)

add() 函数通过 getText() 方法读取两个文本字段的内容,并将其解析为整数,以便可以执行加法运算。然后,结果由 setText() 方法放入第三个文本字段中。

def add(event):
   print "add"
   ttl = int(txt1.getText())+int(txt2.getText())
   txt3.setText(str(ttl))

以下是完整代码 −

from javax.swing import JFrame, JLabel, JButton, JTextField
from java.awt import Dimension

frame = JFrame("Hello")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(300,200)
frame.setLayout(None)

def add(event):
   print "add"
   ttl = int(txt1.getText())+int(txt2.getText())
   txt3.setText(str(ttl))

lbl1 = JLabel("Phy")
lbl1.setBounds(60,20,40,20)
txt1 = JTextField(10)
txt1.setBounds(120,20,60,20)
lbl2 = JLabel("Maths")
lbl2.setBounds(60,50,40,20)
txt2 = JTextField(10)
txt2.setBounds(120, 50, 60,20)
btn = JButton("Add", actionPerformed = add)
btn.setBounds(60,80,60,20)
lbl3 = JLabel("Total")
lbl3.setBounds(60,110,40,20)
txt3 = JTextField(10)
txt3.setBounds(120, 110, 60,20)

frame.add(lbl1)
frame.add(txt1)
frame.add(lbl2)
frame.add(txt2)
frame.add(btn)
frame.add(lbl3)
frame.add(txt3)
frame.setVisible(True)

从命令提示符执行上述代码时,将出现以下窗口。输入“物理”、“数学”的分数,然后单击“添加”按钮。结果将相应显示。

phy maths

Jython JRadioButton Event

JRadioButton 类定义在 javax.swing package 中。它创建一个可选的带有开关状态的切换按钮。如果在 ButtonGroup 中添加了多个单选按钮,则它们的选取是互斥的。

在以下示例中,JRadioButton 类和两种 JLabel 被添加到使用垂直 BoxLayout 的 Jpanel 容器中。在 JRadioButton 对象的构造函数中, OnCheck() 函数被设置为 actionPerformed 属性的值。单击单选按钮更改其状态时会执行此函数。

rb1 = JRadioButton("Male", True,actionPerformed = OnCheck)
rb2 = JRadioButton("Female", actionPerformed = OnCheck)

请注意,单选按钮的默认状态为 false(未选择)。按钮 rb1 的初始状态设置为 True(已选择)。

这两个单选按钮被添加到 Radio ButtonGroup 以使其相互排斥,以便当一个被选中时,另一个会自动取消选择。

grp = ButtonGroup()
grp.add(rb1)
grp.add(rb2)

这两个单选按钮以及两个标签使用垂直布局被添加到一个面板对象中,rb2 和 lbl2 之间的垂直高度间隔为 25 像素。

panel = JPanel()
panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))

panel.add(Box.createVerticalGlue())
panel.add(lbl)
panel.add(rb1)
panel.add(rb2)
panel.add(Box.createRigidArea(Dimension(0,25)))
panel.add(lbl1)

此面板被添加到顶级 JFrame 对象,该对象的 visible 属性最终被设置为 'True'。

frame = JFrame("JRadioButton Example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(250,200)
frame.setVisible(True)
The complete code of radio.py is given below:
from javax.swing import JFrame, JPanel, JLabel, BoxLayout, Box

from java.awt import Dimension
from javax.swing import JRadioButton,ButtonGroup
frame = JFrame("JRadioButton Example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(250,200)
panel = JPanel()
panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))
frame.add(panel)

def OnCheck(event):
   lbl1.text = ""
   if rb1.isSelected():
      lbl1.text = lbl1.text+"Gender selection : Male"
   else:
      lbl1.text = lbl1.text+"Gender selection : Female "
      lbl = JLabel("Select Gender")

rb1 = JRadioButton("Male", True,actionPerformed = OnCheck)
rb2 = JRadioButton("Female", actionPerformed = OnCheck)
grp = ButtonGroup()
grp.add(rb1)
grp.add(rb2)

lbl1 = JLabel("Gender Selection :")

panel.add(Box.createVerticalGlue())
panel.add(lbl)
panel.add(rb1)
panel.add(rb2)
panel.add(Box.createRigidArea(Dimension(0,25)))
panel.add(lbl1)

frame.setVisible(True)

运行上述 Jython 脚本并更改单选按钮选择。选择将显示在底部的标签中。

jradiobutton

Jython JCheckBox Event

JRadioButton 一样,JCheckBox 对象也是一个可选按钮,其标题旁边有一个矩形的可选框。这通常用于为用户提供从项目列表中选择多个选项的机会。

在以下示例中,两个复选框和一个来自 swing 包的标签被添加到使用垂直 BoxLayout 的一个 JPanel 中。底部标签显示两个复选框的瞬时选择状态。

这两个复选框都通过带有将 actionPerformed 属性设置为 OnCheck() 函数的构造函数来声明。

box1 = JCheckBox("Check1", actionPerformed = OnCheck)
box2 = JCheckBox("Check2", actionPerformed = OnCheck)

OnCheck() 函数会验证每个复选框的选择状态,并在底部的标签中显示相应的操作。

def OnCheck(event):
   lbl1.text = ""
   if box1.isSelected():
      lbl1.text = lbl1.text + "box1 selected "
   else:
      lbl1.text = lbl1.text + "box1 not selected "
   if box2.isSelected():
      lbl1.text = lbl1.text + "box2 selected"
   else:
      lbl1.text = lbl1.text + "box2 not selected"

这些框和一个 JLabel 对象被添加到 JPanel 中,它们之间添加了 50 像素高度的占位符。

panel = JPanel()
panel.setLayout(BoxLayout(panel, BoxLayout.Y_AXIS))
panel.add(Box.createVerticalGlue())
panel.add(box1)
panel.add(box2)
panel.add(Box.createRigidArea(Dimension(0,50)))
panel.add(lbl1)

面板本身被添加到一个顶级 JFrame 窗口,其 visible 属性最终被设置为 true。

frame = JFrame("JCheckBox Example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(250,150)
frame.add(panel)

frame.setVisible(True)

运行上述代码并对复选框的选择进行实验。两个复选框的瞬时状态显示在底部。

check box

Jython JList Event

swing 包中的 JList 控件为用户提供了可滚动的项目列表以供选择。JComboBox 提供了一个下拉列表的项目。在 Java 中,选择事件通过在 ListSelectionListener 中实现 valueChanged() 方法来处理。在 Jython 中,事件处理程序被分配给了 JList 对象的 valueChanged 属性。

在以下示例中,一个 JList 对象和一个标签被添加到 BorderLayout 中的一个 JFrame 中。JList 使用元组中的项目集合填充。其 valueChanged 属性被设置为 listSelect() 函数。

lang = ("C", "C++", "Java", "Python", "Perl", "C#", "VB", "PHP", "Javascript", "Ruby")
lst = JList(lang, valueChanged = listSelect)

事件处理程序函数获取所选项目的索引,并从 JList 对象获取相应项目以显示在底部的标签上。

def listSelect(event):
   index = lst.selectedIndex
   lbl1.text = "Hello" + lang[index]

JList 和 JLabel 对象使用 BorderLayout 被添加到 JFrame。

完整的代码如下:

from javax.swing import JFrame, JPanel, JLabel, JList
from java.awt import BorderLayout

frame = JFrame("JList Example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(300,250)

frame.setLayout(BorderLayout())

def listSelect(event):
   index = lst.selectedIndex
   lbl1.text = "Hello" + lang[index]

lang = ("C", "C++", "Java", "Python", "Perl", "C#", "VB", "PHP", "Javascript", "Ruby")
lst = JList(lang, valueChanged = listSelect)
lbl1 = JLabel("box1 not selected box2 not selected")
frame.add(lst, BorderLayout.NORTH)
frame.add(lbl1, BorderLayout.SOUTH)

frame.setVisible(True)

以下代码的输出如下。

jlist and jlabel object

Jython - Menus

大多数基于GUI的应用程序在顶部有一个菜单栏。它就在顶层窗口的标题栏下面。javax.swing包有完善的构建有效菜单系统的功能。利用 JMenuBar, JMenuJMenuItem 类的帮助对其进行构建。

在以下示例中,在顶层窗口提供了菜单栏。菜单栏中添加了一个包含三个菜单项目按钮的文件菜单。现在让我们准备好一个带布局设置成BorderLayout的JFrame对象。

frame = JFrame("JMenuBar example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(400,300)
frame.setLayout(BorderLayout())

现在,通过SetJMenuBar()方法激活了一个JMenuBar对象。

bar = JMenuBar()
frame.setJMenuBar(bar)

接下来,声明了一个标题为“文件”的JMenu对象。三个JMenuItem按钮添加到文件菜单中。当单击任何菜单项时,执行ActionEvent处理程序OnClick()函数。它通过actionPerformed属性进行定义。

file = JMenu("File")
newfile = JMenuItem("New",actionPerformed = OnClick)
openfile = JMenuItem("Open",actionPerformed = OnClick)
savefile = JMenuItem("Save",actionPerformed = OnClick)
file.add(newfile)
file.add(openfile)
file.add(savefile)
bar.add(file)

OnClick()事件处理程序通过gwtActionCommand()函数检索JMenuItem按钮的名称,并显示在窗口底部的文本框中。

def OnClick(event):
   txt.text = event.getActionCommand()

文件菜单对象被添加到菜单栏中。最后,一个JTextField控件被添加到JFrame对象的底部。

txt = JTextField(10)
frame.add(txt, BorderLayout.SOUTH)

menu.py的整个代码如下所示 −

from javax.swing import JFrame, JMenuBar, JMenu, JMenuItem, JTextField
from java.awt import BorderLayout

frame = JFrame("JMenuBar example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(400,300)
frame.setLayout(BorderLayout())

def OnClick(event):
   txt.text = event.getActionCommand()

bar = JMenuBar()
frame.setJMenuBar(bar)

file = JMenu("File")
newfile = JMenuItem("New",actionPerformed = OnClick)
openfile = JMenuItem("Open",actionPerformed = OnClick)
savefile = JMenuItem("Save",actionPerformed = OnClick)
file.add(newfile)
file.add(openfile)
file.add(savefile)
bar.add(file)

txt = JTextField(10)
frame.add(txt, BorderLayout.SOUTH)

frame.setVisible(True)

当使用Jython解释器执行上述脚本时,将会显示一个带有文件菜单的窗口。单击它,它的三个菜单项将会下拉。如果单击了任何按钮,它的名称将会显示在文本框控件中。

jython interpreter

Jython - Dialogs

Dialog 对象是一个窗口,出现在用户与其进行交互的基础窗口的顶部。在本章中,我们将看到 Swing 库中定义的预配置对话框。它们是 MessageDialog, ConfirmDialogInputDialog 。它们是由于 JOptionPane 类的静态方法而可以使用。

在以下示例中,File 菜单包含三个 JMenu 项,分别对应于上述三个对话框;每个都执行 OnClick 事件处理程序。

file = JMenu("File")
msgbtn = JMenuItem("Message",actionPerformed = OnClick)
conbtn = JMenuItem("Confirm",actionPerformed = OnClick)
inputbtn = JMenuItem("Input",actionPerformed = OnClick)
file.add(msgbtn)
file.add(conbtn)
file.add(inputbtn)

OnClick() 处理程序函数检索菜单项按钮的标题并调用相应的 showXXXDialog() 方法。

def OnClick(event):
   str = event.getActionCommand()
   if str == 'Message':
      JOptionPane.showMessageDialog(frame,"this is a sample message dialog")
   if str == "Input":
      x = JOptionPane.showInputDialog(frame,"Enter your name")
      txt.setText(x)
   if str == "Confirm":
      s = JOptionPane.showConfirmDialog (frame, "Do you want to continue?")
      if s == JOptionPane.YES_OPTION:
         txt.setText("YES")
      if s == JOptionPane.NO_OPTION:
         txt.setText("NO")
      if s == JOptionPane.CANCEL_OPTION:
         txt.setText("CANCEL")

如果选择了菜单中的消息选项,则会弹出消息。如果单击输入选项,则会弹出一个请求输入的对话框。然后在 JFrame 窗口中的文本框中显示输入的文本。如果选择了确认选项,则会出现一个带有三个按钮的对话框:是、否和取消。用户的选择在文本框中记录。

完整的代码如下:

from javax.swing import JFrame, JMenuBar, JMenu, JMenuItem, JTextField
from java.awt import BorderLayout
from javax.swing import JOptionPane
frame = JFrame("Dialog example")
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setLocation(100,100)
frame.setSize(400,300)
frame.setLayout(BorderLayout())

def OnClick(event):
   str = event.getActionCommand()
   if str == 'Message':
      JOptionPane.showMessageDialog(frame,"this is a sample message dialog")
   if str == "Input":
      x = JOptionPane.showInputDialog(frame,"Enter your name")
      txt.setText(x)
   if str == "Confirm":
      s = JOptionPane.showConfirmDialog (frame, "Do you want to continue?")
      if s == JOptionPane.YES_OPTION:
         txt.setText("YES")
      if s == JOptionPane.NO_OPTION:
         txt.setText("NO")
      if s == JOptionPane.CANCEL_OPTION:
         txt.setText("CANCEL")

bar = JMenuBar()
frame.setJMenuBar(bar)

file = JMenu("File")
msgbtn = JMenuItem("Message",actionPerformed = OnClick)
conbtn = JMenuItem("Confirm",actionPerformed = OnClick)
inputbtn = JMenuItem("Input",actionPerformed = OnClick)
file.add(msgbtn)
file.add(conbtn)
file.add(inputbtn)
bar.add(file)
txt = JTextField(10)
frame.add(txt, BorderLayout.SOUTH)
frame.setVisible(True)

执行上述脚本时,将显示以下带有菜单中三个选项的窗口:

dialog

Message box

message box

Input Box

input box

Confirm Dialog

confirm dialog