备哥以前发我了一个小工具,TakeColor 取色器。来复刻一个吧。

分析一下:顶部是菜单,左侧框显示当前鼠标所在的颜色(下面显示当前坐标和颜色值,默认RGB),中间框显示鼠标周围区域,右侧显示取色的列表(按alt+c)取色。下面一行是颜色值,并且可以切换不同的模式。打开调色盘会显示底部的颜色框和调节滑块。

TakeColor v1.0

先来实现一个简单的屏幕取色。

鼠标的移动监听器中的 moved 和 dragged。moved 只在组件内有效,dragged 是拖动鼠标才产生的事件。在 java 取得鼠标所在位置屏幕的颜色 中发现了可以获取鼠标位置和颜色的代码:

Point mousepoint = MouseInfo.getPointerInfo().getLocation();
Color pixel = robot.getPixelColor(mousepoint.x, mousepoint.y);

再加上定时器,就可以即时获取鼠标所在点像素的颜色了。

代码如下:

import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.MouseInfo;
import java.awt.AWTException;
import java.awt.Robot;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Timer;
import java.util.TimerTask; class ColorFrame extends JFrame{ private static final long serialVersionUID = 1L;
private static final int WIDTH = 350;
private static final int HEIGHT = 200;
private JPanel mainPanel;
private Robot robot; public ColorFrame(){
// 窗体设置
//setSize(WIDTH, HEIGHT);
// 窗体居中
Dimension centre = this.getScreenCentre();
setLocation(centre.width - WIDTH/2, centre.height - HEIGHT/2); setTitle("TakeColor");
setUndecorated(true); // 关闭所有框架装饰 // 添加 panel
mainPanel = new JPanel();
add(mainPanel);
pack(); // 鼠标监听
mouseListener();
} /**
* 鼠标监听,利用 timer
*/
public void mouseListener() {
try{
robot = new Robot();
}catch(AWTException e){
e.printStackTrace();
} Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
setPanelColor();
}
}, 100, 100);
} /**
* 获取位置和颜色,并设置panel颜色
*/
private void setPanelColor(){
Point point = MouseInfo.getPointerInfo().getLocation();
Color pixel = robot.getPixelColor(point.x, point.y);
System.out.println("Location:x=" + point.x + ", y=" + point.y + "\t" + pixel);
mainPanel.setBackground(pixel);
} /**
* 获取屏幕中心点
* @return Dimension
*/
public Dimension getScreenCentre(){
// 获取屏幕分辨率
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
return new Dimension(screenSize.width/2, screenSize.height/2);
} /**
* 重置窗口大小
*/
public Dimension getPreferredSize(){
return new Dimension(WIDTH, HEIGHT);
}
} public class TakeColor{
public static void main(String [] args){
EventQueue.invokeLater(() -> {
ColorFrame f = new ColorFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭事件
f.setVisible(true); // 显示窗体
});
}
}

之后更改了代码结构,main() 调用 frame, frame 只 add(panel) & pack(),主要操作都在 JPanel 中进行。

TakeColor v1.1

这一版显示坐标和颜色值,放大鼠标周围区域。

1. 显示颜色、位置以及颜色值

用一个 JPanel 设置背景颜色来显示当前颜色,两个 JLable 用来显示当前位置和颜色值。(为了节省计算量,鼠标在移动之前不重新获取颜色和放大区域。)

2. 放大镜

放大镜的功能,本来打算使用 Color 数组存储鼠标周围区域像素的Color,然后放大的话,每个像素放大成四个点。但是使用如下面这种代码,每个像素点都获取颜色getPixelColor()会很慢。

for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
areaColor[i][j] = robot.getPixelColor(x+i, y+i);
}
}

找其他的不用动像素的办法:使用Java实现截取电脑屏幕的功能中发现可以屏幕截取然后展示

// 截取图形,输出
Image image = robot.createScreenCapture(new Rectangle(0, 0, width, height));
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
2.1 屏幕动态截图效果

为了直接将image对象显示到界面上,我们可以覆盖 JComponent 类的 paintCompoent(),得到 Graphics 变量用来绘制。因为 JPanel 继承了 JComponent, 所以同样可以用 paintCompoent()

class TakeColorPanel extends JPanel{
/**
* 执行的方法
*/
public function xxx(){
// 截取以光标所在点为中心点,宽高为100像素的屏幕图像
int x = mousePoint.x;
int y = mousePoint.y;
Rectangle r = new Rectangle (x-50, y-50, 100, 100);
areaImage = robot.createScreenCapture(r); repaint(); // 重绘,调用 paintComponent
} /**
* 绘制界面
*/
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(areaImage,120,10,null); // 绘制到中间区域
} }

展示屏幕截图的效果:ROOM·屠宰场

动图:

真的像特拉法尔加·罗的能力

ROOM·屠宰场

能在自己制造的半球状/全球状空间里进行物件转换,能够将物体或是生物切成数块后在他控制的范围内重新组合,被分离的生物不会死、不痛、也不会流血。此外,罗可以借着此技能帮助特定伤患清除体内的有害物质,达到治疗伤患的效果。也能够进行瞬间移动,进入常理下无法进入的建筑物内。

2.2 放大

发现 drawImage() 就可以放大图片。

对于50*50像素的图片,使用下面的代码, 第二行会显示放大1倍的效果(变成了100*100)

g2.drawImage(areaImage,120,10,null);
g2.drawImage(areaImage,180,10,100,100,null);

放大效果完成。之后添加边框,和原版对比的效果如下:

TakeColor v1.2

这一版添加按键记录颜色历史。

但是没有在颜色添加上颜色值(JLabel样式好像有边框,设置的高度总是不对,不会调),直接用填充矩形来展示颜色历史:

// 右侧用矩形填充颜色
colorRecordRect.setFrameFromDiagonal(230,10+20*i,230+100,10+20*(i+1));
g2.draw(colorRecordRect);
g2.fill(colorRecordRect);

第二天发现 JLabel 高度是好着, 我将 setBounds() 的后两个参数宽高,写成右下角坐标了。所以改用 JLabel 来设置背景色和显示文字:

private JLabel colorRecordValue[] = new JLabel[colorRecordMax];
......
// label 组件添加
// 右侧的颜色背景和颜色值label。位置和大小230, 10, 100, 100
for(int i=0; i<colorRecordMax;i++){
colorRecordValue[i] = new JLabel();
colorRecordValue[i].setOpaque(true); // 背景不透明
colorRecordValue[i].setBounds(230, 10 + i*20, 100, 20);
add(colorRecordValue[i]);
}
......
// 显示颜色
for(Color c: colorQueue){
Color penC = new Color(255-c.getRed(), 255-c.getGreen(), 255-c.getBlue()); // 反色
// 字体颜色设置
colorRecordValue[i].setForeground(penC);
colorRecordValue[i].setText(getColorText(c));
// 背景色
colorRecordValue[i].setBackground(c); if(++i>colorRecordMax)
break;
}

注意,设置 JLabel 背景颜色的时候需要设置背景不透明 jlabel.setOpaque(true);

文字颜色值不能一直是黑色,不然黑色背景就会看不到。这里取反色,即 Color(255-R, 255-G, 255-B) 的值。

效果如下:

TakeColor v1.3

这一版添加颜色模式的 select 框、颜色输入框和复制。

下拉框

使用下拉框放置颜色模式,获取选项时可以直接使用 colorModeCombo.getSelectedItem() 而不是书中这种根据索引再获取 colorModeCombo.getItemAt(colorModeCombo.getSelectedIndex()),书中应该是用来展示各种用法的。

将一个字符串赋值给枚举值时,需要使用 valueOf 方法将字符串转为枚举值,参考如何判断枚举和字符串相等(最简便方法)

enum A {
a, b, c, d;
} A aa = A.valueOf(A.class, "a");
System.out.println(aa == A.a);

所以当选项改变,需要改变当前颜色模式:(selete 选项值转 String 是因为 getSlectedItem() 返回的是 current selected Object )

colorModeCombo.addActionListener(event ->
{
currentColorMode = ColorMode.valueOf((String)colorModeCombo.getSelectedItem());
});

颜色框和按钮都是常规的,访问剪切板参考Java操作系统剪贴板(Clipboard)实现复制和粘贴

我们的复刻取色器项目到这里就完成了,菜单不想加了,因为菜单加上去也最多加个放大倍数的效果,意义不大了。

最终成果:上面是原工具,下面是复刻版

代码 git

Tips: 控制台编译时如果出现编码错误,可以指定编码编译javac -encoding utf-8 TakeColor.java

Arava: 用 swing 写一个取色器的更多相关文章

  1. 【良心保姆级教程】java手把手教你用swing写一个学生的增删改查模块

    很多刚入门的同学,不清楚如何用java.swing去开发出一个系统? 不清楚如何使用java代码去操作数据库进行增删改查一些列操作,不清楚java代码和数据库(mysql.sqlserver)之间怎么 ...

  2. 使用Mediaplay类写一个播放器

    我们知道android本身播放视频的的能力是有限的..先来一个Demo 另附我的一个还未成熟的播放器,下载地址:http://www.eoemarket.com/soft/370334.html,正在 ...

  3. Python 中写一个装饰器实现限制频率访问

    1.思路: 首先要在装饰器中确定访问的方法名, 第一次可以访问成功,之后要在规定的时间(变量)之后才可以访问. 初始应该有一个变量为0;访问成功之后把当前的时间赋值给这个变零. 这样再次访问时把当前的 ...

  4. 手写一个类加载器demo

    1.什么是类加载器? 2.加载方式 ClassLoader类加载器,主要的作用是将class文件加载到jvm虚拟机中.jvm启动的时候,并不是一次性加载所有的类,而是根据需要动态去加载类,主要分为隐式 ...

  5. C#取色器

    闲来无事,就写了一个取色器.原理其实很简单,只需要两步, 获取鼠标光标的位置, 获取当前鼠标光标的位置的RGB颜色值. 获取鼠标光标的位置: System.Drawing.Point p = Mous ...

  6. 写一个Windows上的守护进程(3)句柄的管理

    写一个Windows上的守护进程(3)句柄的管理 在Windows中编程,跟HANDLE打交道是家常便饭.为了防止忘记CloseHandle,我都是使用do-while-false手法: void f ...

  7. 用java写一个用户登陆界面

    一.课堂测试源代码及其结果截图 用java的swing写一个用户登录界面,采用网格布局.源代码如下: /** * */package LiuLijia; import java.awt.CardLay ...

  8. 前端与编译原理——用JS写一个JS解释器

    说起编译原理,印象往往只停留在本科时那些枯燥的课程和晦涩的概念.作为前端开发者,编译原理似乎离我们很远,对它的理解很可能仅仅局限于"抽象语法树(AST)".但这仅仅是个开头而已.编 ...

  9. Arava: 写一个控制台风格的Mp3播放器

    Mp3播放器 来写一个控制台版的mp3播放器.以前很喜欢 cmd.fm 这种控制台风格的播放器. 播放mp3使用 mp3spi 库:下载mp3spi库文件,解压,拿出根目录下的 mp3spi1.9.5 ...

随机推荐

  1. vue 项目npm run dev ip访问

    webpack npm run dev 不能通过ip访问 只能通过localhost访问 解决方法如下: 修改vue-cli: config/index.js 文件 把文件中 host 的值,改成 i ...

  2. 学习JAVAWEB第十六天

    今天做了一个简单的登陆界面,HTML+CSS太不熟悉了,明天还得接着做

  3. 学习JAVAWEB第七天

    ## Bootstrap: 1. 概念: 一个前端开发的框架,Bootstrap,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JavaScript 的 ...

  4. JVM常用命令(九)

    前面东西说完后,现在可以说一些和我们平时进行性能调优相关的东西了,那怎么看和我们JVM性能调优相关的东西呢,其实这对我们开发来说是一个比较头痛的问题,其实我们JDK官网给了一些我们相关的指令,我们可以 ...

  5. 读取数据库Blob类型的文本数据

    开发一个查询功能时,遇到了一个ORM的问题:数据库字段是 Blob 类型,里面实际存储的是文本数据,Java 后端代码中用字符串 String 类型去接收这个字段的数据时,报错,提示没有对应的sett ...

  6. JS 解构赋值

    感谢原文作者:小火柴的蓝色理想 原文链接:https://www.cnblogs.com/xiaohuochai/p/7243166.html 介绍 解构赋值语法是一种 Javascript ES6引 ...

  7. Android App发布遇到的问题总结【转】

    感谢大佬:https://www.cnblogs.com/jeffen/p/6824722.html   问题描述(v1和v2) Android 7.0中引入了APK Signature Scheme ...

  8. Linux 内核引导参数简介

    概述 内核引导参数大体上可以分为两类:一类与设备无关.另一类与设备有关.与设备有关的引导参数多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导参数.比如,如果你想知道可以向 AHA ...

  9. 交换机基本原理与VRP基础及操作

    交换机基本原理与VRP基础及操作 目录 交换机基本原理与VRP基础及操作 一.数据链路层 1.数据链路层的位置 2.数据链路层的功能 二.以太网(Ethernet) 1.以太网的概念 2.MAC地址( ...

  10. HTML与HTTP协议

    HTML与HTTP协议 目录 HTML与HTTP协议 一.HTML 1. HTML概述 2. HTML编辑 3. HTML语法规则 4. HTML文件结构 5. HTML基本标签 (1)头标签中常用标 ...