javaGUI程序设计_第1页
javaGUI程序设计_第2页
javaGUI程序设计_第3页
javaGUI程序设计_第4页
javaGUI程序设计_第5页
已阅读5页,还剩78页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、JAVA 语言,第10讲 JAVA的图形用户界面设计,2020/6/24,.,上一讲回顾,输入/输出流的概念和类层次结构 字节流、字符流的定义和使用 节点流与过滤流的定义和使用 文件管理以及文件操作 对象串行化的概念和实现方法,2020/6/24,.,学习要点,了解AWT和Swing组件的基础知识 理解如何创建框架窗口 理解如何向框架窗口添加组件 使用各种布局管理器创建复杂的窗口 理解Java的事件处理机制 创建GUI对象,以及各GUI对象的事件处理,2020/6/24,.,4,Graphics User Interface,GUI-Graphics User Interface。 GUI程序

2、给用户提供了一个视觉上更加直观,操作更加方便、快捷的用户环境。 在Java中为方便GUI程序的开发,专门提供多种进行图形用户程序开发的程序包。如抽象窗口工具包AWT和Swing等。,2020/6/24,.,5,10.1 GUI类,Java提供了帮助创建图形用户界面程序的丰富的类库: 容器类:JFrame,JPanel,JApplet UI组件类: JButton,JTextField, JComboBox, JList, JMenu等 帮助类:Graphics,Color,Font,Demision, LayoutManager等,2020/6/24,.,用这些类库中的类(框架、面板、标签、按

3、钮、文本框、组合框、复选按钮、菜单、滚动条等)构造用户界面,这些类又称为GUI类。 GUI类存放在java.awt和javax.swing包中,编程时需要导入。 import java.awt.*; 或import javax.swing.*;,2020/6/24,.,设计GUI应用程序的流程: (1)引用需要的包和类。 (2)设置一个顶层的容器。 (3)根据需要为容器设置布局管理器或使用默认布局管理器。 (4)将组件添加到容器内,位置自行设计。 (5)为响应事件的组件编写事件处理代码。,2020/6/24,.,10.2 框架,创建图形用户界面程序的第一步是创建一个容器类,以容纳其他要显示的组

4、件主界面(框架)。在这个容器中放入其他一些图形用户界面组件从而组成一个功能完善的程序。 在Java程序中可用于主界面的类主要有两个: 简单窗口类JWindow 框架窗口类JFrame类,2020/6/24,.,JFrame,.,Content pane,JPanel,JPanel,JButton,JLabel,中间层容器,Swing件组层次关系,顶层容器,2020/6/24,.,10.2.1 创建框架,JFrame Swing应用程序的窗口组件类,是Swing中最常使用的容器组件,可以添加其它容器和添加其它组件 JFrame类构造方法: public JFrame() public JFram

5、e(String Title) JFrame类常用方法: public Container getContentPane() public void setDefaultCloseOperation(int operation),2020/6/24,.,方法 setDefaultCloseOperation( int operation)的参数operation取以下4个常量之一: DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE(默认) DISPOSE_ON_CLOSE EXIT_ON_CLOSE,2020/6/24,.,JFrame类常用方法(2),setIconImag

6、e窗口最小化。 setTitle设置窗口中标题栏的文字。 setResizable设置用户是否可以改变框架大小。 dispose方法关闭窗口,并回收该窗口的所有资源。 setLocation设置组件的位置。 setBounds重新设置组件的大小和位置。 setVisible 设置框架是否可视,2020/6/24,.,【例10.1】 显示一个空框架 FirstFrame.java import javax.swing.*; public class FirstFrame public static void main(String args) SimpleFrame frame = new Si

7、mpleFrame(); /设置用户关闭框架时的响应动作 frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); /显示该框架 frame.show(); class SimpleFrame extends JFrame public SimpleFrame() /设置框架大小 setSize(WIDTH, HEIGHT); public static final int WIDTH = 300; public static final int HEIGHT = 200; ,运行结果,2020/6/24,.,ch10TestFrame.ja

8、va,2020/6/24,.,容器的分类,1、容器(Container类) 容器通过使用一些设计管理器,主要负责布置它所包含的组件的位置。 Container类允许别的Component对象嵌套在的Container类对象中。 2、顶层容器 JFrame:一个使用Swing的独立图形用户界面应用程序至少有一个使用JFrame作为根的包含层次 JApplet:基于Swing的Applet至少有一个包含层次,其根是JApplet 3、中间层容器,2020/6/24,.,10.2.2 在框架内添加组件,如果需要将一些图形用户界面元素加入到框架中,则要在面板组件(JPanel)中进行绘制,然后将该面板

9、组件加入到框架的内容窗格(ContentPane)中: /得到JFrame的内容窗格对象 Container contentPane = getContentPane(); Component c = .; /将组件加入到内容窗格中 contentPane.add(c); 面板JPanel类本身是容器,它可以容纳其他图形用户界面元素,如按钮、菜单等。,2020/6/24,.,/TestFrame.java,class SimpleFrame extends JFrame public static final int WIDTH = 300; public static final int H

10、EIGHT = 200; public SimpleFrame(String title) super(title); /设置框架大小 setSize(WIDTH, HEIGHT); JButton btnOk=new JButton(确定); getContentPane().add(btnOk); ,2020/6/24,.,10.3 布局管理,为了使图形用户界面具有良好的平台无关性,提供了专门用来管理组件在容器中的布局的工具。 Java的GUI组件被放置在容器中,然后由容器的布局管理器对它们的位置和大小进行管理。 在程序中,如果没有指定布局管理器,默认的布局管理器就将组件其放置到框架的中央

11、。,2020/6/24,.,Java共有6种基本的布局管理器,它们分别为: FlowLayout(流式布局) GridLayout(网格布局) BorderLayout (边界布局) CardLayout (卡片布局) GridBagLayout(网格包布局) null (空布局) 。 容器类默认的布局管理器为FlowLayout。,2020/6/24,.,10.3.1 FlowLayout布局管理器,组件从左上角开始按从左到右、从上到下的方式排列 FlowLayout的构造函数: FlowLayout( ):生成一个默认的流式布局 FlowLayout(int alignment):可以设定

12、每一行组件的对齐方式 FlowLayout(int alignment,int horz,int vert):可以设定组件间的水平和垂直距离 Applet和面板的缺省布局:,FlowLayout mylayout = new FlowLayout(); FlowLayout exLayout = new FlowLayout(FlowLayout.RIGHT); setLayout(exlayout); / 为容器设置新布局 Container contentPane = getContentPane(); /增加相应的按钮 for (int i = 0; i buttons; i+ ) JB

13、utton addButton = new JButton(add + i); contentPane.add(addButton); ,2020/6/24,.,ch10TestLayoutFrame.java,2020/6/24,.,10.3.2 GridLayout布局管理器,GridLayout的构造函数: - GridLayout():生成一个单列的网格布局 - GridLayout(int row,int col):生成一个指定行数和列数的网格布局,水平和垂直间距为0 - GridLayout(int row,int col,int horz,int vert):生成一个指定行数和列

14、数的网格布局及组件的水平和垂直间隔。 用于将容器区域划分为一个矩形 网格组件按行和列排列,. . . Button btn; / 声明按钮数组 String str=1,2,3,4,5,6,7,8,9; setLayout(new GridLayout(3,3); btn=new Buttonstr.length; / 创建按钮数组 for(int i=0;istr.length;i+) btni=new Button(stri); add(btni); ,2020/6/24,.,ch10TestGridLayout.java,2020/6/24,.,10.3.3 BorderLayout布局

15、管理器,BorderLayout的构造函数: - BorderLayout( ):生成默认的边界布局 - BorderLayout(int horz,int vert): 可以设定组件间的水平和垂直距离 窗口、框架和对话框等的缺省布局 组件被置于容器的北、南、东、西或中间位置,. . . setLayout(new BorderLayout(); Button btnEast=new Button(东); Button btnWest=new Button(西); Button btnNorth=new Button(北); Button btnSouth=new Button(南); But

16、ton btnCenter=new Button(中); add(btnEast,BorderLayout.EAST); add(btnWest,BorderLayout.WEST); add(btnNorth,BorderLayout.NORTH); add(btnSouth,BorderLayout.SOUTH); add(btnCenter,BorderLayout.CENTER);,2020/6/24,.,ch10TestBorderLayout.java,2020/6/24,.,10.3.4 CardLayout布局管理器,可存储几个不同的布局。 每个布局就像是一个卡片组中的一张卡片

17、。 在一个给定的时间总会有一张卡片在顶层。 卡片通常为一个 JPanel 对象。 每当需要许多面板切换,而每个面板需要显示为不同布局时,可以使用卡片布局。,2020/6/24,.,CardLayout提供了两种构造函数: CardLayout( ) CardLayout(int horz, int vert) 第一种形式生成了一个默认的卡片布局管理器。第二种形式分别在horz和vert中设定控件之间的水平和垂直间隔。,2020/6/24,.,主要方法,void add(Component panelObj, Object name); 在生成一副牌之后,通过调用由CardLayout定义的下列

18、方法之一来激活一张卡片: void first(Container deck) void last(Container deck) void next(Container deck) void previous(Container deck) void show(Container deck, String cardName) 演示TestCardLayout.java,2020/6/24,.,10.3.5 GridBagLayout布局管理器,每个 GridBagLayout 对象维持一个动态的矩形单元网格,每个组件占用一个或多个这样的单元,称为显示区域。 构造函数: GridBagLayo

19、ut( ) 使用GridBagLayout和GridBagConstaints辅助类 GridBagLayout管理的每个组件都与GridBagConstaints对象关联,2020/6/24,.,GridBagConstraints 类中包含 用来定位及调整组件大小所需的全部信息。 组件大小不必相同 组件按行和列排列 放置顺序不一定为从左至右和由上至下 获得 GridBagLayout: GridBagLayout gb=new GridBagLayout(); ContainerName.setLayout(gb); 要使用此布局,必须提供各组件的大小和布局等信息。,2020/6/24,.

20、,GridBagConstraints 类 2-1,成员变量列表: gridx, gridy : 指定组件放置于哪个单元中 gridwidth, gridheight : 指定组件将占用多少行和多少列 weightx, weighty : 指定在一个 GridBagLayout 中应如何分配空间,这些变量的缺省值为 0 ipadx, ipady : 指定组件的最小高度和宽度,2020/6/24,.,成员变量列表: fill : 指定在单元大于组件的情况下,组件如何填充此单元,共有4可选值。缺省值为:GridBagConstraints.NONE anchor : 指定将组件放置在单元中的位置,

21、共有9个可选值。缺省值为:GridBagConstraints.CENTER,GridBagConstraints 类2-2,2020/6/24,.,这十个组件的每一个都将与其相关的 GridBagConstraints 对象的 fill 字段设置为 GridBagConstraints.BOTH。此外,这些组件还有以下非默认值约束 (Constraints): Button1、Button2、Button3: weightx = 1.0 Button4:weightx = 1.0、gridwidth = GridBagConstraints.REMAINDER Button5:gridwid

22、th = GridBagConstraints.REMAINDER Button6:gridwidth = GridBagConstraints.RELATIVE Button7:gridwidth = GridBagConstraints.REMAINDER Button8:gridheight = 2、weighty = 1.0 Button9、Button 10:gridwidth = GridBagConstraints.REMAINDER,2020/6/24,.,创建复杂界面 TestGridBagLayout.java,2020/6/24,.,10.3.6 Null布局管理器,在某

23、些情况下,用户不想使用布局管理器,需要自己设置组件的位置和大小,这时应取消容器的布局管理器,然后再进行设置,否则用户自定义设置将会被布局管理器覆盖。 取消布局管理器的方法是: setLayout(null);,2020/6/24,.,用户使用setLocation()、setSize()、setBounds()等方法为组件设置位置和大小。 需要注意的是,这种方法会导致程序与系统相关,如不同的分辨率会产生不同的效果。 TestNULLLayout.java,2020/6/24,.,10.4 面板容器,一个面板实质上是一个“窗口内的窗口”。它是能够被放入其他容器中的容器。 面板通常用来简化创建复杂

24、的图形用户界面的过程。 例如,我们要在一个框架窗口中放置16个按钮,和一个文本框。,2020/6/24,.,JPanel 主要用于放置Swing轻量级组件,不能独立显示,JPanel的对象可以作为顶层容器的内容面板来使用。 JPanel类构造方法: public JPanel( ) public JPanel( LayoutManager layout ) 示例JPanelDemo.java,2020/6/24,.,创建面板及复杂布局,参见JPanelDemo.java,2020/6/24,.,10.5 事件,目前为止,所有程序都是面向对象的,但是都是以过程化次序执行的。使用了判断和循环语句控

25、制执行流,即程序规定了执行流。 Java GUI编程是事件驱动的。 在事件驱动编程中,当事件发生点击按钮,或者鼠标移动时执行代码。本节介绍Java的事件模型。,2020/6/24,.,10.5.1 事件和事件源,事件与事件处理: 事件处理的3要素: 事件源:产生事件的组件 事件(对象):用户对组件的操作所触发的事件对象 事件监听器:负责处理事件的对象,也可称为事件处理器 Java的事件类和监听器接口大多在java. awt. event包中,一些Swing组件所特有的事件监听器接口则在javax. swing. event中声明,2020/6/24,.,事件层次结构2-1,2020/6/24,

26、.,事件层次结构2-2,2020/6/24,.,10.5.2事件监听,Java 最新的事件处理方法是基于授权事件模型 当事件来源对象因用户的操作(鼠标或键盘),系统会自动触发此事件类对象E,并通知所授权的事件监听者A(若来源对象已向A注册),事件监听者A中有处理各种事件的方法(事件处理者1n)便会处理此事件E的各种状况 。,2020/6/24,.,授权事件模型: 组件(事件源)都不处理自己的事件,而是将事件处理委托给外部的处理实体(监听器),这种事件处理模型称为事件的授权处理模型。不同的事件,可以交由不同类型的监听器去处理 采用授权事件模型进行事件处理的一般步骤为: 第一 确定Event So

27、urce,知道什么组件要被处理 第二 确定Event,知道什么样的事件要被处理 第三 实现Event Listener,即编写实现Event Listener的事件处理代码 第四 将事件监听器对象与事件源的某种事件关联起来 将事件监听器对象与事件源的某种事件关联起来,这个关联的过程称为向事件源注册(Registering)事件监听器。 在一个监听器类中可以实现多个监听器接口,通过它可以同时监听同一个事件源上发生的多种事件,同时,通过事件可以获得事件的详细信息,2020/6/24,.,授权事件模型 -模型图,授权事件模型图,2020/6/24,.,10.5.3 事件处理方法 一,1.首先给组件注

28、册监听器,使用下列方法: addxxxListener(事件监听器对象); 2.实现事件,重写接口中的方法。 public void actionPerformed(ActionEvent e) public void keyPressed(KeyEvent e),DynamicButtonDemo.java,2020/6/24,.,事件处理方法 二,1。定义事件类,且要实现listener interface接口。 private class ColorAction implements ActionListener 2。注册事件类,并给他们发送event object ColorActio

29、n redAction = new ColorAction(Color.RED); yellowButton.addActionListener(yellowAction);,2020/6/24,.,使用实现事件监听器接口的方法处理事件时,必须重写监听器接口中的所有方法,尽管有些方法不会用到。 JDK1.1为某些监听器接口提供了适配器类(XXXAdapter),当需要对某种事件进行处理时,只需让事件处理类继承事件所对应的适配器类,只重写需要关注的方法即可,而无关的方法就不必实现了。 继承事件适配器类,只需要重写所需要的方法即可。 适配器是一个类而不是接口,因而处理事件的类只能继承一个适配器。当

30、该类需要处理多种事件时,通过继承适配器类的方式是不行的。但可以基于适配器类,用内嵌类(Inner Class)的方法来处理这种情况。,addKeyListener(new CharType(); 为事件源注册事件监听器的方法同上。 public class CharType extends KeyAdapter public void keyPressed(KeyEvent e)/大括号中为处理事件的代码 ,事件处理方法 二 -事件适配器,2020/6/24,.,例子: ch10CallByKey.java ch10ButtonTest.java ch10KeyEventDemo.java,2

31、020/6/24,.,10.6 用户界面对象(UI),许多Java的编译器提供了可视化地创建图形用户界面。,2020/6/24,.,10.6.1 常用容器组件,JPanel 组件是一个中间容器,用于将小型的轻量级组件组合在一起 JPanel 的缺省布局为 FlowLayout,2020/6/24,.,10.6.1 常用容器组件3-3,容器JApplet继承自Applet类,与Applet不同的是,它默认的布局管理器是JAppletBorderLayout,而Applet默认的布局管理器是FlowLayout。 可直接向Applet窗口中添加组件,但JApplet添加组件时必须添加到其内容窗格中

32、。得到内容窗格使用方法: getContentPane();,2020/6/24,.,10.6.2 标签(JLabel),既可以显示文本也可以显示图像构造函数如下: JLabel(Icon icon):icon表示使用的图标 JLabel(String text,Icon icon,int align):align表示水平对齐方式,其值可以为:LEFT、RIGHT、CENTER。 其它常用方法 getText() setText(String text),2020/6/24,.,10.6.3 按钮(JButton),可以使用以下任一构造函数来创建按钮: JButton() : 新建一个空的按钮

33、 JButton(Icon icon) JButton(String text) JButton(String text, Icon icon),JButton btnOk=new JButton(确定!); JButton btnCancel=new JButton(取消!); getContentPane.add(btnOk); getContentPane.add(btnCancel);,2020/6/24,.,10.6.4 文本框-JTextField,JTextField 组件允许输入或编辑单行文本 此类的构造函数包括: JTextField() JTextField(Documen

34、t doc, String text, int columns) JTextField(int columns) JTextField(String text) JTextField(String text, int columns), Container con = getContentPane(); con.setLayout(new FlowLayout(); JLabel jl = new JLabel(“文本域”); con.add(jl); JTextField tf = new JTextField(20); con.add(tf); ,2020/6/24,.,Ch10/Butt

35、onDemo.java,2020/6/24,.,10.6.4 文本框-JPasswordField,JPasswordField 组件允许输入或编辑单行文本,并且文本被其他字符代替。 此类的构造函数与单行文本框类似。 其它方法: char getPassword() char getEchoChar() void setEchoChar(char c),2020/6/24,.,Ch10/DemoPassword.java,2020/6/24,.,10.6.4 文本框-JTextArea,JTextArea 组件用于接受来自用户的多行文本,可实现可滚动界面 JTextArea 组件可使用下列构造

36、函数创建: JTextArea() JTextArea(int rows, int cols) JTextArea(String text) JTextArea(String text, int rows, int cols), JLabel jl = new JLabel(“文本区”); con.add(jl); JTextArea ta = new JTextArea(5,10); con.add(ta); ,2020/6/24,.,10.6.5 复选框-JCheckBox,复选框用于为用户提供一组选项 JCheckBox 类具有下列构造函数: JCheckBox() JCheckBox(

37、Icon icon) JCheckBox(Icon icon, boolean selected) JCheckBox(String text) JCheckBox(String text, boolean selected) JCheckBox(String text, Icon icon) JCheckBox(String text, Icon icon, boolean selected),2020/6/24,.,ch10JCheckBoxDemo.java,2020/6/24,.,10.6.6 单选按钮-JRadioButton,单选按钮允许用户从多个选项中选择其中一个 ButtonG

38、roup 用于在 Swing 中创建组 JRadioButton 对象可使用下列构造函数创建: JRadioButton() JRadioButton(Icon icon) JRadioButton(Icon, boolean selected) JRadioButton(String text) JRadioButton(String text, boolean selected) JRadioButton(String text, Icon icon) JRadioButton(String text, Icon icon, boolean selected),2020/6/24,.,ch

39、10CheckAndRaidoDemo.java,2020/6/24,.,10.6.7 列表框-JList,public JList() public JList(ListModel dataModel) public JList (Object listData) JList 不支持滚动。要启用滚动,可使用下列代码: JScrollPane myScrollPane=new JScrollPane(); myScrollPane.getViewport().setView(dataList);, String stars = 安东尼奥.班德拉斯,来昂纳多.迪卡普尼奥, 桑德拉.布洛克,休.格

40、兰特,朱莉亚.罗伯茨; JList moviestars = new JList(stars); ,2020/6/24,.,10.6.8 组合框-JComboBox,文本域和下拉列表的组合 在 Swing 中,组合框由 JComboBox 表示 构造函数如下: public JComboBox() : 此构造函数使用缺省数据模型创建 JComboBox public JComboBox(ComboBoxModel asModel) : 使用现有 ComboBoxModel 中的项目的组合框 public JComboBox(Object items) : 包含指定数组元素的组合框, Strin

41、g names = 弗雷德里克.福西斯, 约翰.克里沙姆, 玛丽.希金斯.克拉克,帕特丽夏.康威尔; JComboBox authors = new JComboBox(names); ,2020/6/24,.,ch10ComboDemo.java,2020/6/24,.,10.6.9菜单以及弹出式菜单,典型的菜单: Swing 菜单由菜单栏、菜单和菜单项构成。,2020/6/24,.,10.6.9 菜单3-2,JMenuBar 是可通过 JFrame的根窗格添加至容器的组件。由多个 JMenu 组成,每个 JMenu 在 JMenuBar 中都表示为字符串。 JMenu 在 JMenuBar

42、 下以文本字符串形式显示,而在用户单击它时,则以弹出式菜单显示。 JMenuItem为JMenu 中的一个组件,以文本字符串形式显示,可以具有图标,外观可以修改,如字体、颜色、背景、边框等。,2020/6/24,.,1 创建菜单步骤,(a)创建菜单栏,并将菜单栏加入到框架中。 JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar); (b)创建“File”菜单、“Edit”菜单和“View”菜单。 JMenu fileMenu = new JMenu(File); JMenu editMenu = new JMenu(Edit); JMe

43、nu viewMenu = new JMenu(View); JMenu optionMenu = new JMenu(Option); (c)创建子菜单。 JMenuItem pasteItem = new JMenuItem(Paste, P);,2020/6/24,.,(d)将菜单项加入到子菜单或菜单中,将子菜单加入到菜单中,将菜单加入到菜单栏中。 fileMenu.add(newItem); editMenu.add(pasteItem); viewMenu.add(optionMenu); menuBar.add(fileMenu); menuBar.add(editMenu); m

44、enuBar.add(viewMenu);,2020/6/24,.,2创建复选框和单选按钮菜单项,创建单选按钮菜单项“Forward”,并将“Forward”菜单项加入到“Search”菜单中。 ButtonGroup group = new ButtonGroup(); forwardItem = new JRadioButtonMenuItem( Forward); group.add(forwardItem); searchMenu.add(forwardItem); 创建复选框菜单项“ToolBar”,并加入到子菜单中。 JCheckBoxMenuItem toolItem = new

45、 JCheckBoxMenuItem (ToolBar); optionMenu.add(toolItem);,2020/6/24,.,3 菜单项的使用状态 /初始设置“Save”菜单项为禁用状态。 saveItem.setEnabled(false); 4 快捷键和加速器 快捷键显示为带有下划线的字母,加速器则显示为菜单项旁边的组合键。 /设置菜单的快捷键。 fileMenu.setMnemonic(F); /设置“Exit”菜单项的快捷键为“T”。 JMenuItem exitItem = new JMenuItem(Exit, T); /设置“Exit”菜单项的加速器为“CtrlT”。 exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.C

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论