首页
论坛
图书
开发资料
在线文档
网址
下载
联系我们
 新闻│Java│JavaScript│Eclipse│Eclipse 英文│J2EE│J2ME│J2SE│JSP│Netbeans│Hibernate│JBuilder│Spring│Struts
站内搜索: 请输入搜索关键词

当前页面: 开发资料首页 → Java 专题 → JAVA中的控件重绘

JAVA中的控件重绘

摘要: JAVA中的控件重绘

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="733" border="0"> <tr> <td height="106"> </td> </tr> </table>

众所周知,使用 JAVA 开发出来的应用程序在各种平台上有着相同的用户界面,这一切得归功于 SWING 良好的跨平台性(少数 AWT 控件在不同的平台上有着极为细小的差别)。并且, JAVA 还提供了 Look&Feel 和 Theme 让开发者对用户界面上的控件进行观感上的改变,这样可以做出更多更漂亮的用户界面。然而,当你仅仅是需要对某个控件进行特别的观感设置时,使用 L&F 或 Theme 可能过于复杂,也使得程序变得比较“庞大”,因此,我们可以通过控件重绘来完成这部分特殊的要求。

javax.swing.JComponent 是所有 SWING 控件的“祖宗”,在 JComponent 中, paintComponent(Graphics g) 方法是用来进行绘制控件的,因此,如果想要重绘 SWING 控件,只需要覆盖 paintComponent(Graphics g) 方法就可以了。如:

<table class=CodeBlock> <tr> <td>

public class CubeMenuBar extends JMenuBar {

void paintComponent(Graphics g) {

// 这里写重绘代码

}

}

</td> </tr> </table>

下面,我们将以例子来实现控件的重绘,最终结果如下图:

首先,我们按照上图制作一个简单的小程序,相信这个不是一件太难的事情:

<table cellPadding=5 class=CodeBlock> <tr> <td>

//TestMenu.java

public class TestMenu extends JFrame {

JMenuBar cmbMenu = new JMenuBar();

JMenu mFile = new JMenu();

JMenu mEdit = new JMenu();

JMenu mSource = new JMenu();

JMenuItem miNew = new JMenuItem();

JMenuItem miOpen = new JMenuItem();

JMenuItem miSave = new JMenuItem();

JMenuItem miClose = new JMenuItem();

JTextArea taEditor = new JTextArea();

public TestMenu() {

// 创建布局

this.getContentPane().setLayout(new BorderLayout());

// 添加菜单

this.setJMenuBar(cmbMenu);

mFile.setText("File");

cmbMenu.add(mFile);

miNew.setText("New");

mFile.add(miNew);

miOpen.setText("Open");

mFile.add(miOpen);

miSave.setText("Save");

mFile.add(miSave);

miClose.setText("Close");

mFile.add(miClose);

miClose.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

dispose();

System.exit(0);

}

});

mEdit.setText("Edit");

cmbMenu.add(mEdit);

mSource.setText("Source");

cmbMenu.add(mSource);

// 添加编辑区域

JScrollPane sp = new JScrollPane(taEditor);

this.getContentPane().add(sp, BorderLayout.CENTER);

this.setTitle("Notepad - JAVA");

this.setSize(new Dimension(400, 300));

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.show();

}

public static void main(String[] args) {

//JFrame.setDefaultLookAndFeelDecorated(true);

TestMenu testmenu = new TestMenu();

}

}

</td> </tr> </table>

( 程序运行如上图 )

为了实现特殊的菜单栏,我们需要自己重写 JMenu 类,假设我们的类叫作 CubeMenuBar ,那么,我们只需要将 TestMenu.java 中的

JMenuBar cmbMenu = new JMenuBar();

改为

CubeMenuBar cmbMenu = new CubeMenuBar();

现在,我们看一看最简单的 CubeMenuBar 应该怎么写:

<table cellPadding=5 class=CodeBlock> <tr> <td>

// CubeMenuBar.java

public class CubeMenuBar extends JMenuBar {

protected final void paintComponent(Graphics g) {

super.paintComponent(g);

}

}

</td> </tr> </table>

我们将 paintComponent(Graphics g) 申明为 protected final 是不愿继承的类再次改写重绘方法, super.paintComponent(g); 调用的父类的方法来进行重绘 MenuBar ,如果你写掉了这一句,呵呵,自己看看运行结果。

由于我们在这里只是研究如何重绘控件,因此,我提供一个现成的类,这个类负责生成带有过度色块的图像,具体不多说,只帖出代码:

<table cellPadding=5 class=CodeBlock> <tr> <td width="659">

// ImageCreator.java

public class ImageCreator {

// 定义颜色

public static final Color mainMidColor = new Color(0, 64, 196);

public static final Color mainUltraDarkColor = new Color(0, 0, 64);

// 定义色块数量 ( 高度 )

public static final int CUBE_DIMENSION = 5;

public ImageCreator() {

}

/**

* 产生过度色块图像

* @param width 图像的宽

* @param height 图像的高

* @param leftColor 色块左侧颜色

* @param rightColor 色块结束的颜色

* @param transitionStart 过度色块开始位置

* @param transitionEnd 过度色块结束位置

* @return 创建好的图像

*/

public static BufferedImage getGradientCubesImage(int width, int height,

Color leftColor, Color rightColor, int transitionStart,

int transitionEnd) {

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

Graphics2D graphics = (Graphics2D) image.getGraphics();

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

GradientPaint gradient = new GradientPaint(transitionStart, 0, leftColor, transitionEnd, 0, rightColor);

graphics.setPaint(gradient);

graphics.fillRect(transitionStart, 0, transitionEnd - transitionStart, height);

graphics.setColor(leftColor);

graphics.fillRect(0, 0, transitionStart, height);

graphics.setColor(rightColor);

graphics.fillRect(transitionEnd, 0, width - transitionEnd, height);

int cubeCountY = height / ImageCreator.CUBE_DIMENSION;

int cubeCountX = 1 + (transitionEnd - transitionStart)

/ ImageCreator.CUBE_DIMENSION;

int cubeStartY = (height % ImageCreator.CUBE_DIMENSION) / 2;

int cubeStartX = transitionStart

- (ImageCreator.CUBE_DIMENSION - ((transitionEnd - transitionStart) % ImageCreator.CUBE_DIMENSION));

for (int col = 0; col < cubeCountX; col++) {

for (int row = 0; row < cubeCountY; row++) {

// 随机放置色块

if (Math.random() < 0.5) {

continue;

}

// 使用插值方法产生颜色,结果看起来和随机产生的差不多

double coef = 1.0 - (((double) col / (double) cubeCountX) + 0.9 * (Math

.random() - 0.5));

coef = Math.max(0.0, coef);

coef = Math.min(1.0, coef);

// 计算 RGB

int r = (int) (coef * leftColor.getRed() + (1.0 - coef) * rightColor.getRed());

int g = (int) (coef * leftColor.getGreen() + (1.0 - coef) * rightColor.getGreen());

int b = (int) (coef * leftColor.getBlue() + (1.0 - coef) * rightColor.getBlue());

// 填充色块

graphics.setColor(new Color(r, g, b));

graphics.fillRect(cubeStartX + col * ImageCreator.CUBE_DIMENSION, cubeStartY + row

* ImageCreator.CUBE_DIMENSION, ImageCreator.CUBE_DIMENSION, ImageCreator.CUBE_DIMENSION);

// 绘置色块边框

graphics.setColor(new Color(255 - (int) (0.95 * (255 - r)), 255 - (int) (0.9 * (255 - g)),

255 - (int) (0.9 * (255 - b))));

graphics.drawRect(cubeStartX + col * ImageCreator.CUBE_DIMENSION, cubeStartY + row

* ImageCreator.CUBE_DIMENSION,

ImageCreator.CUBE_DIMENSION,

ImageCreator.CUBE_DIMENSION);

}

}

return image;

}

}

</td> </tr> </table>

现在,我们的 CubeMenuBar.java 应该写为如下:

<table cellPadding=5 class=CodeBlock> <tr> <td width="654">

public class CubeMenuBar extends JMenuBar {

protected final void paintComponent(Graphics g) {

super.paintComponent(g);

g.drawImage(ImageCreator.getGradientCubesImage(this.getWidth(), this.getHeight(), ImageCreator.mainMidColor,

ImageCreator.mainUltraDarkColor, (int) (0.6 * this.getWidth()), (int) (0.9 * this.getWidth())), 0, 0, null);

}

}

</td> </tr> </table>

只通过如此简单的几句代码,我们就可以得到了带和过度色块的菜单栏,是不是很有意思呢?

同样,我们在这个小程序中对 JMenu 和 JMenuItem 进行重绘,就可以得到最终的结果,然而,这个程序还有一点点小缺陷,当重绘的文字过大的时候,文字的边缘出现的锯齿,这是 Graphics 类的通病,为以,我们可以再做修改:

<table cellPadding=5 class=CodeBlock> <tr> <td width="640">

// CubeMenu.ajva

public class CubeMenu extends JMenu {

protected final void paintComponent(Graphics g) {

Graphics2D graphics = (Graphics2D) g;

Object oldHint = graphics

.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);

graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,

RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

super.paintComponent(graphics);

graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, oldHint);

graphics.setColor(ImageCreator.mainMidColor);

graphics.setBackground(ImageCreator.mainMidColor);

graphics.fillRect(0, 0, this.getWidth(), this.getHeight());

int x = (this.getWidth() - graphics.getFontMetrics().stringWidth(this.getText())) / 4;

int y = (int) (graphics.getFontMetrics().getLineMetrics(this.getText(), graphics).getHeight());

graphics.setColor(Color.black);

graphics.drawString(this.getText(), x + 1, y + 1);

graphics.setColor(Color.white);

graphics.drawString(this.getText(), x, y);

}

}

</td> </tr> </table>

在上述代码中,我们首先将 Graphics 对象转换为了 Graphics2D 对象,这样可以充分利用 Graphics2D 带来的更多特性。然后使用

Object oldHint = graphics.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING);

将控件原来绘制的渲染方式进行了保存,通过

graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

来为文字添加反锯齿绘制方式,最后再使用

graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, oldHint);

恢复控件原来的绘制方式。

function TempSave(ElementID) { CommentsPersistDiv.setAttribute("CommentContent",document.getElementById(ElementID).value); CommentsPersistDiv.save("CommentXMLStore"); } function Restore(ElementID) { CommentsPersistDiv.load("CommentXMLStore"); document.getElementById(ElementID).value=CommentsPersistDiv.getAttribute("CommentContent"); } </td> </tr> <tr>


↑返回目录
前一篇: 看看别人是怎样求质数的!
后一篇: java反射

首页 | 全站 Sitemap | 联系我们 | 设为首页 | 收藏本站
版权所有 Copyright © 2006-2007, Java 编程资料牛鼻站, All rights reserved