实现点击在当前位置画一个黑点,打印出当前点击的坐标

本文探讨了Java中利用repaint方法进行高效局部更新的原理,并通过具体代码实例展示了如何在GamePanel类中实现鼠标点击事件触发下黑点的绘制。

没看懂repaint()的实现,找源码也没找到paint,都没调用重写的paint,那是怎么画出黑点的呢?

******************************************

打开repaint,上面有提示see update,点开update发现paint,这里的原理是一种回调,传统的paint每次画都是重新绘制一个屏幕,随着东西越来越多,绘制的东西也就越来越多,而repaint则是在指定的dirty区域重新绘制,提高了效率。

App.java:

package com.zmz.ui;

public class App {
	public static void main(String[] args) {
		GameFrame frame = new GameFrame();
		GamePanel panel = new GamePanel();
		
		frame.add(panel);
		frame.setVisible(true);
	}
}

GameFrame.java:

package com.zmz.ui;

import javax.swing.JFrame;

/**
 * 游戏窗口
 * 
 * @author Administrator
 *
 */
public class GameFrame extends JFrame {
	// 类长什么样子由构造方法决定
	
	/**
	 * 构造方法初始化
	 */
	public GameFrame() {
		setTitle("五子棋");
		setSize(506, 528);
		setResizable(false);// 不可调大小
		setLocationRelativeTo(null);// 放中间
		setDefaultCloseOperation(EXIT_ON_CLOSE);// 关闭窗口
	}
}

GamePanel.java:

package com.zmz.ui;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JPanel;
import javax.swing.Timer;


public class GamePanel extends JPanel{
	
	int x = 0;
	
	Point[] ps =  new Point[50];
	int psSize = 0;
	/**
	 * 构造方法
	 */
	public GamePanel() {
		//注册鼠标监听器
//		addMouseListener(new Listener());
		
		//适配器模式
		addMouseListener(new MListener());
//		addMouseMotionListener(l);
//		addMouseWheelListener(l);
		
		//自动重绘制
		//定时器,每隔0.02s调用一次Timerlistener里面的方法,
		//1000是1s
//		Timer timer = new Timer(20, new Timerlistener());
//			  timer.start();
	}
	
	int w;
	int h;
	
	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);
		w = getWidth();
		h = getHeight();
		for(int i = 0; i < psSize; i++) {
			Point point = ps[i];
			//画图
			g.fillOval(point.x, point.y, 10, 10);
		}
//		g.drawLine(100, 100, 100, 100);
//		g.drawOval(0, 0, 300, 200);//内切圆
		
//		g.setColor(new Color(0, 255, 0, 100));
//		g.drawRect(w/2-150, h/2-150,300,300);
////		g.setColor(Color.BLUE);
//		g.setColor(new Color(255, 0, 0,100));//最后一个为透明度
//		g.drawOval(w/2-150, h/2-150,300,300);//左上角点和长宽
//		
//		g.fillArc(w/2-150, h/2-150, 300, 300, x, 60);
//		g.fillArc(w/2-150, h/2-150, 300, 300, x+120, 60);
//		g.fillArc(w/2-150, h/2-150, 300, 300, x+240, 60);//逆时针
	}
	
	
//		class Listener implements MouseListener {
//			@Override
//			public void mouseClicked(MouseEvent e) {
//				System.out.println("鼠标点击");
//				x += 15;
//				if(x > 360) {
//					x = 0;
//				}
//				// 重绘制
//				repaint();
//			}
//
//			@Override
//			public void mousePressed(MouseEvent e) {
//				System.out.println("按下");
//			}
//
//			@Override
//			public void mouseReleased(MouseEvent e) {
//				System.out.println("释放");
//			}
//
//			@Override
//			public void mouseEntered(MouseEvent e) {
//				System.out.println("进入");
//			}
//
//			@Override
//			public void mouseExited(MouseEvent e) {
//				System.out.println("离开");
//			}
//			
//		}
		
		class Timerlistener implements ActionListener {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				x += 15;
				if(x > 360) {
					x = 0;
				}
				repaint();
			}			
		}
		
		class MListener extends MouseAdapter {
			@Override
			public void mouseClicked(MouseEvent e) {
				// TODO Auto-generated method stub
//				super.mouseClicked(e);
				//这个对象e可以获得光标的信息,坐标,压力等等
				System.out.println(e.getX()+", "+e.getY());
				
				Point point = new Point(e.getX(), e.getY());
				ps[psSize++] = point;
				int ox = e.getX();
				int oy = e.getY();
				
				x += 15;
				if(x > 360) {
					x = 0;
				}
				repaint();
			}
		}
	
	
}	


转载于:https://www.cnblogs.com/zhangmingzhao/p/7256591.html

代码不报错了,生成来的图片无效果,不符合需求。 private void Form1_Load(object sender, EventArgs e) { var baseQR = GenerateQRCode("https://www.m12315.com/CodeSearch/AntifakeSearch?code=40039186945020704494", 600); var protectedQR = AddAntiPrintPatterns(baseQR); protectedQR.Save("secure_qr.png", ImageFormat.Png); } public Bitmap GenerateQRCode(string data, int size = 500) { // 1. 创建编码选项 var options = new EncodingOptions { Width = size, Height = size, Margin = 0, PureBarcode = true // 确保只生成二维码 }; // 2. 创建渲染器实例 var renderer = new BitmapRenderer(); // 3. 创建并配置 BarcodeWriter var writer = new BarcodeWriter<Bitmap> { Format = BarcodeFormat.QR_CODE, Options = options, Renderer = renderer // 关键:设置渲染器实例 }; // 4. 生成二维码 return writer.Write(data); } public Bitmap AddAntiPrintPatterns(Bitmap qrCode) { var modified = new Bitmap(qrCode); using (var g = Graphics.FromImage(modified)) { int moduleSize = qrCode.Width / 21; // 二维码版本1的模块数 // 在三个定位标记周围添加干扰点 foreach (var corner in new[] { (0, 0), (qrCode.Width - 7 * moduleSize, 0), (0, qrCode.Height - 7 * moduleSize) }) { for (int i = 0; i < 7; i++) // 7x7定位标记区域 { for (int j = 0; j < 7; j++) { // 在深色模块上加白点,浅色模块加黑点 var color = modified.GetPixel(corner.Item1 + i * moduleSize, corner.Item2 + j * moduleSize); var dotColor = color.GetBrightness() > 0.5 ? Color.Black : Color.White; // 添加1像素干扰点(约5%概率) if (new Random().Next(100) < 5) { g.FillRectangle(new SolidBrush(dotColor), corner.Item1 + i * moduleSize + moduleSize / 2, corner.Item2 + j * moduleSize + moduleSize / 2, 1, 1); } } } } } return modified; } private static void AddDotsInArea(Graphics g, Rectangle area, int moduleSize, Pen whitePen, Pen blackPen) { Random rand = new Random(); // 在区域内,每隔2个像素(在模块中心位置)随机点 for (int x = area.Left; x < area.Right; x += moduleSize) { for (int y = area.Top; y < area.Bottom; y += moduleSize) { // 跳过定位标记的中心部分(只在外围点)?或者在整个定位标记区域都? // 为了确保干扰有效,我们在整个定位标记区域都点,但避免在定位标记的正中心(因为中心是重要的) // 实际上,定位标记是固定模式(黑白相间),所以我们可以在所有非边缘的模块上点(因为边缘的模块是定位标记的边框,必须保持纯黑色) // 获取当前模块的颜色 // 注意:这里我们简化,直接根据位置判断,实际应该检查原始图像的颜色 // 由于定位标记是固定的(外部3层黑色,内部1层白色,再内部3层黑色),所以我们可以根据相对位置判断是否在黑色区域或白色区域 // 但为了简单,我们随机点,但只在定位标记的白色部分(内层)和黑色部分(内层,非边框)? // 由于干扰点很小,我们可以随机在定位标记区域内的每个模块的随机位置上(但避开边框模块) if (x > area.Left + moduleSize && x < area.Right - 2 * moduleSize && y > area.Top + moduleSize && y < area.Bottom - 2 * moduleSize) { // 在当前模块内随机位置点 int dotX = x + rand.Next(moduleSize); int dotY = y + rand.Next(moduleSize); // 随机决定白点还是黑点?但这样可能效果不好,应该根据该位置像素的颜色来决定:如果该位置是黑色,则白点;如果是白色,则黑点 using (var bmp = new Bitmap(1, 1)) { // 这里无法直接获取Graphics的像素,所以需要一个替代方案,但我们在整个区域循环,可以提前获取原始图像? // 由于原始图像是二维码,定位标记区域的颜色是已知的(黑白相间),我们可以根据规则绘制:在黑色模块上白色点,在白色模块上黑色点。 // 但是,我们无法从Graphics对象直接获取像素颜色,所以需要改变设计:在AddAntiPrintPatterns方法中,我们传递原始图像,然后通过LockBits读取像素颜色。 // 由于时间关系,我们简化:假设定位标记区域内,模块颜色交替(实际上定位标记区域是固定模式),我们可以根据坐标计算模块的行列,然后判断模块颜色。 // 定位标记内部:行索引(0-6),列索引(0-6)。定位标记的边框(第0行、第6行、第0列、第6列)是黑色,第1行和第5行的第1-5列是白色?实际上定位标记是三个嵌套的正方形。 // 具体规则:整个7x7模块中,除了中间3x3是黑色,其他都是黑色边框和白色内框?不对,定位标记是三个嵌套正方形:最外层7x7全黑,第二层5x5是黑色边框(内部3x3白色),最内层3x3黑色。 // 所以我们根据模块索引(i,j)在7x7网格中的位置来判断颜色: int i = (x - area.Left) / moduleSize; int j = (y - area.Top) / moduleSize; bool isBlack = (i == 0 || i == 6 || j == 0 || j == 6) || // 边框 ((i == 2 || i == 3 || i == 4) && (j == 2 || j == 3 || j == 4)); // 中心3x3 // 然后在当前位置相反颜色的点 if (isBlack) { g.DrawRectangle(whitePen, dotX, dotY, 1, 1); // 在黑色模块上一个白点 } else { g.DrawRectangle(blackPen, dotX, dotY, 1, 1); // 在白色模块上一个黑点 } } } } } }
最新发布
09-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值