56 java编程思想——创建窗口和程序片 用户接口API

56.java编程思想——创建窗口和程序片 用户接口API

Java 1.1 版同样增加了一些重要的新功能,包括焦点遍历,桌面色彩访问,打印“沙箱内”及早期的剪贴板支持。

焦点遍历十分的简单,因为它显然存在于AWT 库里的组件并且我们不必为使它工作而去做任何事。如果我们制造我们自己组件并且想使它们去处理焦点遍历,我们过载isFocusTraversable()以使它返回真值。如果我们想在一个鼠标单击上捕捉键盘焦点,我们可以捕捉鼠标按下事件并且调用requestFocus()需求焦点方法。

1     桌面颜色

利用桌面颜色,我们可知道当前用户桌面都有哪些颜色选择。这样一来,就可在必要的时候通过自己的程序来运用那些颜色。颜色都会得以自动初始化,并置于SystemColor 的static 成员中,所以要做的唯一事情就是读取自己感兴趣的成员。各种名字的意义是不言而喻的:desktop,activeCaption,activeCaptionText,activeCaptionBorder, inactiveCaption, inactiveCaptionText,inactiveCaptionBorder, window, windowBorder, windowText, menu,menuText,text, textText,textHighlight, textHighlightText,textInactiveText,control, controlText, controlHighlight,controlLtHighlight,controlShadow ,controlDkShadow, scrollbar, info(用于帮助)以及infoText(用于帮助文字)。

2     打印

非常不幸,打印时没有多少事情是可以自动进行的。相反,为完成打印,我们必须经历大量机械的、非OO(面向对象)的步骤。但打印一个图形化的组件时,可能多少有点儿自动化的意思:默认情况下,print()方法会调用paint()来完成自己的工作。大多数时候这都已经足够了,但假如还想做一些特别的事情,就必须知道页面的几何尺寸。下面这个例子同时演示了文字和图形的打印,以及打印图形时可以采取的不同方法。此外,它也对打印支持进行了测试:

2.1     代码

import java.awt.*;

import java.awt.event.*;

public class PrintDemo extends Frame {

Button printText = new Button("Print Text"), printGraphics = new Button("Print Graphics");

TextField ringNum = new TextField(3);

Choice faces = new Choice();

Graphics g = null;

Plot plot = new Plot3(); // Try different plots

Toolkit tk = Toolkit.getDefaultToolkit();

public PrintDemo() {

ringNum.setText("3");

ringNum.addTextListener(new RingL());

Panel p = new Panel();

p.setLayout(new FlowLayout());

printText.addActionListener(new TBL());

p.add(printText);

p.add(new Label("Font:"));

p.add(faces);

printGraphics.addActionListener(new GBL());

p.add(printGraphics);

p.add(new Label("Rings:"));

p.add(ringNum);

setLayout(new BorderLayout());

add(p, BorderLayout.NORTH);

add(plot, BorderLayout.CENTER);

String[] fontList = tk.getFontList();

for (int i = 0; i < fontList.length; i++)

faces.add(fontList[i]);

faces.select("Serif");

}

class PrintData {

public PrintJob pj;

public int pageWidth, pageHeight;

PrintData(String jobName) {

pj = getToolkit().getPrintJob(PrintDemo.this, jobName, null);

if (pj != null){

pageWidth = pj.getPageDimension().width;

pageHeight = pj.getPageDimension().height;

g = pj.getGraphics();

}

}

void end() {

pj.end();

}

}

class ChangeFont {

private int stringHeight;

ChangeFont(String face, int style, int point) {

if (g != null){

g.setFont(new Font(face, style, point));

stringHeight = g.getFontMetrics().getHeight();

}

}

int stringWidth(String s) {

return g.getFontMetrics().stringWidth(s);

}

int stringHeight() {

return stringHeight;

}

}

class TBL implementsActionListener {

public void actionPerformed(ActionEvent e) {

PrintData pd = new PrintData("Print Text Test");

// Null means print job canceled:

if (pd == null)

return;

String s = "PrintDemo";

ChangeFont cf = new ChangeFont(faces.getSelectedItem(), Font.ITALIC, 72);

g.drawString(s, (pd.pageWidth- cf.stringWidth(s)) / 2, (pd.pageHeight - cf.stringHeight()) / 3);

s = "Asmaller point size";

cf = new ChangeFont(faces.getSelectedItem(), Font.BOLD, 48);

g.drawString(s, (pd.pageWidth- cf.stringWidth(s)) / 2, (int) ((pd.pageHeight - cf.stringHeight()) /1.5));

g.dispose();

pd.end();

}

}

class GBL implementsActionListener {

public void actionPerformed(ActionEvent e) {

PrintData pd = new PrintData("Print Graphics Test");

if (pd == null)

return;

plot.print(g);

g.dispose();

pd.end();

}

}

class RingL implements TextListener {

public void textValueChanged(TextEvent e) {

int i = 1;

try {

i = Integer.parseInt(ringNum.getText());

} catch (NumberFormatException ex) {

i = 1;

}

plot.rings = i;

plot.repaint();

}

}

public staticvoidmain(String[] args){

Frame pdemo = new PrintDemo();

pdemo.setTitle("Print Demo");

pdemo.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);

}

});

pdemo.setSize(500, 500);

pdemo.setVisible(true);

}

}

class Plot extends Canvas {

public intrings= 3;

}

class Plot1 extends Plot {

// Defaultprint() calls paint():

public voidpaint(Graphics g){

int w = getSize().width;

int h = getSize().height;

int xc = w / 2;

int yc = w / 2;

int x = 0, y = 0;

for (int i = 0; i < rings; i++) {

if (x < xc&& y < yc) {

g.drawOval(x, y, w, h);

x += 10;

y += 10;

w -= 20;

h -= 20;

}

}

}

}

class Plot2 extends Plot {

// To fit thepicture to the page, you must

// knowwhether you‘re printing or painting:

public voidpaint(Graphics g){

int w, h;

if (g instanceofPrintGraphics) {

PrintJob pj = ((PrintGraphics) g).getPrintJob();

w = pj.getPageDimension().width;

h = pj.getPageDimension().height;

} else {

w = getSize().width;

h = getSize().height;

}

int xc = w / 2;

int yc = w / 2;

int x = 0, y = 0;

for (int i = 0; i < rings; i++) {

if (x < xc&& y < yc) {

g.drawOval(x, y, w, h);

x += 10;

y += 10;

w -= 20;

h -= 20;

}

}

}

}

class Plot3 extends Plot {

// Somewhatbetter. Separate

// printingfrom painting:

public voidprint(Graphics g){

// Assume it‘s a PrintGraphics object:

PrintJob pj = ((PrintGraphics) g).getPrintJob();

int w = pj.getPageDimension().width;

int h = pj.getPageDimension().height;

doGraphics(g, w, h);

}

public voidpaint(Graphics g){

int w = getSize().width;

int h = getSize().height;

doGraphics(g, w, h);

}

private voiddoGraphics(Graphics g,intw, int h) {

int xc = w / 2;

int yc = w / 2;

int x = 0, y = 0;

for (int i = 0; i < rings; i++) {

if (x < xc&& y < yc) {

g.drawOval(x, y, w, h);

x += 10;

y += 10;

w -= 20;

h -= 20;

}

}

}

} /// :~

这个程序允许我们从一个选择列表框中选择字体(并且我们会注意到很多有用的字体在Java 1.1 版中一直受到严格的限制,我们没有任何可以利用的优秀字体安装在我们的机器上)。它使用这些字体去打出粗体,斜体和不同大小的文字。另外,一个新型组件调用过的绘图被创建,以用来示范图形。当打印图形时,绘图拥有的ring 将显示在屏幕上和打印在纸上,并且这三个衍生类Plot1,Plot2,Plot3 用不同的方法去完成任务以便我们可以看到我们选择的事物。同样,我们也能在一个绘图中改变一些ring——这很有趣,因为它证明了Java 1.1 版中打印的脆弱。在我的系统里,当ring 计数显示“too high”(究竟这是什么意思?)时,打印机给出错误信息并且不能正确地工作,而当计数给出“low enough”信息时,打印机又能工作得很好。我们也会注意到,当打印到看起来实际大小不相符的纸时页面的大小便产生了。这些特点可能被装入到将来发行的Java 中,我们可以使用这个程序来测试它。

这个程序为促进重复使用,不论何时都可以封装功能到内部类中。例如,不论何时我想开始打印工作(不论图形或文字),我必须创建一个PrintJob 打印工作对象,该对象拥有它自己的连同页面宽度和高度的图形对象。创建的PrintJob打印工作对象和提取的页面尺寸一起被封装进PrintData class 打印类中。

1. 打印文字

打印文字的概念简单明了:我们选择一种字体和大小,决定字符串在页面上存在的位置,并且使用Graphics.drawSrting()方法在页面上画出字符串就行了。这意味着,不管怎样我们必须精确地计算每行字符串在页面上存在的位置并确定字符串不会超出页面底部或者同其它行冲突。如果我们想进行字处理,我们将进行的工作与我们很相配。ChangeFont 封装进少量从一种字体到其它的字体的变更方法并自动地创建一个新字体对象和我们想要的字体,款式(粗体和斜体——目前还不支持下划线、空心等)以及点阵大小。它同样会简单地计算字符串的宽度和高度。当我们按下“Print text”按钮时,TBL 接收器被激活。我们可以注意到它通过反复创建ChangeFont 对象和调用drawString()来在计算出的位置打印出字符串。注意是否这些计算产生预期的结果。(我使用的版本没有出错。)

2. 打印图形

按下“Print graphics”按钮时,GBL 接收器会被激活。我们需要打印时,创建的PrintData 对象初始化,然后我们简单地为这个组件调用print()打印方法。为强制打印,我们必须为图形对象调用dispose()处理方法,并且为PrintData 对象调用end()结束方法(或改变为为PrintJob 调用end()结束方法。)这种工作在绘图对象中继续。我们可以看到基础类绘图是很简单的——它扩展画布并且包括一个中断调用ring 来指明多少个集中的ring 需要画在这个特殊的画布上。这三个衍生类展示了可达到一个目的的不同的方法:画在屏幕上和打印的页面上。

Plot1 采用最简单的编程方法:忽略绘画和打印的不同,并且过载paint()绘画方法。使用这种工作方法的原因是默认的print()打印方法简单地改变工作方法转而调用Paint()。但是,我们会注意到输出的尺寸依赖于屏幕上画布的大小,因为宽度和高度都是在调用Canvas.getSize()方法时决定是,所以这是合理的。如果我们图像的尺寸一值都是固定不变的,其它的情况都可接受。当画出的外观的大小如此的重要时,我们必须深入了解的尺寸大小的重要性。不凑巧的是,就像我们将在Plot2 中看到的一样,这种方法变得很棘手。因为一些我们不知道的好的理由,我们不能简单地要求图形对象以它自己的大小画出外观。这将使整个的处理工作变得十分的优良。相反,如果我们打印而不是绘画,我们必须利用RTTI instanceof 关键字来测试PrintGrapics,然后下溯造型并调用这独特的PrintGraphics 方法:getPrintJob()方法。现在我们拥有PrintJob 的句柄并且我们可以发现纸张的高度和宽度。这是一种hacky 的方法,但也许这对它来说是合理的理由。(在其它方面,到如今我们看到一些其它的库设计,因此,我们可能会得到设计者们的想法。)

我们可以注意到Plot2 中的paint()绘画方法对打印和绘图的可能性进行审查。但是因为当打印时Print()方法将被调用,那么为什么不使用那种方法呢?这种方法同样也在Plot3 中也被使用,并且它消除了对instanceof 使用的需求,因为在Print()方法中我们可以假设我们能对一个PrintGraphics 对象造型。这样也不坏。这种情况被放置公共绘画代码到一个分离的doGraphics()方法的办法所改进。

2. 在程序片内运行帧

如果我们想在一个程序片中打印会怎以样呢?很好,为了打印任何事物我们必须通过工具组件对象的getPrintJob()方法拥有一个PrintJob 对象,设置唯一的一个帧对象而不是一个程序片对象。于是它似乎可能从一个应用程序中打印,而不是从一个程序片中打印。但是,它变为我们可以从一个程序片中创建一个帧(相反的到目前为止,我在程序片或应用程序例子中所做的,都可以生成程序片并安放帧。)。这是一个很有用的技术,因为它允许我们在程序片中使用一些应用程序(只要它们不妨碍程序片的安全)。但是,当应用程序窗口在程序片中出现时,我们会注意到WEB 浏览器插入一些警告在它上面,其中一些产生“Warning:AppletWindow. (警告:程序片窗口)”的字样。

我们会看到这种技术十分直接的安放一个帧到程序片中。唯一的事是当用户关闭它时我们必须增加帧的代码(代替调用System.exit()):

2.2     代码2

import java.applet.*;

import java.awt.*;

import java.awt.event.*;

public class PrintDemoApplet extends Applet {

public voidinit() {

Button b = new Button("Run PrintDemo");

b.addActionListener(new PDL());

add(b);

}

class PDL implementsActionListener {

public void actionPerformed(ActionEvent e) {

final PrintDemo pd = new PrintDemo();

pd.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

pd.dispose();

}

});

pd.setSize(500, 500);

pd.show();

}

}

} /// :~

伴随Java 1.1 版的打印支持功能而来的是一些混乱。一些宣传似乎声明我们能在一个程序片中打印。但Java 的安全系统包含了一个特点,可停止一个正在初始化打印工作的程序片,初始化程序片需要通过一个Web 浏览器或程序片浏览器来进行。在写作这本书时,这看起来像留下了一个未定的争议。当我在WEB 浏览器中运行这个程序时,printdemo(打印样本)窗口正好出现,但它却根本不能从浏览器中打印。

3     剪贴板

Java 1.1 对系统剪贴板提供有限的操作支持(在Java.awt.datatransfer package 里)。我们可以将字符串作这文字对象复制到剪贴板中,并且我们可以从剪贴板中粘贴文字到字符中对角中。当然,剪贴板被设计来容纳各种类型的数据,存在于剪贴板上的数据通过程序运行剪切和粘贴进入到程序中。虽然剪切板目前只支持字符串数据,Java 的剪切板API 通过“特色”概念提供了良好的可扩展性。当数据从剪贴板中出来时,它拥有一个相关的特色集,这个特色集可以被修改(例如,一个图形可以被表示成一些字符串或者一幅图像)并且我们会注意到如果特殊的剪贴板数据支持这种特色,我们会对此十分的感兴趣。

下面的程序简单地对TextArea 中的字符串数据进行剪切,复制,粘贴的操作做了示范。我们将注意到的是我们需要按照剪切、复制和粘贴的顺序进行工作。但如果我们看见一些其它程序中的TextField 或者TextArea,我们会发现它们同样也自动地支持剪贴板的操作顺序。程序中简单地增加了剪贴板的程序化控制,如果我们想用它来捕捉剪贴板上的文字到一些非文字组件中就可以使用这种技术。

3.1     代码

import java.awt.*;

import java.awt.event.*;

import java.awt.datatransfer.*;

public class CutAndPaste extends Frame {

MenuBar mb = new MenuBar();

Menu edit = new Menu("Edit");

MenuItem cut = new MenuItem("Cut"), copy = new MenuItem("Copy"),paste= newMenuItem("Paste");

TextArea text = new TextArea(20, 20);

Clipboard clipbd = getToolkit().getSystemClipboard();

public CutAndPaste() {

cut.addActionListener(new CutL());

copy.addActionListener(new CopyL());

paste.addActionListener(new PasteL());

edit.add(cut);

edit.add(copy);

edit.add(paste);

mb.add(edit);

setMenuBar(mb);

add(text, BorderLayout.CENTER);

}

class CopyL implements ActionListener {

public void actionPerformed(ActionEvent e) {

String selection = text.getSelectedText();

StringSelection clipString = new StringSelection(selection);

clipbd.setContents(clipString, clipString);

}

}

class CutL implements ActionListener {

public void actionPerformed(ActionEvent e) {

String selection = text.getSelectedText();

StringSelection clipString = new StringSelection(selection);

clipbd.setContents(clipString, clipString);

text.replaceRange("", text.getSelectionStart(), text.getSelectionEnd());

}

}

class PasteL implements ActionListener {

public void actionPerformed(ActionEvent e) {

Transferable clipData = clipbd.getContents(CutAndPaste.this);

try {

String clipString = (String) clipData.getTransferData(DataFlavor.stringFlavor);

text.replaceRange(clipString, text.getSelectionStart(), text.getSelectionEnd());

} catch (Exception ex) {

System.out.println("not String flavor");

}

}

}

public staticvoidmain(String[] args){

CutAndPaste cp = new CutAndPaste();

cp.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

System.exit(0);

}

});

cp.setSize(300, 200);

cp.setVisible(true);

}

} /// :~

创建和增加菜单及TextArea 到如今似乎已变成一种单调的活动。这与通过工具组件创建的剪贴板字段clipbd有很大的区别。

所有的动作都安置在接收器中。CopyL 和Cupl 接收器同样除了最后的CutL 线以外删除被复制的线。特殊的两条线是StringSelection 对象从字符串从创建并调用StringSelection 的setContents()方法。说得更准确些,就是放一个字符串到剪切板上。

在PasteL 中,数据被剪贴板利用getContents()进行分解。任何返回的对象都是可移动的匿名的,并且我们并不真正地知道它里面包含了什么。有一种发现的方法是调用getTransferDateFlavors(),返回一个DataFlavor 对象数组,表明特殊对象支持这种特点。我们同样能要求它通过我们感兴趣的特点直接地使用IsDataFlavorSupported()。但是在这里使用一种大胆的方法:调用getTransferData()方法,假设里面的内容支持字符串特色,并且它不是个被分类在异常处理器中的难题 。

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://www.cnblogs.com/captainbed

原文地址:https://www.cnblogs.com/swncz/p/10178675.html

时间: 2024-10-06 19:59:28

56 java编程思想——创建窗口和程序片 用户接口API的相关文章

52 java编程思想——创建窗口和程序片 程序片限制

52.java编程思想--创建窗口和程序片 程序片限制 出于安全缘故,程序片十分受到限制,并且有很多的事我们都不能做.您一般会问:程序片看起来能做什么,传闻它又能做什么:扩展浏览器中WEB 页的功能.自从作为一个网上冲浪者,我们从未真正想了解是否一个WEB 页来自友好的或者不友好的站点,我们想要一些可以安全地行动的代码.所以我们可能会注意到大量的限制: (1) 一个程序片不能接触到本地的磁盘.这意味着不能在本地磁盘上写和读,我们不想一个程序片通过WEB页面阅读和传送重要的信息.写是被禁止的,当然

《Java编程思想》学习笔记(序言):从机电男到程序猿

为什么要写该篇? 那是我计划把这个写成一个系列,所以这是序言.Java编程还差两个月就两年了,我希望在这之前读完<Java编程思想>,对自己的知识的一个总结.该系列主要叙述我在读<Java编程思想>这本书的过程中的一些理解,我希望用最通俗易懂的语言,最真实的生活场景来表达我个人世界里的Java.如果你是初学者,可以跟随我一起阅读,我想一定会有些帮助. 话说在前头,这篇大部分纯属扯淡,没有所谓的干货!如果你实在无聊的蛋疼,可以瞅瞅,一个机电男变身程序猿的故事.大学学的机械专业,平时有

Java编程思想重点笔记(Java开发必看)

Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面 试过程中,而且在大型项目开发中也是常用的知识,既有简单的概念理解题(比如is-a关系和has-a关系的区别),也有深入的涉及RTTI和JVM底层 反编译知识. 1. Java中的多态性理解(注意与C++区分) Java中除了static方法和final方法(private方法本质上属于final方法,因为不能被子类访问)之外,其它所有的方法都是动态绑定,这意

71.JAVA编程思想——JAVA与CGI

71.JAVA编程思想--JAVA与CGI Java 程序可向一个服务器发出一个CGI 请求,这与HTML 表单页没什么两样.而且和HTML 页一样,这个请求既可以设为GET(下载),亦可设为POST(上传).除此以外,Java 程序还可拦截CGI 程序的输出,所以不必依赖程序来格式化一个新页,也不必在出错的时候强迫用户从一个页回转到另一个页.事实上,程序的外观可以做得跟以前的版本别无二致. 代码也要简单一些,毕竟用CGI 也不是很难就能写出来(前提是真正地理解它).所以我们准备办个CGI 编程

39.JAVA编程思想之外篇——JAVA图形化设计精简大全一文覆盖

39.JAVA编程思想之外篇--JAVA图形化设计精简大全一文覆盖 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/51204948 目录 Java图形化界面设计--容器(JFrame)...1 Java基本类(JFC)...1 l     AWTAbstract Window Toolkit(AWT)抽象窗口工具包... 2 l     Swing包... 2 l     AWT和Swing的区别... 6 Swing基本框

Java编程思想(十六) —— 联系JVM再谈Class

编程思想这个专栏停了好久了,主要是把精力放在了其他知识上,现在继续补上. 前面两篇写到RTTI和简单的反射介绍,先回顾一下: RTTI,运行时类型信息,多态的应用,类型转换其实是发生在运行期间. Class对象: 编程思想讲到的定义,Java使用Class对象来执行其RTTI,类是程序的一部分,每个类都有一个Class对象,其实每编写和编译一个新类,就会产生一个Class对象,其实这个对象时被保存在同名的.class文件中的.生成这个类对象,其实是JVM(Java虚拟机)使用了"类加载器&quo

83.JAVA编程思想——关于JAVA性能

83.JAVA编程思想--关于JAVA性能 Java 语言特别强调准确性,但可靠的行为要以性能作为代价.这一特点反映在自动收集垃圾.严格的运行期检查.完整的字节码检查以及保守的运行期同步等等方面.对一个解释型的虚拟机来说,由于目前有大量平台可供挑选,所以进一步阻碍了性能的发挥. "先做完它,再逐步完善.幸好需要改进的地方通常不会太多." 1     基本方法 只有正确和完整地检测了程序后,再可着手解决性能方面的问题: (1) 在现实环境中检测程序的性能.若符合要求,则目标达到.若不符合

重学Java(一):与《Java编程思想》的不解之缘

说起来非常惭愧,我在 2008 年的时候就接触了 Java,但一直到现在(2018 年 10 月 10 日),基础知识依然非常薄弱.用一句话自嘲就是:十年 IT 老兵,Java 菜鸡一枚. 于是,我想,不如静下心来,重新读一遍那些经典的 Java 技术书,并且没读完一章就输出一篇原创技术文章.从哪一本开始呢?想了一想,还是从<Java 编程思想>开始吧!毕竟这本书赢得了全球程序员的广泛赞誉,从 Java 的基础语法到最高级特性,都能指导我们 Java 程序员轻松掌握. 记得刚上大学那会,就买了

异常笔记--java编程思想

开一个新的系列,主要记一些琐碎的重要的知识点,把书读薄才是目的...特点: 代码少,概念多... 1. 基本概念 异常是在当前环境下无法获得必要的信息来解决这个问题,所以就需要从当前环境跳出,就是抛出异常.抛出异常后发生的几件事: 1.在堆上创建异常对象. 2.当前的执行路径中止                                          3. 当前环境抛出异常对象的引用.                                         4. 异常处理机制接