paint()方法中Graphics实例对象是怎么来的

【JAVA】-- 绘图技术(paint()、Graphics类、双缓冲技术、addWindowListener()) JAVA坐标系中,x表示水平方向,距离坐标原点x个像素;y表示垂直方向,距离坐标原点y个像素。需要类继承JFrame或JPanel类来画窗口。 前序:设置窗口 setTitle(String s) //设置窗口标题setLocation(int x,int y) //设置窗口位置setSize(int width,int height) //设置窗口宽和高setVisible(true) //设置窗口可见,默认为false1、paint(Grap 阅读详情

学了一个多月的J2ME应用,画界面也画了好些,却一直忽视了最常用的paint方法中Graphics实例对象的来源,今天在别人的博客中找了篇文章,希望对大家有用

原文地址:http://blog.youkuaiyun.com/crazyerghb/archive/2007/10/10/1818302.aspx

 

在Canvas中调用repaint后,系统会调用paint(Graphics g),而能给与程序员发挥的空间就在paint里,那么,paint的Graphics从那里来的呢?换句话说,我们paint操作的东西到底是什么呢?他又是怎么反应到手机硬件屏幕上了呢?

 1。我们先来看看repaint是怎么实现的。

public final void repaint(int x, int y, int width, int height) {

        synchronized (Display.LCDUILock) {

            callRepaint(x + viewport[X], y + viewport[Y], width, height, null);

        }

    }

 

 2。那么callReapint是怎么实现的呢?

在Displable里有一个方法(以final标识),此方法禁止任何子类重写,就是为了保证只有他来控制repaint事件的传递:

final void callRepaint(int x, int y, int width, int height, Object target) {

        if (currentDisplay != null) {

            // Note: Display will not let anyone but the current

            // Displayable schedule repaints

            currentDisplay.repaintImpl(paintDelegate, x, y, width, height, target);//target是NULL

        }

    }

3,在Diaplay里,此方法的实现如下:

    void repaintImpl(Displayable d, int x, int y, int w, int h,

                     Object target) {

 

        synchronized (LCDUILock) {

            if (paintSuspended || !hasForeground || d != current) {

                return;

            }

        }

 

        eventHandler.scheduleRepaint(x, y, w, h, target);//把Repaint的请求部署下去

    }

4.   /**

     * Called to schedule a repaint of the current Displayable

     * as soon as possible

     *

     * @param x     The x coordinate of the origin of the repaint rectangle

     * @param y     The y coordinate of the origin of the repaint rectangle

     * @param w     The width of the repaint rectangle

     * @param h     The height of the repaint rectangle

     * @param target An optional target Object, which may have been the

     *               original requestor for the repaint

     */

    public void scheduleRepaint(int x, int y, int w, int h, Object target) {

        eventQueue.push(x, y, w, h, target);//安排后的处理就是往事件队列里push一个消息

    }

5.

 

        /**

         * Push a repaint

         *

         * @param x The x origin coordinate

         * @param y The y origin coordinate

         * @param w The width

         * @param h The height

         * @param target The optional paint target

         */

        public void push(int x, int y, int w, int h, Object target) {

 

            try {

                w += x; // convert from width, height to absolute

                h += y; //  x2, y2

              if (x < 0) x = 0;

              if (y < 0) y = 0;

 

                synchronized (qLock) {

                    if (paintX1 == -1) {

                        // If we have no pending repaint

                        // just store the region

                     paintX1 = x;

                     paintY1 = y;

                     paintX2 = w;

                     paintY2 = h;

                     paintTarget = target;

                    } else {

                        // If there is a pending repaint

                        // union the dirty regions

                        if (paintX1 > x) {

                            paintX1 = x;

                        }

                        if (paintY1 > y) {

                            paintY1 = y;

                        }

                        if (paintX2 < w) {

                            paintX2 = w;

                        }

                        if (paintY2 < h) {

                            paintY2 = h;

                        }

                        paintTarget = null;

                    }

                } // synchronized

            } catch (Throwable t) {

                t.printStackTrace();

            }

            queuedEventHandler.process(); //push消息后,就要立即进行处理,

        }

6.  其实,一个事件队列就是一个无限循环的线程,不停的检查队列,看是否有需要处理的消息,有则处理,无则等待。现在既然已经push进去一个消息,就要立即唤醒他去处理这个消息。所以自然就notify了。

        /**

         * Signal this handler there is a need to process

         * a pending event.

         */

        public synchronized void process() {

            try {

                notify();

            } catch (Throwable t) {

                // TO DO: Do something more useful with this

                t.printStackTrace();

            }

        }

7. 我们来看看事件队列EventQuene的线程是如何定义的,其中repaintScreenEvent是来对repaint事件进行处理的。

/**

         * Process events from the EventQueue

         */

        public void run() {

            int x1, y1, x2, y2, type = 0;

            Display parentOfNextScreen = null;

            Displayable nextScreen = null;

            boolean call = false;

                    

                     ........

                      if (x1 != -1) {

                        repaintScreenEvent(x1, y1, x2, y2, target);

                        x1 = y1 = x2 = y2 = -1;

                        target = null;

                    }

8. 那么,我们再来看看是如何实现repaintScreenEvent的,

/**

     * Process a repaint event

     *

     * @param x1 The x origin coordinate

     * @param y1 The y origin coordinate

     * @param x2 The lower right x coordinate

     * @param y2 The lower right y coordinate

     * @param target The optional paint target

     */

    void repaintScreenEvent(int x1, int y1, int x2, int y2, Object target) {

        try {

            synchronized (eventLock) {

                displayManager.repaint(x1, y1, x2, y2, target);//调用了屏幕管理器的reapint,请注意,这是5个参数的repaint

            }

        } catch (Throwable t) {

            handleThrowable(t);

        }

    }

9.   这个5个参数的实现方法如下:

/*

     * SYNC NOTE: this method performs its own locking of

     * LCDUILock and calloutLock.  Therefore, callers

     * must not hold any locks when they call this method.

     */

    void repaint(int x1, int y1, int x2, int y2, Object target) {

        Displayable currentCopy = null;

 

        synchronized (LCDUILock) {

            if (paintSuspended || !hasForeground) {

                return;

            }

            currentCopy = current;

        }

 

        if (currentCopy == null) {

            return;

        }

 

        screenGraphics.reset(x1, y1, x2, y2);

        current.callPaint(screenGraphics, target);

        refresh(x1, y1, x2, y2);

    }

10. 可见,screenGraphcis当作了参数传递给了callPaint,在需要知道screenGraphics如何来的之前,我们先看看callPaint方法。

/**

     * Paint this Canvas

     *

     * @param g the Graphics to paint to

     * @param target the target Object of this repaint

     */

    void callPaint(Graphics g, Object target) {

        super.callPaint(g, target);

 

        if (g.getClipY() + g.getClipHeight() <= viewport[Y]) {

            return;

        }

 

        // We prevent the Canvas from drawing outside of the

        // allowable viewport - such as over the command labels

        g.clipRect(viewport[X], viewport[Y],

                   viewport[WIDTH],

                   viewport[HEIGHT]);

 

        synchronized (Display.calloutLock) {

            g.translate(viewport[X], viewport[Y]);

            try {

                paint(g); //这就是调用后repaint方法后,系统会调用到paint(g),这个g就是调用callPaint方法传递过来的screenGraphcis,请看下面分析

            } catch (Throwable t) {

                Display.handleThrowable(t);

            }

            g.translate(-viewport[X], -viewport[Y]);

        }

    }

11,现在我们来看看screenGraphics是从那里来的,在Display类里,有一段静态数据初始化的代码

./*

 * ************* Static initializer, constructor

 */

    static {

 

        /* done this way because native access to static fields is hard */

        DeviceCaps c = new DeviceCaps();

 

        WIDTH               = c.width;

        HEIGHT              = c.height;

        ADORNEDHEIGHT       = c.adornedHeight;

        ………

 

        c = null; // let the DeviceCaps instance be garbage collected

 

        /* Let com.sun.midp classes call in to this class. */

        displayManagerImpl = new DisplayManagerImpl();//初始化屏幕管理器

        DisplayManagerFactory.SetDisplayManagerImpl(displayManagerImpl); //得到屏幕管理器,这个一个工厂方法,为以后使用做准备,此处不赘叙

        deviceAccess = new DisplayDeviceAccess(); //猜测可能是KVM和DEVICE的桥接器

        eventHandler = getEventHandler(); //事件处理器

 

        screenGraphics = Graphics.getGraphics(null);//哈哈,screenGraphics找到了

    }

      

       12. 在Graphics类里有个方法,getGraphics,但是,这个方法是默认的package级别的访问权限。所以我们不会看到。

    static Graphics getGraphics(Image img) {

        if (img == null) {

            return new Graphics(Display.WIDTH, Display.HEIGHT);

        } else {

            return new ImageGraphics(img); //猜猜它是为谁服务的?

        }

    }

13.  Graphics的构造方法如下:

 Graphics(int w, int h) {

        destination = null;

 

        maxWidth  = (short) (w & 0x7fff);

        maxHeight = (short) (h & 0x7fff);

 

        init();

        reset();

    }

14.   天哪,终于找到了,native的一个接口,init,是它来初始化了Graphics

        /**

     * Intialize the native peer of this Graphics context

     */

private native void init();

 

15.其实,找到这里,还不能说挖掘到了最根本的实现,但是,我们暂且就挖到这里,所以,总结一下,paint中的Graphics,其实是Display来提供的,只是,这个变量不会让我们看到。那么KVM的底层实现,也就是native的init(),会把这个Graphics给对接到某个具体的平台,比如win32的GDI,Symbian的Graphics GDI,还有LINUX常见的QT平台的GDI等等。


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/crazyerghb/archive/2007/10/10/1818302.aspx

SAP BO系统启用邮件发送功能 目录 背景 维护邮件目标 启用邮件功能 背景 为了将BO报表或BO预警信息发送给特定的收件人,需要启用SAP BO系统的邮件发送功能。 维护邮件目标 1. 登录BO系统的中央管理控制台(CMC): http://<bo server name>:<port>/BOE/CMC 2. 点击“Organize”底下的“Servers”按钮进入BO服务器界面: 3. 点击“Servers List”进入服务器列表界面,右键点击JobServer&lt. 阅读详情

相关推荐

Qt5.12.12安卓开发环境搭建:Windows下避开SDK版本坑的保姆级教程

本文提供Qt5.12.12在Windows下搭建Android开发环境的详细教程,重点解决SDK版本兼容性问题,特别是cmdline-tools与JDK8的匹配陷阱。通过精准选择组件版本、手动配置路径和修复常见错误,帮助开发者高效完成环境配置,适用于Qt跨平台移动开发。

weixin_33737774的博客 542

java绘图之paint(Graphics g)与Graphics g=getGraphics()的两种画笔获取

java绘图是初级程序员需要了解的内容之一,其中利用Graphics对象获取画笔就是比较核心的内容了,而通常获取Graphics对象时有多种方式,例如paint(Graphics g)与Graphics g=getGraphics()的两种方式画笔获取

ye_se_cong_cong的博客 3万+

基于FPGA的工业相机项目大赏1——cmos线阵相机

●CMOS CL0402 作为图像传感芯片,曝光后产生一定格式的图像数据;●FPGA ZYNQ7020 作为主控芯片负责cmos驱动控制、图像像素的采集、cmos寄存器的配置、cameralink协议的实现、上位机串口通信的实现;●Cameralink端子实现图像数据的高速串行发送,将数据传送至采集卡PC端。系统工作流程如下: FPGA 上电加载配置程序,计算机通过异步串口向 FPGA 发送控制信息,FPGA对接收的控制信息进行分析判断。

weixin_41895751的博客 6398

JAVA基础——重写JFrame中的paint(Graphics g)方法

为什么要重写paint方法? 当我们使用JFrame创建出窗体时,遇到窗体的尺寸改变(ie.拉伸窗体),或者窗体的部分像素被移动到屏幕之外,都会导致窗体的刷新。窗体有一个系统自带的刷新方法。但这时如果窗体中有此前绘制出的图像,则图像会随窗体的刷新而消失,这时候我们就需要将绘制图像的方法重写入JFrame的paint方法中,让图像随窗体的刷新而同步再次被绘制出来。 实现方式 函数要在类继承JFrame或者JPanel两个属性下才能实现重写,并且这个方法是系统自动调用的。 重写绘制方法的本质是将图像数据化、对象

Charlesssyang的博客 4107

基于STM32F103C8T6单片机设计CAN接口8路继电器控制板硬件(原理图+PCB)+软件源码

基于STM32F103C8T6单片机设计CAN接口8路继电器控制板硬件(原理图+PCB)+软件源码,仅供学习及设计参考。

GJZGRB的博客 1416

基于ZYNQ7020芯片(黑金开发板AX7020)之AXI-FULL DDR的PL与PS交互操作。

在该工程中我们使用了PS端的串口接收功能,PS端串口接收和发送分别有一个64字节的FIFO,但是因为串口接收阈值设置为16,所以固定接收16个字节数据后才会发生中断。此测试工程得到以前知识的总结和各大网友的支持,只希望可以为学习的你更进一步,大家一起学习才是真的开心。加油,国产芯片之路。

landyjzlai的博客 3189

说一说JAVA中paint(Graphics g)和repaint();

paint方法的用法:首先在Java文件中的第一个类要继承Jframe或者JPanel;然后再写一个构造方法进行初始化窗口,通过main方法调用该构造方法;最后通过paint方法进行画图。

weixin_45345143的博客 3411

机器学习-02 模型的评估与选择

2.1 误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异成为:误差(error)。定义: 在训练集上的误差称为训练误差(training error)或经验误差(empirical error)。 在测试集上的误差称为测试误差(test error)。 学习器在所有新样本上的误差称为泛化误差(generalization error)。 显然,我们希望得到的是在新样本上表现得很好的学习器,即泛化误差小的学习器。因此,我们应该让学习器尽可能地从训练集中学出普适性的“一般特征”,这

一个小白 1703

java-paint(Graphics g)方法的用法和JPanel和JFrame

写了这么长时间的Java代码了,今天我突然间在想这个paint方法到底是谁来调用呢?那我又怎样重写这个方法呢,然后我就百度了一下仔细研究了下,发现: public void paint(Graphics g){ } 1 函数要在类继承JFrame或者JPanel两个属性下才能实现这个方法,并且这个方法是系统自动调用的。 public class Mainwindow extends JFrame{...

鹅弍的博客 5744

Objective-C实现人工势场法(附完整源码)

Objective-C实现人工势场法(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 426

MOS管的体二极管在LLC中的作用

MOSFET是一个三端器件(G、D、S),在N沟道MOSFET的结构中,源极和漏极之间的N型材料中自然形成了一个寄生的PN结,这个PN结就是体二极管(Body Diode),它是不可避免的器件结构。📌 对于N沟MOSFET:体二极管是从漏极 D 到源极 S 的正向导通二极管,方向为 D → S。MOS管的体二极管在LLC中并不是主功率通道,但却是实现软开关(ZVS)和能量过渡的关键“临时路径”。用得好,它是你的朋友;忽略它,电路就可能烧毁。

weixin_43199439的博客 699

java 星点随机变换,星怎么画 - Java - 开发技术问答 - 云代码

import java.awt.*;import javax.swing.*;public class WuJiaoXing extends JPanel {public WuJiaoXing() {this.setSize(800, 800);}public void paint(Graphics g) {int c1, c2, c3, w, h, r;c1 = (int) (255);c2 =...

weixin_42116604的博客 108

LLC电路细讲笔记(二)LLC谐振转换器:频率、增益与Q值的详细探讨

这本电子书通过详细分析LLC谐振转换器的工作原理、等效电路和增益公式,帮助读者深入理解如何设计和优化谐振转换器系统。通过这些公式和设计方法,工程师可以根据不同的应用需求调整参数,实现高效的电能转换。

weixin_43199439的博客 6876

JAVA调用Graphics类中的paint方法,窗口出现黑屏

在调用Graphics中,使用paint方法时,显示的GUI窗口黑屏。源代码如下: 运行时,GUI窗口显示如下: 窗口显示黑屏,程序运行异常,跟我想要的结果不一样。仔细查看这一段源代码: @Override public void paint(Graphics g) {//自动被调用,g相当于一只画笔 g.drawLine(100, 100, 300, 300);//画一条线 ...

qq_44560295的博客 1702

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

图像化界面paint,repaint方法的总结

JAVA 画图中出现的paint()函数 问题:小弟刚学JAVA,有一个问题。以下是一段JAVA代码,它弹出了一个窗口,并在窗口上使用paint()画出矩形、椭圆、扇面等图形。但鉴于paint()并不在main()中执行,所以它会一次画完。现在我想让画图行为受用户控制,比如说,开始只有一个空白窗口。当用户输入1,画出矩形。用户输入2,擦掉矩形。用户输入3,画出椭圆。等等等等。 所以小弟应该如何做?...

tortelee的博客 2万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

java paint方法调用_Java paint()方法个人理解

这些天给同学讲了不少次JUI的 paint()方法和画笔,就目前而言已经比当初自己写的时候理解的多了不少了,虽然有点花时间,但好处还是有的。(习惯把Graphics g对象叫做画笔)以前想要在某个容器上用画笔绘制东西来做游戏,直接给主类继承JPanel,然后只是把paint()+repaint()当作线程来使,感觉就这么背下来了。然后当我再看这个paint方法的时候,隐约记得有个方法叫做获取对象的...

weixin_32059869的博客 2829

创建Graphics对象的三种方法

方法一、利用控件或窗体的Paint事件中的PainEventArgs 在窗体或控件的Paint事件中接收对图形对象的引用,作为PaintEventArgs(PaintEventArgs指定绘制控件所用的Graphics)的一部分,在为控件创建绘制代码时,通常会使用此方法来获取对图形对象的引用。 例如: //窗体的Paint事件的响应方法 代码如下: private void fo

羊羽的博客 7421

java jpanel paint_关于swing:Java-图形-传递给paint()的Graphics对象与JPanel实例中的Graphics对象不同...

我有一个JPanel可以绘制形状并允许选择这些形状。我开始添加使用AffineTransform对象以及Graphics2D对象来转换此视图的功能。在我的paint()方法中,当然会传入一个Graphics对象。我在该对象上设置了一个新的转换(在这种情况下,只是将内容缩放2倍),paint()方法中的所有内容均根据AffineTransform正确绘制我刚开始在这一点上,图形形状部分效果很好!现在...

weixin_39593593的博客 344

如何实例化Graphics对象

一、创建Graphics对象 要绘制图像,首先要创建Graphics对象,然后才可以使用GDI+绘制线条和形状,呈现文本或显示与操作图像。Graphics对象是GDI+的绘图表面,是用于创建图形图像的对象。创建Graphics对象有下面三个方法(摘自MSDN): 1、在窗体或控件的 Paint 事件中接收对图形对象的引用,作为 PaintEventArgs 的一部分。在为控件创建绘制代码时,通

yulongguiziyao的专栏 6127

c#创建Graphics对象的三种方法

方法一、利用控件或窗体的Paint事件中的PainEventArgs 在窗体或控件的Paint事件中接收对图形对象的引用,作为PaintEventArgs(PaintEventArgs指定绘制控件所用的Graphics)的一部分,在为控件创建绘制代码时,通常会使用此方法来获取对图形对象的引用。 例如: //窗体的Paint事件的响应方法 复制代码代码如下: private vo...

denggu5258的博客 554

java 建立一个graphics对象_java中怎么把当前类的Graphics设置为自己的Graphics对象?...

就是把getGraphics对象替换为自己的Graphics对象。bufferedImageBimg=newBufferedImage(600,600,BufferedImage.TYPE_INT_RGB);Graphicsg=Bimg.getGraphics();publicvoidinit(){super....就是把getGraphics对象替换为自己的Graphics对象。buffered...

weixin_29973077的博客 682

Graphics 绘图类 Paint()函数

/* Graphics 绘图类  Paint()函数 */ import java.awt.*; public class TestPaint { public static void main(String[] args) { new TFrame(); } } class TFrame extends Frame { TFrame() { setL

kokodudu的专栏 1189

Graphics类使用的解释与思考

@[TOC] Graphics类使用的解释与思考 Graphics类说明 该类的所在的包为java.awt,也就是说这是一个用于GUI界面设计的类。根据API中Graphics类的声明为: public abstract class Graphics extends Object 即该类为抽象类,注意!!!**无法直接生成实例对象**,这个很关键,正常来说初学的思路大概就是生成一个实例变量...

Rwenkai的博客 1462

java repaint 重画图形_Java Graphics的paint和repaint方法

调用paint的一般是repaint()或当显示器刷新的时候调用的类似repaint()的类。 当对于桌面执行了某类操作,改变了桌面上的图象时,jvm收到界面被调整的信息,此时会调用visible是ture的图形组件的repaint()方法对界面重绘。 当然,直接重绘或全部重绘是很亏的,一个是用双缓存技术,另一个是只对桌面上显示的部分重绘。双缓存是指在缓存内先模拟重绘过程,只把最后成形的...

weixin_39622150的博客 1131
上一篇: paint()方法中Graphics实例对象是怎么来的
下一篇: paint()方法中Graphics实例对象是怎么来的
QGJava
博客等级 码龄16年 14粉丝 8原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值