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

量子计算入门指南:密度算符的核心概念与应用解析 本文深入解析了量子计算中密度算符的核心概念与应用。作为描述量子系统“状态的状态”的关键数学工具,密度算符能有效处理混合态与子系统描述,是理解量子噪声、量子纠错和开放系统演化的基石。文章通过对比纯态与混合态,阐释了密度矩阵的数学定义与物理意义,并结合代码示例演示了其在实际量子计算问题中的强大威力。 阅读详情

相关推荐

IsaacLab从入门到精通(二) 导入自定义机器人

IsaacLab系列第二讲,导入自定义的机器人及设置

DejaWu33的博客 8463

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

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

ye_se_cong_cong的博客 3万+

arduino esp8266_Arduino传感器教程 第22章ESP8266 控制 5V 继电器

ESP8266控制5V继电器目录一、NodeMCU二、工作原理本文将使用亚马逊 AlexaEcho 和 ESP8266 控制 5V 继电器。NodeMCUNodeMCU 是一个开源的 IoT 物联网硬件开发板,由于它支持 WIFI 功能且使用方法十分类似 Arduino 开发板,所以近些年获得了越来越多来自全世界的创客朋友们的青睐。NodeMCU 尺寸与 Arduino Nano 类似。...

weixin_39611722的博客 3455

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

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

Charlesssyang的博客 4107

人工智能训练师技能等级认定四级技能考核试卷-样题1

本文为人工智能训练师四级技能考核试卷,包含六个实操考核项目,总分100分,考试时间150分钟。试卷涵盖数据处理、模型训练准备及系统维护等核心技能:1)垃圾分类数据集规范与处理(30分),要求评估数据格式并编写Python处理代码;2)学生成绩数据集分析(20分),涉及数据预处理、可视化及相关性分析;3)数据标注审核(10分),重点审核标注准确性;4)智能数据服务系统维护与优化(40分),包括安全帽数据集的项目创建、数据处理及平台协作。考核强调Python编程、数据处理平台操作及AI工作流程的实践能力。

weixin_42221934的博客 437

从零到实战:用QCustomPlot在QT中绘制动态曲线图(含OpenGL加速配置)

本文详细介绍了如何在QT中使用QCustomPlot库绘制动态曲线图,并配置OpenGL加速以提升渲染性能。从环境搭建、动态数据可视化到OpenGL加速配置,手把手教你实现工业级动态曲线监控系统,适用于大数据量实时展示场景。

weixin_29019241的博客 351

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

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

weixin_45345143的博客 3411

3dmax文件格式转换——.max 转换为 .flt(解决转换后.flt没有纹理贴图的问题)

本文主要介绍如何在3dmax中将.max格式文件转换为.flt格式文件,并解决转换后的文件没有纹理贴图的问题。 在3dmax中,将.max文件转换为.flt格式,只需导出选择.flt格式即可,但是导出的文件在osgEarth中加载后,缺少纹理和贴图。 下面是解决方案: 1、选中加载的模型,然后点击 渲染-> 渲染到纹理 2、将 渲染到纹理 子窗口往下拉,点击 添加 按钮,添加 ...

cchangcs 6164

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

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

鹅弍的博客 5744

Qt Quick (QML) 老年人健康管理

通过 **Qt SQL** 模块将所有健康数据(用药记录、体检数据等)安全地存储在本地 **SQLite** 数据库中。你想用 **Qt C++** 结合 **Qt Quick** (QML) 来开发一个老年人健康管理软件,主要功能包含 **用药提醒** 和 **健康记录** (使用 `Qt SQL` 存储数据)。* **UI 框架**: Qt Quick (QML) - 用于构建流畅、动态的用户界面。**数据模型类 (models/MedicationReminder.h / .cpp)**

寒寒豆豆软件公司的博客 192

华为OD机试新系统真题-魔法咒语组合(Java/Py/C++/Go/C/Js)

华为OD机试 新系统真题【魔法咒语组合】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【魔法咒语组合】多语言题解

qq_45776114的博客 666

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

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

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

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

qq_44560295的博客 1702

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

tortelee的博客 2万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

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

【c#窗体绘图2】picturebox的refresh方法和paint方法

前文介绍到c#窗体绘图实质上都是在画布上进行工作,本节课原本是要介绍如何创建一个画布以及如何使用,但是转念一想,在这之前,需要先介绍一下picturebox的refresh方法以及paint方法,uu们才能更加理解后续内容,如果有着急的uu不想看这节也可以直接跳过。

m0_56339807的博客 4210

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

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

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

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值