java Swing 图片缓冲机制:

参考:http://jorneyr.iteye.com/blog/868858#comments

package util;

import java.awt.geom.Point2D;

public class GeometryUtil {
// 两点之间的距离
public static double distanceOfPoints(Point2D p1, Point2D p2) {
double disX = p2.getX() - p1.getX();
double disY = p2.getY() - p1.getY();
double dis = Math.sqrt(disX * disX + disY * disY); return dis;
} // 两点的中点
public static Point2D middlePoint(Point2D p1, Point2D p2) {
double x = (p1.getX() + p2.getX()) / 2;
double y = (p1.getY() + p2.getY()) / 2; return new Point2D.Double(x, y);
} // 在两点所在直线上,以从startPoint到endPoint为方向,离startPoint的距离disToStartPoint的点
public static Point2D extentPoint(Point2D startPoint, Point2D endPoint, double disToStartPoint) {
double disX = endPoint.getX() - startPoint.getX();
double disY = endPoint.getY() - startPoint.getY();
double dis = Math.sqrt(disX * disX + disY * disY);
double sin = (endPoint.getY() - startPoint.getY()) / dis;
double cos = (endPoint.getX() - startPoint.getX()) / dis;
double deltaX = disToStartPoint * cos;
double deltaY = disToStartPoint * sin; return new Point2D.Double(startPoint.getX() + deltaX, startPoint.getY() + deltaY);
} // 绕原点的旋转矩阵,绕任意点旋转,可以先移动到原点,旋转,然后再移回去
// cosθ -sinθ 0
// sinθ +conθ 0
// 0000 +0000 1
// x = r*cosα, y = r*sinα
// x' = r*cos(α+θ) = r*cosα*cosθ - r*sinα*sinθ = x*cosθ - y*sinθ
// y' = r*sin(α+θ) = r*sinα*cosθ + r*cosα*sinθ = x*sinθ + y*cosθ
// (x, y)绕圆心旋转degree度
public static Point2D rotate(double x, double y, double degree) {
return rotate(x, y, 0, 0, degree);
} // (x, y)绕(ox, oy)旋转degree度
public static Point2D rotate(double x, double y, double ox, double oy, double degree) {
x -= ox;
y -= oy; double cos = Math.cos(Math.toRadians(degree));
double sin = Math.sin(Math.toRadians(degree)); double temp = x * cos - y * sin;
y = x * sin + y * cos;
x = temp; return new Point2D.Double(x + ox, y + oy);
} public static void main(String[] args) {
Point2D p = rotate(50, 10, 10);
System.out.println(p);
p = rotate(100, 60, 50, 50, 10);
System.out.println(p);
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import util.GeometryUtil;
@SuppressWarnings("serial")
public class Growing extends JPanel {
private List<Point2D> ps = new ArrayList<Point2D>();
private Timer timer;
private boolean stopped = false;
public Growing() {
ps.add(new Point2D.Double(0, 0));
ps.add(new Point2D.Double(800, 0));
timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
grow();
repaint();
}
});
timer.start();
}
public void grow() {
if (stopped) {
return;
}
List<Point2D> temp = new ArrayList<Point2D>();
temp.add(ps.get(0));
for (int i = 0; i < ps.size() - 1; ++i) {
Point2D p0 = ps.get(i);
Point2D p4 = ps.get(i + 1);
double len = GeometryUtil.distanceOfPoints(p0, p4);
if (len < 0.02) {
// 当线条长度小于1时,就停止再增长
System.out.println(ps.size());
timer.stop();
return;
}
Point2D p1 = GeometryUtil.extentPoint(p0, p4, len / 3);
Point2D p3 = GeometryUtil.extentPoint(p0, p4, len * 2 / 3);
Point2D p2 = GeometryUtil.rotate(p3.getX(), p3.getY(), p1.getX(), p1.getY(), 60);
temp.add(p1);
temp.add(p2);
temp.add(p3);
temp.add(p4);
}
// 将增长的计算结果赋予ps变量;
ps = null;
ps = temp;
temp = null;
}
int i = 0; // 记录绘制了几次;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// 修改type的值使用不同的绘制方式,1为compatible image, 2为swing的back-buffer
int type = 2;
// 改变窗口的大小,可以看到直接对intermediate image操作比直接对swing back-buffer操作快很多.
// 所以有很多绘制操作时,使用triple buffer是很有必要的(因为Swing已经默认使用了双缓冲).
if (type == 1) {
// [[[1]]]: 操作 compatible image 速度非常快
renderWithBuf(g2d, getWidth(), getHeight());
} else {
// [[[2]]]: 操作Swing的 back-buffer 速度非常慢
render(g2d, getWidth(), getHeight());
}
System.out.println("Growing.paintComponent(Graphics):" + i++);
}
private BufferedImage bufImg;
protected void renderWithBuf(Graphics2D g2d, int w, int h) {
if (bufImg == null || bufImg.getWidth() != w || bufImg.getHeight() != h) {
bufImg = createCompatibleImage(w, h, Transparency.OPAQUE);
// bufImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
}
Graphics2D gg = bufImg.createGraphics();
render(gg, w, h);
gg.dispose();
g2d.drawImage(bufImg, 0, 0, null);
}
protected void render(Graphics2D g2d, int w, int h) {
g2d.setBackground(Color.BLACK);
g2d.clearRect(0, 0, w, h);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.translate(0, h - 20);
g2d.setColor(Color.WHITE);
for (int i = 0; i < ps.size() - 1; ++i) {
Point2D sp = ps.get(i);
Point2D ep = ps.get(i + 1);
g2d.drawLine((int) sp.getX(), -(int) sp.getY(), (int) ep.getX(), -(int) ep.getY());
}
}
// 创建硬件适配的缓冲图像,为了能显示得更快速
public static BufferedImage createCompatibleImage(int w, int h, int type) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration gc = device.getDefaultConfiguration();
return gc.createCompatibleImage(w, h, type);
}
private static void createGuiAndShow() {
JFrame frame = new JFrame("Growing");
frame.getContentPane().add(new Growing());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 400);
frame.setAlwaysOnTop(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createGuiAndShow();
}
});
}
}
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List; import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Transform;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell; import util.GeometryUtil; public class GrowingSWT
{
private final Shell shell;
private final Canvas canvas; private List<Point2D> ps = new ArrayList<Point2D>();
private boolean stopped = false;
Image image = null;
int type = 1; private final Runnable timer = new Runnable() {
public void run()
{
shell.getDisplay().timerExec(500, timer);
grow();
canvas.redraw();
}
}; GrowingSWT(final Display display)
{
shell = new Shell(display, SWT.DOUBLE_BUFFERED | SWT.SHELL_TRIM);
shell.setLayout(new FillLayout());
canvas = new Canvas(shell, SWT.NULL);
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e)
{
long time = System.currentTimeMillis();
if (type == 1) {
e.gc.drawImage(getBuffer(false), 0, 0);
} else {
render(e.gc);
}
time = System.currentTimeMillis() - time;
if (time > 10) {
System.out.println(time);
}
} });
ps.add(new Point2D.Double(0, 0));
ps.add(new Point2D.Double(800, 0));
display.timerExec(500, timer);
} Image getBuffer( boolean withRefresh)
{
Rectangle bounds = canvas.getBounds();
if (image == null || !image.getBounds().equals(bounds)) {
image = new Image(shell.getDisplay(), bounds);
renderWithBuffer(image);
} else if (withRefresh) {
renderWithBuffer(image);
}
return image;
}
public void grow()
{
if (stopped) {
return;
} List<Point2D> temp = new ArrayList<Point2D>();
temp.add(ps.get(0)); for (int i = 0; i < ps.size() - 1; ++i) {
Point2D p0 = ps.get(i);
Point2D p4 = ps.get(i + 1);
double len = GeometryUtil.distanceOfPoints(p0, p4); if (len < 0.1) {
// 当线条长度小于1时,就停止再增长
System.out.println(ps.size());
shell.getDisplay().timerExec(-1, timer);
return;
} Point2D p1 = GeometryUtil.extentPoint(p0, p4, len / 3);
Point2D p3 = GeometryUtil.extentPoint(p0, p4, len * 2 / 3);
Point2D p2 = GeometryUtil.rotate(p3.getX(), p3.getY(), p1.getX(), p1.getY(), 60); temp.add(p1);
temp.add(p2);
temp.add(p3);
temp.add(p4);
} ps = null;
ps = temp;
temp = null;
if (type == 1) {
getBuffer(true);
}
} private void renderWithBuffer(Image image)
{
GC _gc = new GC(image);
render(_gc);
_gc.dispose();
} private void render(GC gc)
{
Display display = shell.getDisplay();
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
Rectangle bounds = canvas.getBounds();
gc.fillRectangle(bounds);
gc.setAdvanced(true);
gc.setAntialias(SWT.ON); Transform transform = new Transform(display);
transform.translate(0, bounds.height - 20);
gc.setTransform(transform); gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
for (int i = 0; i < ps.size() - 1; ++i) {
Point2D sp = ps.get(i);
Point2D ep = ps.get(i + 1);
gc.drawLine((int) sp.getX(), -(int) sp.getY(), (int) ep.getX(), -(int) ep.getY());
}
} public static void main(String[] args)
{
Display display = Display.getDefault();
Shell shell = new GrowingSWT(display).shell;
shell.setSize(800, 400);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
} }

java Swing 图片缓冲机制的更多相关文章

  1. learning java swing 双缓冲和键盘驱动

    import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.In ...

  2. opencv java swing 图片灰度化 二值化

    工程下载地址 https://download.csdn.net/download/qq_16596909/11503860 基于maven 首先引入opencv <!-- https://mv ...

  3. Java Swing事件处理机制

    Java Swing的事件处理机制 Swing GUI启动后,Java虚拟机就启动三个线程,分别为主线程,事件派发线程(也是事件处理线程)和系统工具包线程. 主线程 :负责创建并显示该程序的初始界面: ...

  4. java : 包装类 缓冲机制的使用(转载)

    摘要: 八种基本数据类型和其包装类中 Integer valueOf(int i).Byte valueOf(byte b).Short valueOf(short s).Long valueOf(l ...

  5. java SWing事件调用的两种机制

      Java(91)  /** * java swing中事件调用的两种机制: * (一)响应机制 * (二)回调机制 */ package test; import java.awt.*; impo ...

  6. 恶补Java Swing线程刷新UI机制(由浅到深的参考大佬博文)

    1. java中进度条不能更新问题的研究 感谢大佬:https://blog.csdn.net/smartcat86/article/details/2226681 为什么进度条在事件处理过程中不更新 ...

  7. Java Swing 使用总结(转载)

    随笔转载自:此去经年ぢ 地址:http://www.cnblogs.com/FLFL/p/5369756.html 1.     GUI编程引言 以前的学习当中,我们都使用的是命令交互方式: 例如:在 ...

  8. Java swing项目-图书管理系统(swing+mysql+jdbc) 总结

    (一)java Swing的学习. (1)学习如何安装windowbuilder插件的安装. <1>在eclipse中点击help <2>在help的下拉选中选择install ...

  9. 【小型系统】抽奖系统-使用Java Swing完成

    一.需求分析 1. 显示候选人照片和姓名. 2. 可以使用多种模式进行抽奖,包括一人单独抽奖.两人同时抽奖.三人同时抽奖. 3. 一个人可以在不同的批次的抽奖中获取一.二.三等奖,但是不能在同一批次抽 ...

随机推荐

  1. 转:web_custom_request 和 web_submit_data的差别

    web_custom_request方法可以发送POST和GET类型的请求 web_submit_data只能发送POST类型的请求 所有web_submit_data方法发送的请求都可以使用web_ ...

  2. 制作windows镜像

    下载包含windows驱动的iso: http://222.186.58.77/virtio-win-0.1-30.iso?fid=kF46uzxlPMrgvLDErP0ohhZYwAUASLoCAA ...

  3. Qt5:QSystemTrayIcon类实现程序托盘图标

    windows下,在许多应用程序中都会实现一个托盘图标,用于隐藏应用程序窗口时还能对该应用程序进行简单的操作,例如 QQ ,renren等程序 那么,在Qt中,如何实现呢? 这就要用到Qt提供的 QS ...

  4. php示例代码

    11111<?php $var = 'ABCDEFGH:/MNRPQR/'; echo "Original: $var<hr />\n"; /* 这两个例子使用 ...

  5. js 中调用 Object.prototype.toString()来检测对象的类型

    1.使用toString()方法来检测对象类型 可以通过toString() 来获取每个对象的类型.为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Fun ...

  6. ural1019 Line Painting

    Line Painting Time limit: 2.0 secondMemory limit: 64 MB The segment of numerical axis from 0 to 109  ...

  7. The 2013 ACMICPC Asia Regional Chengdu

    还有19天出发北京站,今年北京站的出题方是上交,去年他们出的成都现场的赛题,首先复盘一下. 去年的成都是我经历的第一次现场赛,也是近距离第一次见到了CLJ的真人,最后也是被虐惨了,那时候是声闻大神带着 ...

  8. FTP服务器中vsftpd主配置文件解析

    /etc/vsftpd/vsftpd.conf#################匿名权限控制############### anonymous_enable=YES #是否启用匿名用户no_anon_ ...

  9. SQL复习一(基础知识)

    1.什么是sql SQL(structure query language)是结构化查询语言,它是对关系型数据库的操作语言.它可以应用到所有的数据库中,例如:MySQL.Oracle.SQL serv ...

  10. 单片机裸机下写一个自己的shell调试器

    该文章是针对于串口通讯过程中快速定义命令而写的,算是我自己的一个通用化的平台,专门用来进行串口调试用,莫要取笑 要处理串口数据首先是要对单片机的串口中断进行处理,我的方法是正确的命令必须要在命令的结尾 ...