- Jython 教程
- Jython - 首页
- Jython - 概述
- Jython - 安装
- Jython - 导入 Java 库
- Jython - 变量和数据类型
- Jython - 使用 Java 集合类型
- Jython - 决策控制
- Jython - 循环
- Jython - 函数
- Jython - 模块
- Jython - 包
- Jython - Java 应用程序
- Jython - Eclipse 插件
- Jython - Eclipse 中的项目
- Jython - NetBeans 插件和项目
- Jython - Servlet
- Jython - JDBC
- Jython - 使用 Swing GUI 库
- Jython - 布局管理
- Jython - 事件处理
- Jython - 菜单
- Jython - 对话框
- Jython 有用资源
- Jython 快速指南
- Jython - 有用资源
- Jython - 讨论
Jython 快速指南
Jython - 概述
Jython 是 Python 编程语言的 JVM 实现。它旨在在 Java 平台上运行。Jython 程序可以导入和使用任何 Java 类。就像 Java 一样,Jython 程序编译成字节码。主要优势之一是,用 Python 设计的用户界面可以使用AWT、Swing 或SWT 包的 GUI 元素。
Jython 最初名为 JPython,后来改名为 Jython,它紧随Guido Van Rossum创建的称为CPython的标准 Python 实现。Jython 由Jim Hugunin于 1997 年创建。Jython 2.0 于 1999 年发布。从那时起,Jython 2.x 版本对应于等效的 CPython 版本。2015 年 5 月发布的 Jython 2.7.0 对应于 CPython 2.7。Jython 3.x 的开发正在进行中。
Python 和 Java 之间的区别
以下是 Python 和 Java 之间的区别:
Python 是一种动态类型语言。因此,不需要变量的类型声明。另一方面,Java 是一种静态类型语言,这意味着变量的类型声明是强制性的并且不能更改。
Python 只有未经检查的异常,而 Java 既有已检查异常也有未经检查的异常。
Python 使用缩进进行作用域,而 Java 使用匹配的花括号。
由于 Python 是一种基于解释器的语言,因此它没有单独的编译步骤。但是,Java 程序需要编译成字节码,然后由 JVM 执行。
Python 支持多重继承,但在 Java 中,多重继承是不可能的。但是,它实现了接口。
与 Java 相比,Python 具有更丰富的内置数据结构(列表、字典、元组,所有内容都是对象)。
Python 和 Jython 之间的区别
以下是 Python 和 Jython 之间的区别:
称为 CPython 的 Python 参考实现是用 C 语言编写的。另一方面,Jython 完全是用 Java 编写的,并且是 JVM 实现。
标准 Python 可用于多个平台。Jython 可用于安装了 JVM 的任何平台。
标准 Python 代码编译成.pyc文件,而 Jython 程序编译成.class文件。
Python 扩展可以用 C 语言编写。Jython 的扩展是用 Java 编写的。
Jython 本质上是多线程的。但是,Python 使用全局解释器锁 (GIL) 机制来实现此目的。
两种实现具有不同的垃圾回收机制。
在下一章中,我们将学习如何在 Jython 中导入 Java 库。
Jython - 安装
在安装 Jython 2.7 之前,请确保系统已安装JDK 7或更高版本。Jython 以可执行 jar 文件的形式提供。从 - https://www.jython.cn/download.html 下载它,然后双击其图标或运行以下命令:
java -jar jython_installer-2.7.0.jar
安装向导将开始,其中必须提供安装选项。以下是系统的安装过程。
向导的第一步要求您选择语言。
第二步提示您接受许可协议。
在下一步中,选择安装类型。建议选择标准安装。
下一个屏幕会询问您有关选项的确认,然后继续完成安装。
安装过程可能需要一些时间才能完成。
安装完成后,从目标目录内的 bin 目录中调用jython.exe。假设 Jython 安装在C:\jython27中,请从命令行执行以下操作。
C:\jython27\bin\jython
将出现 Python 提示符 (>>>),在它前面可以执行任何 Python 语句或 Python 脚本。
Jython - 导入 Java 库
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 库要么没有它们的等效项,要么不如它们好。
- Servlet
- JMS
- J2EE
- Javadoc
- Swing 被认为优于其他 GUI 工具包
任何 Java 包都可以在 Jython 脚本中导入。在这里,以下 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 - 变量和数据类型
变量是计算机内存中命名的存储位置。每个变量可以在其中保存一个数据。与 Java 不同,Python 是一种动态类型语言。因此,在使用 Jython 时也是如此;不会执行变量数据类型的预先声明。与其说是变量的类型决定了可以在其中存储哪些数据,不如说是数据决定了变量的类型。
在以下示例中,变量被分配了一个整数值。使用 type() 内置函数,我们可以验证变量的类型是整数。但是,如果将相同的变量分配给字符串,则 type() 函数将字符串作为相同变量的类型。
> x = 10 >>> type(x) <class 'int'> >>> x = "hello" >>> type(x) <class 'str'>
这解释了为什么 Python 被称为动态类型语言。
以下 Python 内置数据类型也可以在 Jython 中使用:
- 数字
- 字符串
- 列表
- 元组
- 字典
Python 将数字数据识别为数字,它可以是整数、带浮点数的实数或复数。字符串、列表和元组数据类型称为序列。
Jython 数字
在 Python 中,任何带符号整数都被称为类型“int”。要表示长整数,请在其后附加字母“L”。用小数点分隔整数部分和小数部分的数字称为“float”。小数部分可以包含用“E”或“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 字符串
字符串是任何用单引号(例如“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 列表
列表是一种序列数据类型。它是用方括号存储的逗号分隔项目的集合,这些项目不一定属于相同类型。可以使用基于零的索引访问列表中的单个项目。
以下代码块总结了 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 表达式 | 描述 |
---|---|
len(List) | 长度 |
List[2]=10 | 更新 |
Del List[1] | 删除 |
List.append(20) | 追加 |
List.insert(1,15) | 插入 |
List.sort() | 排序 |
Jython 元组
元组是用括号存储的逗号分隔数据项的不可变集合。无法删除或修改元组中的元素,也无法向元组集合中添加元素。以下代码块显示了元组操作。
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 字典
Jython 字典类似于 Java 集合框架中的 Map 类。它是键值对的集合。用花括号括起来,逗号分隔的对。字典对象不遵循基于零的索引来检索其中的元素,因为它们是通过哈希技术存储的。
同一个键不能在字典对象中出现多次。但是,多个键可以具有相同的关联值。下面解释了字典对象可用的不同函数:
dict = {'011':'New Delhi','022':'Mumbai','033':'Kolkata'} print "dict[‘011’]: ",dict['011'] print "dict['Age']: ", dict['Age']
下表描述了一些与字典相关的最常见的 Jython 表达式。
Jython 表达式 | 描述 |
---|---|
dict.get(‘011’) | 搜索 |
len(dict) | 长度 |
dict[‘044’] = ‘Chennai’ | 追加 |
del dict[‘022’] | 删除 |
dict.keys() | 键列表 |
dict.values() | 值列表 |
dict.clear() | 删除所有元素 |
Jython - 使用 Java 集合类型
除了 Python 的内置数据类型之外,Jython 还可以通过导入java.util 包来使用 Java 集合类的好处。以下代码描述了以下类:
- 具有 add() 的 Java ArrayList 对象
- remove()
- 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 类
Jython 还实现了Jarray 对象,它允许在 Python 中构造 Java 数组。为了使用 jarray,只需在 Jython 中定义一个序列类型并将其与包含在序列中的对象类型一起传递给 jarrayobject。jarray 中的所有值必须是相同类型。
下表显示了与 jarray 一起使用的字符类型代码。
字符类型代码 | 相应的 Java 类型 |
---|---|
Z | 布尔值 |
C | 字符 |
B | 字节 |
H | 短整型 |
I | 整型 |
L | 长整型 |
F | 浮点型 |
D | 双精度浮点型 |
以下示例显示了 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 字符串序列构造的。上述脚本jarray.py的输出如下:
array('i', [1, 2, 3, 4, 5]) array('c', 'Hello Jython')
Jython - 决策控制
决策结构包含一个或多个条件,程序需要对其进行评估或测试,以及如果条件被判定为真则要执行的语句或语句组,并且可以选择性地执行其他语句,如果条件被判定为假。
下图显示了大多数编程语言中常见的决策结构的通用形式。
Jython 不使用花括号来指示当条件为真或假时要执行的语句块(如 Java 中那样)。相反,使用统一缩进(从左边缘的空格)来形成语句块。这样的统一缩进块使得当“if”语句中给定的条件为真时要执行的条件代码。
一个类似的块可能存在于可选的“else”语句之后。Jython 还提供了elif 语句,可以使用它来测试连续的条件。在这里,else 子句将最后出现,并且仅当所有前面的条件都失败时才会执行。使用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 - 循环
通常,程序中的语句按顺序执行:函数中的第一个语句首先执行,然后是第二个语句,依此类推。可能存在您需要多次执行代码块的情况。提供这种重复功能的语句称为循环语句。
在 Jython 中,循环可以通过两个语句形成,它们是:
while 语句和
for 语句
WHILE 循环
Jython 中的 while 循环语句类似于 Java 中的 while 循环语句。只要给定的条件为真,它就会重复执行语句块。以下流程图描述了while循环的行为。
while 语句的通用语法如下所示。
while expression: statement(s)
以下 Jython 代码使用 while 循环重复递增和打印变量的值,直到它小于零。
count = 0 while count<10: count = count+1 print "count = ",count print "Good Bye!"
输出 - 输出将如下所示。
count = 1 count = 2 count = 3 count = 4 count = 5 count = 6 count = 7 count = 8 count = 9 count = 10 Good Bye!
FOR 循环
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
输出 - 输出将如下所示。
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
输出 - 输出将如下所示。
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
输出 - 上述程序的输出如下所示。
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() 函数形成的列表。例如:
for num in range(5): print num
它产生以下输出:
0 1 2 3 4
Jython - 函数
复杂的编程逻辑被分解成一个或多个独立且可重用的语句块,称为函数。Python 的标准库包含大量的内置函数。也可以使用def关键字定义自己的函数。用户定义的函数名称后面跟着一个语句块,形成函数体,该语句块以 return 语句结束。
一旦定义,就可以从任何环境中调用任意次数。让我们考虑以下代码来说明这一点。
#definition of function defSayHello(): "optional documentation string" print "Hello World" return #calling the function SayHello()
可以设计一个函数从调用环境接收一个或多个参数/参数。在调用这样的参数化函数时,您需要提供相同数量的参数,这些参数具有与函数定义中使用的类似数据类型,否则 Jython 解释器将抛出TypeError异常。
示例
#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)
输出将如下所示:
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 - 模块
模块是 Jython 脚本,其中定义了一个或多个相关的函数、类或变量。这允许 Jython 代码的逻辑组织。模块中定义的程序元素可以通过导入模块或从中导入特定元素(函数/类)在另一个 Jython 脚本中使用。
在以下代码(hello.py)中,定义了一个函数SayHello()。
#definition of function defSayHello(str): print "Hello ", str return
要从另一个脚本使用 SayHello() 函数,请在其中导入hello.py 模块。
import hello hello.SayHello("TutorialsPoint")
但是,这将导入模块中定义的所有函数。为了从模块导入特定函数,请使用以下语法。
from modname import name1[, name2[,... nameN]
例如,要仅导入 SayHello() 函数,请将上述脚本更改如下。
from hello import SayHello SayHello("TutorialsPoint")
在调用函数时,无需为模块名称添加前缀。
Jython - 包
任何包含一个或多个 Jython 模块的文件夹都被识别为包。但是,它必须有一个名为__init__.py的特殊文件,该文件提供要使用的函数索引。
现在让我们了解如何创建和导入包。
步骤 1 - 创建一个名为package1的文件夹,然后在其中创建并保存以下g模块。
#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
步骤 2 - 在 package1 文件夹中创建并保存__init__.py文件,内容如下。
#__init__.py from fact import factorial from sum import add from mult import multiply
步骤 3 - 在 package1 文件夹之外创建以下 Jython 脚本作为test.py。
# 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
步骤 4 - 从 Jython 提示符执行 test.py。将获得以下输出。
factorial = 120 addition = 30 multiplication = 200
Jython - Java 应用程序
下载jython-standalone-2.7.0.jar - 用于从其官方下载页面将 Jython 嵌入到 Java 应用程序中:https://www.jython.cn/downloads.html并将此 jar 文件包含在 Java CLASSPATH 环境变量中。
此库包含PythonInterpreter类。使用此类的对象,可以使用execfile()方法执行任何 Python 脚本。PythonInterpreter 使您能够直接使用PyObjects。Jython 运行时系统已知的所有对象都由类 PyObject 或其子类的实例表示。
PythonInterpreter 类有一些常用的方法,在下表中解释。
序号 | 方法和描述 |
---|---|
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 获取本地命名空间中变量的值。该值将作为给定 Java 类的实例返回。 |
以下代码块是一个 Java 程序,其中嵌入了 Jython 脚本“hello.py”。使用 PythonInterpreter 对象的 execfile()方法。它还展示了如何使用 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 插件
PyDev 是 Eclipse IDE 的一个开源插件,用于启用 Python、Jython 以及 IronPython 项目的开发。它托管在https://pydev.org。下面是将 PyDev 插件安装到 Eclipse IDE 中的分步过程。
步骤 1 - 打开 Eclipse IDE 并从“帮助”菜单中选择“安装新软件”选项。
步骤 2 - 在“使用”标签前面的文本框中输入http://pydev.org/updates,然后单击“添加”。选择列表中的所有可用条目,然后单击“下一步”。向导将花费几分钟来完成安装,并且它将提示 IDE 重新启动。
步骤 3 - 现在从“窗口”菜单中选择“首选项”选项。将打开“首选项”对话框,如下所示。
步骤 4 - 展开“解释器”节点,并在左侧窗格中选择“Jython 解释器”。在右侧窗格中,单击“新建”以提供jython.jar 文件的路径。
现在我们准备使用 Eclipse 启动 Jython 项目。
Jython - Eclipse 中的项目
要在 eclipse 中创建一个项目,我们应该按照以下步骤操作。
步骤 1 - 选择“文件”→“新建”→“项目”。从过滤器对话框中选择PyDev。提供项目名称、项目类型,然后单击“完成”。
步骤 2 - Hello 项目现在将出现在左侧的项目资源管理器中。右键单击以在其中添加 hello.py。
步骤 3 - 一个空的 hello.py 将出现在编辑器中。编写 Jython 代码并保存。
步骤 4 - 单击菜单栏上的“运行”按钮。输出将出现在控制台窗口中,如下所示。
Jython - NetBeans 插件和项目
NetBeans 的 Python 和 Jython 支持可以通过 **nbPython 插件** 获得。从以下 URL 下载插件 - http://plugins.netbeans.org/plugin/56795。将下载的压缩文件解压到某个文件夹中。例如 - **d:\nbplugin**。要安装 NetBeans 插件,请按照以下步骤操作。
**步骤 1** - 启动 **Netbeans IDE**,然后转到 Tools/Plugin 以打开插件管理器。选择“Downloaded”选项卡,然后浏览到已解压缩下载文件的文件夹。NetBeans 窗口将如下所示。
**步骤 2** - 下一步是选择所有 **.nbm** 文件并单击打开。
**步骤 3** - 单击“Install”按钮。
**步骤 4** - 接受以下许可协议以继续。
忽略有关插件不受信任来源的警告并重新启动 IDE 以继续。
NetBeans 中的 Jython 项目
重新启动后,通过选择 File/New 启动一个新项目。Python 类别现在将在类别列表中可用。选择它以继续。
如果系统已安装 Python,则其版本/版本将自动检测到并在 Python 平台下拉列表中显示。但是,Jython 不会列出。单击“Manage”按钮添加它。
单击“New”按钮添加 Jython 可执行文件的平台名称和路径。
Jython 现在将在平台列表中可用。从下拉列表中选择,如下面的屏幕截图所示。
我们现在可以在下一个窗口中填写项目名称、位置和主文件。
项目结构将出现在 NetBeans IDE 的项目窗口中,并在编辑器窗口中显示模板 Python 代码。
构建并执行 Jython 项目以在 NetBeans IDE 的输出窗口中获得以下结果。
Jython - Servlet
Java servlet 是最广泛使用的 Web 开发技术。我们可以使用 Jython 编写 servlet,这增加了 Java 无法提供的许多优势,因为现在我们也可以利用 Python 语言的功能。
我们将使用 NetBeans IDE 开发一个包含 Jython servlet 的 Java Web 应用程序。确保 **nbPython 插件** 已安装在 NetBeans 安装中。通过选择以下路径启动一个新项目以构建 Web 应用程序 - **File → New Project → Java web → New Web Application**。
提供项目名称和位置。IDE 将创建项目文件夹结构。在“Projects”窗口的源包节点下添加一个 Java servlet 文件 (ServletTest.java)。这将在项目的 lib 文件夹中添加 **servlet-api.jar**。此外,让 IDE 创建 web.xml **描述符文件**。在 **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 文件** 的请求时调用 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 -
https://127.0.0.1:8080/jythonwebapp/jythonservlet.py
浏览器将显示 <h1> 标记中的 **Servlet Test**,就像 Java Servlet 输出一样。
Jython - JDBC
Jython 使用 **zxJDBC 包**,它提供了一个易于使用的 Python 包装器,围绕 JDBC。zxJDBC 连接了两个标准:**JDBC** 是 Java 中数据库访问的标准平台,而 **DBI** 是 Python 应用程序的标准数据库 API。
ZxJDBC 为 JDBC 提供了一个符合 DBI 2.0 标准的接口。JDBC 可用 200 多个驱动程序,它们都适用于 zxJDBC。所有主要关系数据库都提供了高性能驱动程序,包括 -
- DB2
- Derby
- MySQL
- Oracle
- PostgreSQL
- SQLite
- SQL Server 和
- Sybase。
ZxJDBC 包可以从 https://sourceforge.net/projects/zxjdbc/ 或 http://www.ziclix.com/zxjdbc/ 下载。下载的压缩文件包含 ZxJDBC.jar,应将其添加到 CLASSPATH 环境变量中。
我们打算建立与 MySQL 数据库的数据库连接。为此,需要 MySQL 的 JDBC 驱动程序。从以下链接下载 **MySQL J 连接器** - https://dev.mysqlserver.cn/downloads/connector/j/ 并将 mysql connector java-5.1.42-bin.jar 包含在 CLASSPATH 中。
登录到 MySQL 服务器并在测试数据库中创建一个学生表,其结构如下 -
字段 | 类型 | 宽度 |
---|---|---|
姓名 | Varchar | 10 |
年龄 | Int | 3 |
分数 | Int | 3 |
在其中添加一些记录。
姓名 | 年龄 | 分数 |
---|---|---|
Ravi | 21 | 78 |
Ashok | 20 | 65 |
Anil | 22 | 71 |
创建以下 Jython 脚本作为 **dbconnect.py**。
url = "jdbc:mysql://127.0.0.1/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 提示符执行上述脚本。学生表中的记录将如下所示 -
(“Ravi”, 21, 78) (“Ashok”, 20, 65) (“Anil”,22,71)
这解释了在 Jython 中建立 JDBC 的过程。
Jython - 使用 Swing GUI 库
Jython 的主要功能之一是能够在 JDK 中使用 Swing GUI 库。标准 Python 发行版(通常称为 CPython)附带了 **Tkinter GUI 库**。其他 GUI 库,如 **PyQt** 和 **WxPython** 也可以与之一起使用,但 swing 库提供了一个平台无关的 GUI 工具包。
与在 Java 中使用 Swing 库相比,在 Jython 中使用它要容易得多。在 Java 中,必须使用匿名类来创建事件绑定。在 Jython 中,我们可以简单地传递一个函数来实现相同的目的。
基本顶级窗口是通过声明 **JFrame 类** 的对象并将其 visible 属性设置为 true 来创建的。为此,需要从 swing 包中导入 Jframe 类。
from javax.swing import JFrame
JFrame 类有多个带不同数量参数的构造函数。我们将使用一个以字符串作为参数并将其设置为标题的构造函数。
frame = JFrame(“Hello”)
在将 visible 属性设置为 true 之前,设置框架的大小和位置属性。将以下代码存储为 **frame.py**。
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)
从命令提示符运行上述脚本。它将显示以下输出,显示一个窗口。
swing GUI 库以 Java 中 **javax.swing** 包的形式提供。其主要容器类 **JFrame** 和 **JDialog** 分别派生自 Frame 和 Dialog 类,它们位于 AWT 库中。其他 GUI 控件,如 **JLabel、JButton、JTextField** 等,都派生自 JComponent 类。
下图显示了 Swing 包类层次结构。
下表总结了 swing 库中不同的 GUI 控件类 -
序号 | 类和描述 |
---|---|
1 | JLabel JLabel 对象是一个用于在容器中放置文本的组件。 |
2 | JButton 此类创建一个带标签的按钮。 |
3 | JColorChooser JColorChooser 提供了一个控件面板,旨在允许用户操作和选择颜色。 |
4 | JCheckBox JCheckBox 是一个图形组件,可以处于 **打开** (true) 或 **关闭** (false) 状态。 |
5 | JRadioButton JRadioButton 类是一个图形组件,可以处于打开 (true) 或关闭 (false) 状态。在一个组中。 |
6 | JList JList 组件向用户显示一个包含文本项目的滚动列表。 |
7 | JComboBox JComboBox 组件向用户显示一个项目的下拉列表 |
8 | JTextField JTextField 对象是一个文本组件,允许编辑单行文本。 |
9 | JPasswordField JPasswordField 对象是一个专门用于密码输入的文本组件。 |
10 | JTextArea JTextArea 对象是一个文本组件,允许编辑多行文本。 |
11 | ImageIcon ImageIcon 控件是 Icon 接口的实现,它从 Images 绘制 Icons |
12 | JScrollbar Scrollbar 控件表示一个滚动条组件,以便用户能够从值范围内进行选择。 |
13 | JOptionPane JOptionPane 提供了一组标准对话框,这些对话框提示用户输入值或通知他们某些事情。 |
14 | JFileChooser JFileChooser 控件表示一个对话框窗口,用户可以在其中选择文件。 |
15 | JProgressBar 随着任务向完成方向发展,进度条显示任务的完成百分比。 |
16 | JSlider JSlider 允许用户通过在有界区间内滑动旋钮以图形方式选择值。 |
17 | JSpinner JSpinner 是一个单行输入字段,允许用户从有序序列中选择数字或对象值。 |
我们将在后续示例中使用其中一些控件。
Jython - 布局管理
Java 中的布局管理器是管理控件在容器对象(如 **Frame、Dialog** 或 **Panel**)中的放置的类。即使分辨率发生变化或框架本身调整大小,布局管理器也会维护控件在框架中的相对位置。
这些类实现了 **Layout 接口**。以下布局管理器在 **AWT 库** 中定义 -
- BorderLayout
- FlowLayout
- GridLayout
- CardLayout
- GridBagLayout
以下布局管理器在 **Swing 库** 中定义 -
- BoxLayout
- GroupLayout
- ScrollPaneLayout
- SpringLayout
我们将在以下示例中使用 AWT 布局管理器以及 swing 布局管理器。
- 绝对布局
- 流布局
- 网格布局
- 边框布局
- 盒子布局
- 组布局
现在让我们详细讨论每一个。
绝对布局
在我们探索所有上述布局管理器之前,我们必须查看控件在容器中的绝对定位。我们必须将框架对象的布局方法设置为“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)
以上代码的输出如下所示。
Jython FlowLayout
FlowLayout 是容器类的默认布局管理器。它从左到右,然后从上到下排列控件。
在下面的示例中,需要在使用 FlowLayout 管理器的 JFrame 中显示一个 Jlabel 对象、一个 JTextField 对象和一个 JButton 对象。首先,让我们从 **javax.swing** 包和 **java.awt** 包中导入所需的类。
from javax.swing import JFrame, JLabel, JButton, JTextField from java.awt import FlowLayout
然后创建一个 JFrame 对象,并设置其 Location 和 size 属性。
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)
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)
现在,通过指定其维度为 4x4 来应用 GridLayout。
frame.setLayout(GridLayout(4,4))
我们现在应该使用两个 FOR 循环,每个循环从 1 到 4,因此十六个 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)))
最后将框架的可见性设置为 true。完整的 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 BorderLayout
BorderLayout 管理器将容器划分为五个地理区域,并在每个区域中放置一个组件。这些区域由定义的常量表示,如下所示 -
- BorderLayout.NORTH
- BorderLayout.SOUTH
- BorderLayout.EAST
- BorderLayout.WEST
- BorderLayout.CENTER
让我们考虑以下示例 -
Jython BoxLayout
BoxLayout 类在 **javax.swing 包**中定义。它用于在容器中垂直或水平排列组件。方向由以下常量确定 -
- X_AXIS
- Y_AXIS
- LINE_AXIS
- 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()** 函数占用布局中的前导或尾随空间。
首先,添加顶部和底部面板,并将框架的可见性属性设置为 true。完整的代码如下所示 -
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 GroupLayout
GroupLayout 管理器以分层方式对组件进行分组。分组由两个类完成,**SequentialGroup** 和 **ParallelGroup**,这两个类都实现了 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")
接下来,我们创建一个名为 **LeftToRight** 的 **SequentialGroup**,其中添加了 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。添加三个按钮的行并行组,然后垂直添加其余两个按钮。
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 - 事件处理
Java Swing 中的事件处理要求控件(如 JButton 或 JList 等)应向相应的事件侦听器注册。事件侦听器接口或相应的适配器类需要实现或子类化,并覆盖其事件处理方法。在 Jython 中,事件处理非常简单。我们可以将任何函数作为控件对应事件处理函数的属性传递。
让我们首先了解如何在 Java 中处理点击事件。
首先,我们必须导入 **java.awt.event 包**。接下来,扩展 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。相反,任何用户定义的函数都会直接作为 **actionPerformed** bean 属性的值提供给 JButton 构造函数。
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”消息。
在下面的 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”的分数,然后单击“Add”按钮。结果将相应显示。
Jython JRadioButton 事件
JRadioButton 类在 **javax.swing 包**中定义。它创建具有打开或关闭状态的可选择切换按钮。如果在 ButtonGroup 中添加多个单选按钮,则它们的选中状态是互斥的。
在下面的示例中,两个 JRadioButton 类对象和两个 JLabels 添加到垂直 BoxLayout 中的 Jpanel 容器中。在 JRadioButton 对象的构造函数中,**OnCheck()** 函数设置为 actionPerformed 属性的值。当单击单选按钮以更改其状态时,将执行此函数。
rb1 = JRadioButton("Male", True,actionPerformed = OnCheck) rb2 = JRadioButton("Female", actionPerformed = OnCheck)
请注意,单选按钮的默认状态为 false(未选中)。按钮 rb1 以其起始状态为 True(选中)创建。
这两个单选按钮添加到单选按钮组中,以使它们互斥,因此如果选中一个,则另一个将自动取消选中。
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 脚本并更改单选按钮选择。选择将显示在底部的标签中。
Jython JCheckBox 事件
与 **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)
运行以上代码并试验复选框的选择。两个复选框的瞬时状态在底部显示。
Jython JList 事件
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)
以下代码的输出如下所示。
Jython - 菜单
大多数基于 GUI 的应用程序在顶部都有一个菜单栏。它位于顶级窗口标题栏的正下方。javax.swing 包提供了构建高效菜单系统的完善功能。它借助于**JMenuBar、JMenu** 和 **JMenuItem** 类构建。
在下面的示例中,在顶级窗口中提供了一个菜单栏。一个包含三个菜单项按钮的“文件”菜单被添加到菜单栏中。现在让我们准备一个 JFrame 对象,并将布局设置为 BorderLayout。
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 - 对话框
对话框对象是一个窗口,它显示在用户与其交互的基本窗口的顶部。在本章中,我们将看到 swing 库中定义的预配置对话框。它们是**MessageDialog、ConfirmDialog** 和 **InputDialog**。它们由于 JOptionPane 类的静态方法而可用。
在下面的示例中,“文件”菜单有三个 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)
当执行上述脚本时,将显示以下窗口,菜单中有三个选项: