commit
aa6dee90be
@ -0,0 +1,9 @@ |
||||
/out |
||||
/files |
||||
/caches |
||||
/target |
||||
*.token |
||||
/target/ |
||||
/log/ |
||||
/logs/ |
||||
.idea |
@ -0,0 +1,165 @@ |
||||
GNU LESSER GENERAL PUBLIC LICENSE |
||||
Version 3, 29 June 2007 |
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> |
||||
Everyone is permitted to copy and distribute verbatim copies |
||||
of this license document, but changing it is not allowed. |
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates |
||||
the terms and conditions of version 3 of the GNU General Public |
||||
License, supplemented by the additional permissions listed below. |
||||
|
||||
0. Additional Definitions. |
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser |
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU |
||||
General Public License. |
||||
|
||||
"The Library" refers to a covered work governed by this License, |
||||
other than an Application or a Combined Work as defined below. |
||||
|
||||
An "Application" is any work that makes use of an interface provided |
||||
by the Library, but which is not otherwise based on the Library. |
||||
Defining a subclass of a class defined by the Library is deemed a mode |
||||
of using an interface provided by the Library. |
||||
|
||||
A "Combined Work" is a work produced by combining or linking an |
||||
Application with the Library. The particular version of the Library |
||||
with which the Combined Work was made is also called the "Linked |
||||
Version". |
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the |
||||
Corresponding Source for the Combined Work, excluding any source code |
||||
for portions of the Combined Work that, considered in isolation, are |
||||
based on the Application, and not on the Linked Version. |
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the |
||||
object code and/or source code for the Application, including any data |
||||
and utility programs needed for reproducing the Combined Work from the |
||||
Application, but excluding the System Libraries of the Combined Work. |
||||
|
||||
1. Exception to Section 3 of the GNU GPL. |
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License |
||||
without being bound by section 3 of the GNU GPL. |
||||
|
||||
2. Conveying Modified Versions. |
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a |
||||
facility refers to a function or data to be supplied by an Application |
||||
that uses the facility (other than as an argument passed when the |
||||
facility is invoked), then you may convey a copy of the modified |
||||
version: |
||||
|
||||
a) under this License, provided that you make a good faith effort to |
||||
ensure that, in the event an Application does not supply the |
||||
function or data, the facility still operates, and performs |
||||
whatever part of its purpose remains meaningful, or |
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of |
||||
this License applicable to that copy. |
||||
|
||||
3. Object Code Incorporating Material from Library Header Files. |
||||
|
||||
The object code form of an Application may incorporate material from |
||||
a header file that is part of the Library. You may convey such object |
||||
code under terms of your choice, provided that, if the incorporated |
||||
material is not limited to numerical parameters, data structure |
||||
layouts and accessors, or small macros, inline functions and templates |
||||
(ten or fewer lines in length), you do both of the following: |
||||
|
||||
a) Give prominent notice with each copy of the object code that the |
||||
Library is used in it and that the Library and its use are |
||||
covered by this License. |
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license |
||||
document. |
||||
|
||||
4. Combined Works. |
||||
|
||||
You may convey a Combined Work under terms of your choice that, |
||||
taken together, effectively do not restrict modification of the |
||||
portions of the Library contained in the Combined Work and reverse |
||||
engineering for debugging such modifications, if you also do each of |
||||
the following: |
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that |
||||
the Library is used in it and that the Library and its use are |
||||
covered by this License. |
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license |
||||
document. |
||||
|
||||
c) For a Combined Work that displays copyright notices during |
||||
execution, include the copyright notice for the Library among |
||||
these notices, as well as a reference directing the user to the |
||||
copies of the GNU GPL and this license document. |
||||
|
||||
d) Do one of the following: |
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this |
||||
License, and the Corresponding Application Code in a form |
||||
suitable for, and under terms that permit, the user to |
||||
recombine or relink the Application with a modified version of |
||||
the Linked Version to produce a modified Combined Work, in the |
||||
manner specified by section 6 of the GNU GPL for conveying |
||||
Corresponding Source. |
||||
|
||||
1) Use a suitable shared library mechanism for linking with the |
||||
Library. A suitable mechanism is one that (a) uses at run time |
||||
a copy of the Library already present on the user's computer |
||||
system, and (b) will operate properly with a modified version |
||||
of the Library that is interface-compatible with the Linked |
||||
Version. |
||||
|
||||
e) Provide Installation Information, but only if you would otherwise |
||||
be required to provide such information under section 6 of the |
||||
GNU GPL, and only to the extent that such information is |
||||
necessary to install and execute a modified version of the |
||||
Combined Work produced by recombining or relinking the |
||||
Application with a modified version of the Linked Version. (If |
||||
you use option 4d0, the Installation Information must accompany |
||||
the Minimal Corresponding Source and Corresponding Application |
||||
Code. If you use option 4d1, you must provide the Installation |
||||
Information in the manner specified by section 6 of the GNU GPL |
||||
for conveying Corresponding Source.) |
||||
|
||||
5. Combined Libraries. |
||||
|
||||
You may place library facilities that are a work based on the |
||||
Library side by side in a single library together with other library |
||||
facilities that are not Applications and are not covered by this |
||||
License, and convey such a combined library under terms of your |
||||
choice, if you do both of the following: |
||||
|
||||
a) Accompany the combined library with a copy of the same work based |
||||
on the Library, uncombined with any other library facilities, |
||||
conveyed under the terms of this License. |
||||
|
||||
b) Give prominent notice with the combined library that part of it |
||||
is a work based on the Library, and explaining where to find the |
||||
accompanying uncombined form of the same work. |
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License. |
||||
|
||||
The Free Software Foundation may publish revised and/or new versions |
||||
of the GNU Lesser General Public License from time to time. Such new |
||||
versions will be similar in spirit to the present version, but may |
||||
differ in detail to address new problems or concerns. |
||||
|
||||
Each version is given a distinguishing version number. If the |
||||
Library as you received it specifies that a certain numbered version |
||||
of the GNU Lesser General Public License "or any later version" |
||||
applies to it, you have the option of following the terms and |
||||
conditions either of that published version or of any later version |
||||
published by the Free Software Foundation. If the Library as you |
||||
received it does not specify a version number of the GNU Lesser |
||||
General Public License, you may choose any version of the GNU Lesser |
||||
General Public License ever published by the Free Software Foundation. |
||||
|
||||
If the Library as you received it specifies that a proxy can decide |
||||
whether future versions of the GNU Lesser General Public License shall |
||||
apply, that proxy's public statement of acceptance of any version is |
||||
permanent authorization for you to choose that version for the |
||||
Library. |
@ -0,0 +1,68 @@ |
||||
|
||||
# 一个用来点名的玩意/A simple guy to choose names |
||||
|
||||
 |
||||
|
||||
看下面 |
||||
|
||||
|
||||
## 介绍/Introduce |
||||
这是一个基于Java语言,以Google Material Design(Google MD)为设计风格的,用来点名的东西。 |
||||
|
||||
基本上不会有什么大更新,就是改善代码而已了ヾ§  ̄▽)ゞ |
||||
|
||||
由于时间仓促,加上还是JAVA的新手,因此代码和算法写的很烂,望谅解ヽ(╯▽╰)ノ |
||||
|
||||
------------ |
||||
|
||||
|
||||
#### 用法介绍 |
||||
[去去去➡](https://github.com/lensferno/dogename/blob/main/res/usage.md) |
||||
|
||||
## 截图/Screenshot: |
||||
|
||||
#### [来来来~](https://github.com/lensferno/dogename/blob/main/res/you-want.md "我要康康") |
||||
|
||||
|
||||
|
||||
## 下载/Download: |
||||
[来这里](https://github.com/lensferno/dogename/releases "这里") |
||||
|
||||
|
||||
## 使用到的第三方库/Third-party library used: |
||||
|
||||
- [JFoenix](https://github.com/jfoenixadmin/JFoenix "JFoenix")(8.0.4),UI界面库。 |
||||
|
||||
- [Apache Commons Codec](http://commons.apache.org/proper/commons-codec/ "Apache Commons Codec")(1.11),用于Base64解码。 |
||||
|
||||
- [Gson](https://github.com/google/gson "Gson")(2.8.5),用于Json数据的解析与生成。 |
||||
|
||||
- [OkHttp3](https://github.com/square/okhttp "OkHttp")(4.2.2),用于语音部分的数据请求。 |
||||
|
||||
- [gushici](https://github.com/xenv/gushici/ "古诗词")项目提供的古诗词接口和数据。 |
||||
|
||||
- “每日一句话”的数据来自[一言](https://hitokoto.cn/ "一言") |
||||
|
||||
- 本项目还使用了 百度AI SDK 来实现OCR功能。 |
||||
|
||||
------ |
||||
|
||||
#### License信息 |
||||
|
||||
本程序使用[GNU Lesser General Public License](http://www.gnu.org/licenses/lgpl-3.0.html "LGPL") (LGPL,version 3)开源许可证, |
||||
|
||||
|
||||
|
||||
遵循[Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0 "Apache License 2.0")使用了以下库: |
||||
|
||||
- [JFoenix](https://github.com/jfoenixadmin/JFoenix "JFoenix")(8.0.4) |
||||
|
||||
- [Apache Commons Codec](http://commons.apache.org/proper/commons-codec/ "Apache Commons Codec")(1.11) |
||||
|
||||
- [Gson](https://github.com/google/gson "Gson")(2.8.5) |
||||
|
||||
- [OkHttp3](https://github.com/square/okhttp "OkHttp")(4.2.2) |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,33 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4"> |
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8"> |
||||
<output url="file://$MODULE_DIR$/target/classes" /> |
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" /> |
||||
<content url="file://$MODULE_DIR$"> |
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> |
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> |
||||
<excludeFolder url="file://$MODULE_DIR$/target" /> |
||||
</content> |
||||
<orderEntry type="inheritedJdk" /> |
||||
<orderEntry type="sourceFolder" forTests="false" /> |
||||
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.6" level="project" /> |
||||
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.14" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.jfoenix:jfoenix:8.0.9" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-core:2.13.2" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.13.2" level="project" /> |
||||
<orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:4.2.2" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.squareup.okio:okio:2.2.2" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.3.50" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:mp3spi:1.9.5.4" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:jlayer:1.0.1.4" level="project" /> |
||||
<orderEntry type="library" name="Maven: junit:junit:3.8.2" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.googlecode.soundlibs:tritonus-share:0.3.7.4" level="project" /> |
||||
<orderEntry type="library" name="Maven: com.baidu.aip:java-sdk:4.12.0" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.json:json:20160810" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" /> |
||||
<orderEntry type="library" name="Maven: org.slf4j:slf4j-simple:1.7.25" level="project" /> |
||||
</component> |
||||
</module> |
@ -0,0 +1,109 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>me.lensferno.dogename</groupId> |
||||
<artifactId>dogename</artifactId> |
||||
<version>3.3</version> |
||||
|
||||
<properties> |
||||
<maven.compiler.source>1.8</maven.compiler.source> |
||||
<maven.compiler.target>1.8</maven.compiler.target> |
||||
|
||||
</properties> |
||||
|
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.apache.maven.plugins</groupId> |
||||
<artifactId>maven-jar-plugin</artifactId> |
||||
<version>2.4</version> |
||||
<configuration> |
||||
<archive> |
||||
<mainClass>me.lensferno.dogename.Main</mainClass> |
||||
</archive> |
||||
</configuration> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
|
||||
<dependencies> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> |
||||
<dependency> |
||||
<groupId>com.google.code.gson</groupId> |
||||
<artifactId>gson</artifactId> |
||||
<version>2.8.6</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --> |
||||
<dependency> |
||||
<groupId>commons-codec</groupId> |
||||
<artifactId>commons-codec</artifactId> |
||||
<version>1.14</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.jfoenix/jfoenix --> |
||||
<dependency> |
||||
<groupId>com.jfoenix</groupId> |
||||
<artifactId>jfoenix</artifactId> |
||||
<version>8.0.9</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> |
||||
<dependency> |
||||
<groupId>org.apache.logging.log4j</groupId> |
||||
<artifactId>log4j-core</artifactId> |
||||
<version>2.13.2</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> |
||||
<dependency> |
||||
<groupId>commons-io</groupId> |
||||
<artifactId>commons-io</artifactId> |
||||
<version>2.6</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp --> |
||||
<dependency> |
||||
<groupId>com.squareup.okhttp3</groupId> |
||||
<artifactId>okhttp</artifactId> |
||||
<version>4.2.2</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.googlecode.soundlibs/mp3spi --> |
||||
<dependency> |
||||
<groupId>com.googlecode.soundlibs</groupId> |
||||
<artifactId>mp3spi</artifactId> |
||||
<version>1.9.5.4</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>com.baidu.aip</groupId> |
||||
<artifactId>java-sdk</artifactId> |
||||
<version>4.12.0</version> |
||||
</dependency> |
||||
|
||||
</dependencies> |
||||
|
||||
|
||||
<repositories> |
||||
<repository> |
||||
<id>central</id> |
||||
<name>aliyun maven</name> |
||||
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> |
||||
<layout>default</layout> |
||||
<!-- 是否开启发布版构件下载 --> |
||||
<releases> |
||||
<enabled>true</enabled> |
||||
</releases> |
||||
<!-- 是否开启快照版构件下载 --> |
||||
<snapshots> |
||||
<enabled>false</enabled> |
||||
</snapshots> |
||||
</repository> |
||||
</repositories> |
||||
|
||||
</project> |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 23 KiB |
@ -0,0 +1,229 @@ |
||||
# 我该如何使用Dogename?(适用于最新的版本) |
||||
|
||||
*哈哈,终于开始写了,我都说鸽鸽我呀是不会咕的嘛*~ ╮(‵▽′)╭ |
||||
|
||||
此文章是Dogename的使用说明,它将指导您如何更好地使用这个点名工具。 |
||||
|
||||
> *使用一样新东西之前看看使用说明是个好习惯。* 🤔 *——我说的* |
||||
|
||||
这个使用说明分为以下几个部分:(点击可直达) |
||||
|
||||
### 1. 安装&开始使用 |
||||
- [从哪弄来?](#从哪弄来) |
||||
- [怎么配置环境?(很简单的!)](#怎么配置环境) |
||||
- [运行&使用](#运行与使用) |
||||
|
||||
### 2. 名单管理 |
||||
- [添加一个名字](#添加一个名字) |
||||
- [懒人:批量添加名字(特别棒!)](#批量添加名字) |
||||
- 文字识别法 |
||||
- 复制粘贴法 |
||||
- [删除名字](#删除名字) |
||||
- [导入&导出名单](#名单的导入和导出) |
||||
- [打乱名字](#打乱名字) |
||||
|
||||
### 3. 选项设置 |
||||
- [点名方面的](#点名方面的设置) |
||||
- 点名规则 |
||||
- 挑选次数 |
||||
- 挑选速度 |
||||
- 使用/不使用随机性更强的Java SecureRandom |
||||
- 开启/不开启语言播报 |
||||
- [语音报方面的](#语音播报方面的设置) |
||||
|
||||
|
||||
### 4. 其他小功能的介绍&说明 |
||||
- [历史记录](#历史记录) |
||||
- [小窗模式](#小窗模式) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-------------------------------------------- |
||||
|
||||
被夹在分割线之中不得动弹~ |
||||
|
||||
-------------------------------------------- |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 开始:使用说明 |
||||
|
||||
|
||||
|
||||
## 1. 安装&开始使用 |
||||
|
||||
|
||||
|
||||
### 从哪弄来 |
||||
- 呃嗯嗯嗯嗯嗯🤔...怎么说呢,既然你能来到这里,基本上你已经有Dogename了吧? |
||||
|
||||
- 如果还真没有,那就去这里吧:[Github](https://github.com/eatenid/dogename/releases) |
||||
> 说一声: |
||||
> 文件“dogename.jar”为主程序文件。 |
||||
> “dogename_with_jre”之类的文件是带有Java运行库的整合版本,如果您下载的是这个整合包,那么您就不必再配置运行环境,跳过b步骤了。 |
||||
|
||||
不过在中国大陆内,Github的访问速度普遍偏慢,因此建议您下载不带运行环境的包(dogeneme_no_jre),或者去下载页(releases页)给出的其他下载方式。 |
||||
|
||||
### 怎么配置环境 |
||||
本程序是用Java语言写成的,因此您的计算机需要有合适的Java运行环境才能运行Dogename。(跟Minecraft一样的道理) |
||||
|
||||
- 如果您是从本程序过来的,那么恭喜,您不用配置环境了!🥳 |
||||
|
||||
- 如果您下载的是附带有Java运行环境的Dogename,那么您也不需要配置Java运行环境。 |
||||
|
||||
- 如果您都不是以上,您可以到[Java官网](https://www.java.com/)下载并安装,安装完成后,就好了。 |
||||
|
||||
### 运行与使用 |
||||
- 很简单,如果您的Java环境已经没问题了,就可以直接运行“dogename.exe”开始玩耍。 |
||||
- 您也可以运行“dogename_hide.exe”来隐式运行dogename(就是不会有黑框框显示出来),不过直接使用“dogename.exe”可以*在一定程度上*帮助您排查为何不能运行(如果您按照说明去做*一般*不会出现这种情况)。 |
||||
- 成功运行后,点击“安排一下”即可开始点名,不过此时还没有任何名字在名单中,因此您需要至少添加一个名字(或者先使用“数字模式”玩玩)。下面讲讲述如何添加一个或多个名字。 |
||||
|
||||
|
||||
|
||||
-------- |
||||
|
||||
|
||||
|
||||
## 2. 名单管理 |
||||
|
||||
首先,您需要点击主界面上的“名单管理”按钮,呼出名单管理面板,以便进行操作。此时名单列表会列出已经添加的名字。 |
||||
|
||||
### 添加一个或几个名字 |
||||
|
||||
1. 在名字输入框中输入想要添加的名字,如果输入多行名字,则可以同时添加对个名字(每一行识别为一个名字)。 |
||||
2. 输入完成后,点击"添加"按钮,即可在名单列表中看到刚刚添加进去的名字。 |
||||
|
||||
### 批量添加名字 |
||||
> 在上面“添加一个或几个名字”提到过,如果一行输入了一个名字,就可以同时添加多个名字(每一行识别为一个名字)。 |
||||
因此,根据这个原理,可以实现批量添加名字。 |
||||
|
||||
以下提供两种批量添加名字的方法: |
||||
|
||||
*(您也可以自己摸索其他的批量添加方法,只要最后能够使得名字输入框中每行拥有一个名字即可)* |
||||
|
||||
|
||||
##### 1. 通过Dogename自带的OCR(文字识别)功能来截取屏幕上的名字。 |
||||
- 点击名单管理面板上的“从屏幕上截取名字”,打开OCR模块。 |
||||
- 打开其他含有欲添加名单的文件*(例如Excel表格、Word文档、座位表图片等或者其他显示了名字的程序)*。 |
||||
- 然后切换到Dogename的文字识别窗口(注意请使显示了名字的界面保持显示),点击“截屏并开始识别”按钮。此时Dogename的界面将会被隐藏,以便进行截图操作。等待大约0.5秒,屏幕将会出现跟随鼠标位置的竖线和横线,这是方便您剪裁定位的。 |
||||
- 点击鼠标左键,选取*含有名字的区域*,松开鼠标后,将会完成截屏操作并开始识别。 |
||||
- 识别完成后,文字识别界面左侧的文本框将会显示出识别出的名字。如果文字关系清楚,识别出来的结果就是一行一个名字。如果不是,您可以手动修改,使得*一行只有一个名字* |
||||
- 修改完成后,将识别结果复制下来,粘贴在名字输入框中。点击“添加”按钮,即可完成添加。 |
||||
|
||||
下面的动图演示了如何进行这一操作: |
||||
|
||||
|
||||
|
||||
|
||||
 |
||||
|
||||
|
||||
|
||||
|
||||
##### 2. 从Word、Excel等含有表格式名单列表的地方复制粘贴。 |
||||
- 如果因为网络不畅或者其他原因无法使用文字识别功能,您可以使用这种办法。 |
||||
- 在其中的表格里,如果竖着选中文本,复制粘贴到名单输入框后一般就能够一行一个名字。点击“添加”按钮,即可批量添加上名字。 |
||||
|
||||
下面的动图演示了如何进行这一操作: |
||||
|
||||
|
||||
|
||||
|
||||
 |
||||
|
||||
|
||||
|
||||
|
||||
### 删除名字 |
||||
- 很简单,只需要在名单列表中选中欲删除的名字,点击“删除”按钮即可。 |
||||
- 点击“删除所有”按钮会删除名单列表中的所有名字。 |
||||
- 注意:除非已经备份好名单,否则无法撤销,请小心操作。 |
||||
|
||||
### 名单的导入和导出 |
||||
- 点击“备份”按钮,选择将要保存名单的地方,输入好文件名,点击确定,即可保存。 |
||||
- 点击“恢复”按钮,选择导出过的名单文件,点击确定,即可导入。 |
||||
注意:**导入名单会直接覆盖现有名单**,因此建议您在导入之前备份好现有名单。 |
||||
|
||||
### 打乱名字 |
||||
- 点击“打乱顺序”按钮,将会把名单中的名字随机排列,在*一定程度上(不是很严格地)*提高随机性。 |
||||
|
||||
|
||||
|
||||
-------- |
||||
|
||||
|
||||
|
||||
## 3. 选项设置 |
||||
|
||||
|
||||
|
||||
### 点名的设置 |
||||
|
||||
这里讲介绍一下几个方面的设置: |
||||
1. 点名规则 |
||||
2. 挑选次数 |
||||
3. 挑选速度 |
||||
4. 使用/不使用随机性更强的Java SecureRandom |
||||
5. 开启/不开启语言播报 |
||||
|
||||
|
||||
|
||||
-------------这是分割线------------- |
||||
|
||||
|
||||
|
||||
##### 1. 点名规则 |
||||
- 通过设置此项,可以按以下规则进行挑选: |
||||
- ①被点过的名字还要被点 |
||||
- ②被点过的名字不会再被点(默认使用) |
||||
- ~~娱乐模式*(①模式下可用)* ~~ *(已移除)* |
||||
- 机会均等*(②模式下可用,默认使用)* |
||||
|
||||
介绍: |
||||
- **娱乐模式**:旧称“套路模式”,勾选后会使被点过的名字在挑选列表中多出现4到5次,增加再次被点中的几率。 |
||||
**注意:仅在勾选此模式后点中的名字才会被多增加4到5次,不勾选时选中的名字不受影响。 |
||||
退出后会自动重置,不影响下次使用。** |
||||
|
||||
- **机会均等**:勾选“机会均等”后,将会保存已点过的的名字和数字到文件中,下次启动时仍不会被点到,直到全部名字或数字被点完 或点击“机会均等”的“重置”按钮。 |
||||
**注意:仅保存“这次点过就不点了”模式下选中的名字或数字。*** |
||||
|
||||
|
||||
##### 2. 挑选次数 |
||||
- 您可以调节名字随机滚动的次数,滚动显示多少个名字后,才是真正被选中的名字。 |
||||
--范围:3至200次 |
||||
--默认值:随机次数(范围:100至250次) |
||||
~~小问题:这个次数是不怎么准确的~~😓 |
||||
|
||||
##### 3. 挑选速度 |
||||
- 通过调节滑动条,您可以设置名字滚动的速度。数值越大速度越快。若调节为0,则显示一个名字后,会过100ms才显示下一个名字,直至出现正真被挑选中的名字。默认值:80 (20ms) |
||||
|
||||
##### 4. 设置是否使用Java SecureRandom |
||||
- 开启后,将使用Java SecureRandom来获得较强随机性的随机数,而不是普通的随机数算法。默认开启。如果您觉得开启后点名明显变卡(虽说不太可能),可以尝试关闭。 |
||||
|
||||
##### 5.设置是否开启语言播报 |
||||
- 开启后,点中名字后将会把被选中的名字用语音播放出来。默认开启。需要网络支持。如果因为各种原因无法/没必要播放,可以关闭这个功能。 |
||||
|
||||
|
||||
### 语音播报的设置 |
||||
- 在这里,你可以设置播报人,以及其语速和语调(默认都是5)。 |
||||
|
||||
|
||||
-------- |
||||
|
||||
|
||||
|
||||
## 4. 其他小功能的介绍&说明 |
||||
|
||||
#### 1. 历史记录 |
||||
- 在这里,你可以查看最近2000条点名记录。当记录超过2000条时,将会自动清空历史记录,重新从0开始记录,当然,您也可以手动清空。 |
||||
- 在搜索框输入文字后,点击“向上查找”或者“向下查找”按钮,可以查找出包含有您想要搜索的文字的记录。 |
||||
~~(该功能现阶段状况:容易出bug~~😫~~,搜寻替代方案ing...)~~ |
||||
#### 2. 小窗模式 |
||||
- 点击主界面的“小窗模式”按钮,可以将窗口变成小版界面,仅保留“安排一下”和“恢复”按钮,以及一个用于显示名字的文本。这个时候窗口总在最前端,拖动非按钮区域可以移动窗口。点击“恢复”按钮即可恢复原来的窗口状态。 |
@ -0,0 +1,41 @@ |
||||
# 你想瞅一瞅的截图 |
||||
您看好了啊🧐 |
||||
|
||||
*此截图为Windows 10下的效果,不同的系统**可能**会有不同的效果* |
||||
|
||||
*这里的截图不是最新的版本,因此可能会有一定的差别,请以实物为准* |
||||
|
||||
## 1. 第一界面 |
||||
#### a. 古诗词: |
||||
|
||||
 |
||||
|
||||
#### b. 一言: |
||||
|
||||
 |
||||
|
||||
## 2. 主界面 |
||||
#### a. 未挑选时: |
||||
|
||||
 |
||||
|
||||
#### b. 选中一个名字: |
||||
 |
||||
|
||||
## 3. “迷你模式”界面 |
||||
 |
||||
|
||||
## 4. “名单管理”界面 |
||||
 |
||||
|
||||
## 5. 设置界面 |
||||
 |
||||
|
||||
## 6. OCR模块界面 |
||||
 |
||||
|
||||
## 7. “程序信息”界面 |
||||
 |
||||
|
||||
## 8. 还有更多的吗? |
||||
[下载](https://github.com/eatenid/dogename/releases "下载")下来看看吧😀 |
@ -0,0 +1,34 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<configuration status="error"> |
||||
<!--先定义所有的appender--> |
||||
<appenders> |
||||
<!--这个输出控制台的配置--> |
||||
<Console name="Console" target="SYSTEM_OUT"> |
||||
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)--> |
||||
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/> |
||||
<!--这个都知道是输出日志的格式--> |
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %l:%m%n "/> |
||||
</Console> |
||||
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用--> |
||||
<File name="log" fileName="log/test.log" append="false"> |
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %l:%m%n "/> |
||||
</File> |
||||
|
||||
<!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> |
||||
<RollingFile name="RollingFile" fileName="log/app.log" |
||||
filePattern="log/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> |
||||
<PatternLayout pattern=" %-5level %class{36} %L %M - %msg%xEx%n"/> |
||||
<SizeBasedTriggeringPolicy size="50MB"/> |
||||
</RollingFile> |
||||
</appenders> |
||||
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效--> |
||||
<loggers> |
||||
<!--建立一个默认的root的logger--> |
||||
<root level="trace"> |
||||
<appender-ref ref="RollingFile"/> |
||||
<appender-ref ref="Console"/> |
||||
</root> |
||||
|
||||
</loggers> |
||||
</configuration> |
@ -0,0 +1,21 @@ |
||||
package me.lensferno.dogename; |
||||
|
||||
import me.lensferno.dogename.resources.MainInterfaceImage; |
||||
import me.lensferno.dogename.resources.dogename; |
||||
import org.apache.commons.codec.binary.Base64; |
||||
|
||||
import java.io.ByteArrayInputStream; |
||||
import java.io.InputStream; |
||||
|
||||
public class DataReleaser { |
||||
|
||||
public static InputStream getDogenameStream(){ |
||||
return new ByteArrayInputStream(Base64.decodeBase64(dogename.data)); |
||||
} |
||||
|
||||
public static InputStream getMainPicStream(){ |
||||
return new ByteArrayInputStream(Base64.decodeBase64(MainInterfaceImage.data)); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,66 @@ |
||||
package me.lensferno.dogename; |
||||
|
||||
import javafx.application.Application; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.Parent; |
||||
import javafx.scene.Scene; |
||||
import javafx.stage.Stage; |
||||
import me.lensferno.dogename.configs.ConfigLoader; |
||||
import me.lensferno.dogename.controllers.MainInterfaceController; |
||||
import me.lensferno.dogename.sayings.Gushici; |
||||
import me.lensferno.dogename.sayings.Hitokoto; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.util.Random; |
||||
|
||||
public class Main extends Application { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
public static void main(String[] args){ launch(args);} |
||||
|
||||
@Override |
||||
public void start(Stage primaryStage) { |
||||
FXMLLoader fxmlLoader; |
||||
Parent parent; |
||||
|
||||
try{ |
||||
fxmlLoader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/MainInterface.fxml")); |
||||
parent=fxmlLoader.load(); |
||||
}catch (Exception e){ |
||||
log.error("Error to load main interface FXML :"+e.toString()); |
||||
return; |
||||
} |
||||
|
||||
Scene scene=new Scene(parent,990,700); |
||||
primaryStage.setTitle("DogeName 叁号姬"); |
||||
primaryStage.setScene(scene); |
||||
|
||||
primaryStage.show(); |
||||
|
||||
ConfigLoader configLoader=new ConfigLoader(); |
||||
|
||||
MainInterfaceController mainInterfaceController=fxmlLoader.getController(); |
||||
|
||||
mainInterfaceController.setToggleGroup(); |
||||
|
||||
mainInterfaceController.setUpConfig(configLoader); |
||||
|
||||
mainInterfaceController.bindProperties(); |
||||
|
||||
mainInterfaceController.setImg(DataReleaser.getMainPicStream()); |
||||
|
||||
primaryStage.setOnCloseRequest(event -> configLoader.writeAllConfigToFile(configLoader.getMainConfigLocation(),configLoader.getVoiceConfigLocation())); |
||||
|
||||
if (mainInterfaceController.getMainConfig().isShowSaying()) { |
||||
if (new Random().nextBoolean()){ |
||||
new Gushici().showGushici(mainInterfaceController.getRootPane(),mainInterfaceController.getTopBar()); |
||||
}else { |
||||
new Hitokoto().showHitokoto(mainInterfaceController.getRootPane(),mainInterfaceController.getTopBar()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,212 @@ |
||||
package me.lensferno.dogename.configs; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.GsonBuilder; |
||||
import javafx.beans.property.*; |
||||
import me.lensferno.dogename.configs.adapters.BooleanPropertyAdapter; |
||||
import me.lensferno.dogename.configs.adapters.DoublePropertyAdapter; |
||||
import me.lensferno.dogename.configs.adapters.IntegerPropertyAdapter; |
||||
import me.lensferno.dogename.configs.adapters.StringPropertyAdapter; |
||||
import org.apache.commons.io.IOUtils; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.*; |
||||
import java.nio.charset.StandardCharsets; |
||||
|
||||
public class ConfigLoader { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
//ConfigValuesBean config;
|
||||
private MainConfig mainConfig; |
||||
private VoiceConfig voiceConfig; |
||||
|
||||
private final String mainConfigLocation = "files"+ File.separator+"Config.json"; |
||||
private final String voiceConfigLocation = "files"+ File.separator+"VoiceConfig.json"; |
||||
|
||||
public String getMainConfigLocation() { |
||||
return mainConfigLocation; |
||||
} |
||||
|
||||
public String getVoiceConfigLocation() { |
||||
return voiceConfigLocation; |
||||
} |
||||
|
||||
public MainConfig getMainConfig() { |
||||
return mainConfig; |
||||
} |
||||
|
||||
public MainConfig readConfigFromFile(String fileLocation){ |
||||
|
||||
//property属性应该要自定义一个json适配器才能解析出来
|
||||
Gson gson=new GsonBuilder() |
||||
.registerTypeAdapter(SimpleBooleanProperty.class,new BooleanPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleIntegerProperty.class,new IntegerPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleStringProperty.class,new StringPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleDoubleProperty.class,new DoublePropertyAdapter()) |
||||
.setPrettyPrinting() |
||||
.create(); |
||||
|
||||
String ConfigJSON; |
||||
|
||||
try{ |
||||
File configFile=new File(fileLocation); |
||||
if(!configFile.exists()){ |
||||
configFile.getParentFile().mkdirs(); |
||||
configFile.createNewFile(); |
||||
mainConfig=new MainConfig(); |
||||
writeMainConfigToFile(mainConfigLocation); |
||||
return mainConfig; |
||||
} |
||||
InputStream inputStream=new FileInputStream(configFile); |
||||
ConfigJSON=IOUtils.toString(inputStream, StandardCharsets.UTF_8); |
||||
|
||||
mainConfig=gson.fromJson(ConfigJSON,MainConfig.class); |
||||
|
||||
if (mainConfig == null) { |
||||
mainConfig=new MainConfig(); |
||||
writeMainConfigToFile(mainConfigLocation); |
||||
return mainConfig; |
||||
} |
||||
|
||||
}catch (Exception e){ |
||||
log.error("Error to load config file:"+e+"\nUse Default config."); |
||||
|
||||
mainConfig=new MainConfig(); |
||||
writeMainConfigToFile(mainConfigLocation); |
||||
return mainConfig; |
||||
} |
||||
|
||||
return this.mainConfig; |
||||
} |
||||
|
||||
public VoiceConfig readVoiceConfigFromFile(String fileLocation){ |
||||
|
||||
//property属性应该要自定义一个json适配器才能解析出来
|
||||
Gson gson=new GsonBuilder() |
||||
.registerTypeAdapter(SimpleBooleanProperty.class,new BooleanPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleIntegerProperty.class,new IntegerPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleStringProperty.class,new StringPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleDoubleProperty.class,new DoublePropertyAdapter()) |
||||
.setPrettyPrinting() |
||||
.create(); |
||||
|
||||
String ConfigJSON; |
||||
|
||||
try{ |
||||
File configFile=new File(fileLocation); |
||||
if(!configFile.exists()){ |
||||
configFile.getParentFile().mkdirs(); |
||||
configFile.createNewFile(); |
||||
|
||||
voiceConfig=new VoiceConfig(); |
||||
writeVoiceConfigToFile(voiceConfigLocation); |
||||
return voiceConfig; |
||||
} |
||||
InputStream inputStream=new FileInputStream(configFile); |
||||
ConfigJSON=IOUtils.toString(inputStream, StandardCharsets.UTF_8); |
||||
|
||||
writeVoiceConfigToFile(voiceConfigLocation); |
||||
voiceConfig=gson.fromJson(ConfigJSON,VoiceConfig.class); |
||||
if (voiceConfig == null) { |
||||
voiceConfig=new VoiceConfig(); |
||||
writeVoiceConfigToFile(voiceConfigLocation); |
||||
return voiceConfig; |
||||
} |
||||
|
||||
}catch (Exception e){ |
||||
log.error("Error to load voice config file:"+e+"\nUse Default voice config."); |
||||
|
||||
voiceConfig=new VoiceConfig(); |
||||
writeVoiceConfigToFile(voiceConfigLocation); |
||||
return voiceConfig; |
||||
} |
||||
|
||||
return this.voiceConfig; |
||||
} |
||||
|
||||
//
|
||||
public MainConfig setValuesToProperty(){ |
||||
//mainconfig.set..(config.get..)
|
||||
//...so on
|
||||
//
|
||||
return this.mainConfig; |
||||
} |
||||
|
||||
private String toJSON(MainConfig config){ |
||||
|
||||
Gson gson=new GsonBuilder() |
||||
.registerTypeAdapter(SimpleBooleanProperty.class,new BooleanPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleIntegerProperty.class,new IntegerPropertyAdapter()) |
||||
.registerTypeAdapter(SimpleStringProperty.class,new StringPropertyAdapter()) |
||||
.setPrettyPrinting() |
||||
.create(); |
||||
|
||||
return gson.toJson(config); |
||||
} |
||||
|
||||
private String VoiceConfigtoJSON(VoiceConfig config){ |
||||
|
||||
Gson gson=new GsonBuilder() |
||||
.registerTypeAdapter(SimpleDoubleProperty.class,new DoublePropertyAdapter()) |
||||
.setPrettyPrinting() |
||||
.create(); |
||||
|
||||
return gson.toJson(config); |
||||
} |
||||
|
||||
public void writeAllConfigToFile(String outputLocation, String voiceConfigFile){ |
||||
File outputFile = new File(outputLocation); |
||||
|
||||
try{ |
||||
if(! outputFile.exists()){ |
||||
outputFile.getParentFile().mkdirs(); |
||||
outputFile.createNewFile(); |
||||
} |
||||
OutputStream stream=new FileOutputStream(outputFile); |
||||
IOUtils.write(toJSON(this.mainConfig).getBytes(StandardCharsets.UTF_8),stream); |
||||
|
||||
OutputStream voiceConfigFileStream=new FileOutputStream(voiceConfigFile); |
||||
IOUtils.write(VoiceConfigtoJSON(this.voiceConfig).getBytes(StandardCharsets.UTF_8),voiceConfigFileStream); |
||||
|
||||
}catch (Exception e){ |
||||
log.error("Error in writing all config:"+e); |
||||
} |
||||
} |
||||
|
||||
public void writeMainConfigToFile(String outputLocation){ |
||||
File outputFile = new File(outputLocation); |
||||
|
||||
try{ |
||||
if(! outputFile.exists()){ |
||||
outputFile.getParentFile().mkdirs(); |
||||
outputFile.createNewFile(); |
||||
} |
||||
|
||||
OutputStream stream=new FileOutputStream(outputFile); |
||||
IOUtils.write(toJSON(this.mainConfig).getBytes(StandardCharsets.UTF_8),stream); |
||||
|
||||
}catch (Exception e){ |
||||
log.error("Error in writing main config:"+e); |
||||
} |
||||
} |
||||
|
||||
public void writeVoiceConfigToFile(String voiceConfigFile){ |
||||
File outputFile = new File(voiceConfigFile); |
||||
|
||||
try{ |
||||
|
||||
if(! outputFile.exists()) { |
||||
outputFile.getParentFile().mkdirs(); |
||||
outputFile.createNewFile(); |
||||
} |
||||
OutputStream voiceConfigFileStream=new FileOutputStream(voiceConfigFile); |
||||
IOUtils.write(VoiceConfigtoJSON(this.voiceConfig).getBytes(StandardCharsets.UTF_8),voiceConfigFileStream); |
||||
|
||||
}catch (Exception e){ |
||||
log.error("Error in writing voice config:"+e); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,4 @@ |
||||
package me.lensferno.dogename.configs; |
||||
|
||||
public class ConfigValuesBean { |
||||
} |
@ -0,0 +1,242 @@ |
||||
package me.lensferno.dogename.configs; |
||||
|
||||
import com.google.gson.annotations.Expose; |
||||
import javafx.beans.property.*; |
||||
|
||||
public class MainConfig { |
||||
|
||||
// ConfigValuesBean configValuesBean =new ConfigValuesBean();
|
||||
|
||||
// ---------------------- Default values ---------------------------------------------------------
|
||||
|
||||
@Expose |
||||
private final String NEWEST_CONFIG_VERSION = "2"; |
||||
|
||||
private String currentConfigVersion = null; |
||||
|
||||
@Expose |
||||
public final boolean DEFAULT_NAME_CHOOSE = true; |
||||
|
||||
public final int METHOD_NAME = 0; // 名字挑选法
|
||||
public final int METHOD_NUMBER = 1; // 数字挑选法
|
||||
|
||||
public final int DEFAULT_CYCLE_TIMES = 120; // 默认轮回次数:120
|
||||
public final int DEFAULT_SPEED = 80; // 默认速度:20ms,对应滑动条80的位置
|
||||
|
||||
public final boolean DEFAULT_RANDOM_TIMES = true; // 默认挑选轮回次数是否随机:ture
|
||||
|
||||
public final boolean DEFAULT_IGNORE_PAST = true; // 默认忽略已经点过的名字:ture
|
||||
|
||||
public final boolean DEFAULT_EQUAL_MODE = true; // 默认开启"机会均等"
|
||||
|
||||
public final boolean DEFAULT_NEW_ALGO = true; // 默认使用新算法"Java sec random"
|
||||
public final boolean DEFAULT_VOICE_PLAY = true; // 默认使用语音播报
|
||||
|
||||
public final boolean DEFAULT_SHOW_SAYING = true; |
||||
|
||||
// ----------------------Properties----------------------------------------------------------------
|
||||
|
||||
private SimpleBooleanProperty nameChooseProperty; |
||||
|
||||
private SimpleBooleanProperty randomTimesProperty; // 挑选次数是否随机
|
||||
private SimpleBooleanProperty ignorePastProperty; // 是否忽略已经被点过的名字
|
||||
|
||||
private SimpleIntegerProperty chooseMethodProperty; // 挑选方式: 0->名字挑选法 1->数字挑选法
|
||||
private SimpleIntegerProperty cycleTimesProperty; // 挑选轮回次数,旧称"chosenTime"
|
||||
|
||||
private SimpleIntegerProperty speedProperty; // 速度
|
||||
|
||||
private SimpleStringProperty minNumberProperty; // 最小值
|
||||
private SimpleStringProperty maxNumberProperty; // 最大值
|
||||
|
||||
private SimpleBooleanProperty equalModeProperty; // 是否开启"机会均等"
|
||||
|
||||
private SimpleBooleanProperty newAlgoProperty; // 是否使用新算法
|
||||
private SimpleBooleanProperty voicePlayProperty; // 是否使用语音播报
|
||||
|
||||
private SimpleBooleanProperty showSaying; |
||||
|
||||
// -------------------------- 初始化 --------------------------------------------------------------
|
||||
public MainConfig() { |
||||
randomTimesProperty = new SimpleBooleanProperty(DEFAULT_RANDOM_TIMES); |
||||
ignorePastProperty = new SimpleBooleanProperty(DEFAULT_IGNORE_PAST); |
||||
|
||||
chooseMethodProperty = new SimpleIntegerProperty(METHOD_NAME); |
||||
nameChooseProperty = new SimpleBooleanProperty(DEFAULT_NAME_CHOOSE); |
||||
|
||||
cycleTimesProperty = new SimpleIntegerProperty(DEFAULT_CYCLE_TIMES); |
||||
|
||||
speedProperty = new SimpleIntegerProperty(DEFAULT_SPEED); |
||||
|
||||
minNumberProperty = new SimpleStringProperty("0"); |
||||
maxNumberProperty = new SimpleStringProperty("10"); |
||||
|
||||
equalModeProperty = new SimpleBooleanProperty(DEFAULT_EQUAL_MODE); |
||||
|
||||
newAlgoProperty = new SimpleBooleanProperty(DEFAULT_NEW_ALGO); |
||||
voicePlayProperty = new SimpleBooleanProperty(DEFAULT_VOICE_PLAY); |
||||
|
||||
showSaying = new SimpleBooleanProperty(DEFAULT_SHOW_SAYING); |
||||
|
||||
currentConfigVersion = NEWEST_CONFIG_VERSION; |
||||
} |
||||
|
||||
// -------------------------- Getters and Setters ---------------------------------------------
|
||||
|
||||
public boolean isNameChooseProperty() { |
||||
return nameChooseProperty.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty nameChoosePropertyProperty() { |
||||
return nameChooseProperty; |
||||
} |
||||
|
||||
public void setNameChooseProperty(boolean nameChooseProperty) { |
||||
this.nameChooseProperty.set(nameChooseProperty); |
||||
} |
||||
|
||||
public boolean isRandomTimesProperty() { |
||||
return randomTimesProperty.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty randomTimesPropertyProperty() { |
||||
return randomTimesProperty; |
||||
} |
||||
|
||||
public void setRandomTimesProperty(boolean randomTimesProperty) { |
||||
this.randomTimesProperty.set(randomTimesProperty); |
||||
} |
||||
|
||||
public boolean isIgnorePastProperty() { |
||||
return ignorePastProperty.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty ignorePastPropertyProperty() { |
||||
return ignorePastProperty; |
||||
} |
||||
|
||||
public void setIgnorePastProperty(boolean ignorePastProperty) { |
||||
this.ignorePastProperty.set(ignorePastProperty); |
||||
} |
||||
|
||||
public int getChooseMethodProperty() { |
||||
return chooseMethodProperty.get(); |
||||
} |
||||
|
||||
public SimpleIntegerProperty chooseMethodPropertyProperty() { |
||||
return chooseMethodProperty; |
||||
} |
||||
|
||||
public void setChooseMethodProperty(int chooseMethodProperty) { |
||||
this.chooseMethodProperty.set(chooseMethodProperty); |
||||
} |
||||
|
||||
public int getCycleTimesProperty() { |
||||
return cycleTimesProperty.get(); |
||||
} |
||||
|
||||
public SimpleIntegerProperty cycleTimesPropertyProperty() { |
||||
return cycleTimesProperty; |
||||
} |
||||
|
||||
public void setCycleTimesProperty(int cycleTimesProperty) { |
||||
this.cycleTimesProperty.set(cycleTimesProperty); |
||||
} |
||||
|
||||
public int getSpeedProperty() { |
||||
return speedProperty.get(); |
||||
} |
||||
|
||||
public SimpleIntegerProperty speedPropertyProperty() { |
||||
return speedProperty; |
||||
} |
||||
|
||||
public void setSpeedProperty(int speedProperty) { |
||||
this.speedProperty.set(speedProperty); |
||||
} |
||||
|
||||
public String getMinNumberProperty() { |
||||
return minNumberProperty.get(); |
||||
} |
||||
|
||||
public SimpleStringProperty minNumberPropertyProperty() { |
||||
return minNumberProperty; |
||||
} |
||||
|
||||
public void setMinNumberProperty(String minNumberProperty) { |
||||
this.minNumberProperty.set(minNumberProperty); |
||||
} |
||||
|
||||
public String getMaxNumberProperty() { |
||||
return maxNumberProperty.get(); |
||||
} |
||||
|
||||
public SimpleStringProperty maxNumberPropertyProperty() { |
||||
return maxNumberProperty; |
||||
} |
||||
|
||||
public void setMaxNumberProperty(String maxNumberProperty) { |
||||
this.maxNumberProperty.set(maxNumberProperty); |
||||
} |
||||
|
||||
public boolean isEqualModeProperty() { |
||||
return equalModeProperty.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty equalModePropertyProperty() { |
||||
return equalModeProperty; |
||||
} |
||||
|
||||
public void setEqualModeProperty(boolean equalModeProperty) { |
||||
this.equalModeProperty.set(equalModeProperty); |
||||
} |
||||
|
||||
public boolean isNewAlgoProperty() { |
||||
return newAlgoProperty.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty newAlgoPropertyProperty() { |
||||
return newAlgoProperty; |
||||
} |
||||
|
||||
public void setNewAlgoProperty(boolean newAlgoProperty) { |
||||
this.newAlgoProperty.set(newAlgoProperty); |
||||
} |
||||
|
||||
public boolean isVoicePlayProperty() { |
||||
return voicePlayProperty.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty voicePlayPropertyProperty() { |
||||
return voicePlayProperty; |
||||
} |
||||
|
||||
public void setVoicePlayProperty(boolean voicePlayProperty) { |
||||
this.voicePlayProperty.set(voicePlayProperty); |
||||
} |
||||
|
||||
public boolean isShowSaying() { |
||||
return showSaying.get(); |
||||
} |
||||
|
||||
public SimpleBooleanProperty showSayingProperty() { |
||||
return showSaying; |
||||
} |
||||
|
||||
public void setShowSaying(boolean showSaying) { |
||||
this.showSaying.set(showSaying); |
||||
} |
||||
|
||||
public String getCurrentConfigVersion() { |
||||
return currentConfigVersion; |
||||
} |
||||
|
||||
public void setCurrentConfigVersion(String currentConfigVersion) { |
||||
this.currentConfigVersion = currentConfigVersion; |
||||
} |
||||
|
||||
public String getNewestConfigVersion() { |
||||
return NEWEST_CONFIG_VERSION; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,75 @@ |
||||
package me.lensferno.dogename.configs; |
||||
|
||||
import javafx.beans.property.SimpleDoubleProperty; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
|
||||
public class VoiceConfig { |
||||
|
||||
private String speaker; |
||||
private int selectedSpeaker; |
||||
|
||||
|
||||
//度小宇=1,度小美=0,度逍遥=3,度丫丫=4
|
||||
//度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
|
||||
|
||||
private SimpleDoubleProperty speed; |
||||
private SimpleDoubleProperty intonation; |
||||
|
||||
public String getSpeaker() { |
||||
return speaker; |
||||
} |
||||
|
||||
public void setSpeaker(String speaker) { |
||||
this.speaker = speaker; |
||||
} |
||||
|
||||
public final int DEFAULT_SPEED=5; |
||||
public final int DEFAULT_INTONATION=5; |
||||
|
||||
public VoiceConfig(){ |
||||
selectedSpeaker=0; |
||||
speaker="1"; |
||||
speed=new SimpleDoubleProperty(DEFAULT_SPEED); |
||||
intonation=new SimpleDoubleProperty(DEFAULT_INTONATION); |
||||
} |
||||
|
||||
public int getSelectedSpeaker() { |
||||
return selectedSpeaker; |
||||
} |
||||
|
||||
public void setSelectedSpeaker(int selectedSpeaker) { |
||||
this.selectedSpeaker = selectedSpeaker; |
||||
} |
||||
public double getSpeed() { |
||||
return speed.get(); |
||||
} |
||||
|
||||
public SimpleDoubleProperty speedProperty() { |
||||
return speed; |
||||
} |
||||
|
||||
public void setSpeed(double speed) { |
||||
this.speed.set(speed); |
||||
} |
||||
|
||||
public double getIntonation() { |
||||
return intonation.get(); |
||||
} |
||||
|
||||
public SimpleDoubleProperty intonationProperty() { |
||||
return intonation; |
||||
} |
||||
|
||||
public void setIntonation(double intonation) { |
||||
this.intonation.set(intonation); |
||||
} |
||||
|
||||
@FXML |
||||
void showAdvancedVoiceSettings(ActionEvent event) { |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,27 @@ |
||||
package me.lensferno.dogename.configs.adapters; |
||||
|
||||
import com.google.gson.*; |
||||
import javafx.beans.property.SimpleBooleanProperty; |
||||
|
||||
import java.lang.reflect.Type; |
||||
|
||||
public class BooleanPropertyAdapter implements JsonSerializer<SimpleBooleanProperty>, JsonDeserializer<SimpleBooleanProperty> { |
||||
|
||||
@Override |
||||
public SimpleBooleanProperty deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { |
||||
if(jsonElement==null) { |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new SimpleBooleanProperty(jsonElement.getAsBoolean()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public JsonElement serialize(SimpleBooleanProperty simpleBooleanProperty, Type type, JsonSerializationContext jsonSerializationContext) { |
||||
if(simpleBooleanProperty==null){ |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new JsonPrimitive(simpleBooleanProperty.get()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
package me.lensferno.dogename.configs.adapters; |
||||
|
||||
import com.google.gson.*; |
||||
import javafx.beans.property.SimpleDoubleProperty; |
||||
|
||||
import java.lang.reflect.Type; |
||||
|
||||
public class DoublePropertyAdapter implements JsonSerializer<SimpleDoubleProperty>, JsonDeserializer<SimpleDoubleProperty> { |
||||
|
||||
@Override |
||||
public SimpleDoubleProperty deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { |
||||
if(jsonElement==null) { |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new SimpleDoubleProperty(jsonElement.getAsDouble()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public JsonElement serialize(SimpleDoubleProperty simpleDoubleProperty, Type type, JsonSerializationContext jsonSerializationContext) { |
||||
if(simpleDoubleProperty==null){ |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new JsonPrimitive(simpleDoubleProperty.get()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
package me.lensferno.dogename.configs.adapters; |
||||
|
||||
import com.google.gson.*; |
||||
import javafx.beans.property.SimpleIntegerProperty; |
||||
|
||||
import java.lang.reflect.Type; |
||||
|
||||
public class IntegerPropertyAdapter implements JsonSerializer<SimpleIntegerProperty>, JsonDeserializer<SimpleIntegerProperty> { |
||||
@Override |
||||
public SimpleIntegerProperty deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { |
||||
if(jsonElement==null) { |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new SimpleIntegerProperty(jsonElement.getAsInt()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public JsonElement serialize(SimpleIntegerProperty simpleIntegerProperty, Type type, JsonSerializationContext jsonSerializationContext) { |
||||
if(simpleIntegerProperty==null){ |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new JsonPrimitive(simpleIntegerProperty.get()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@ |
||||
package me.lensferno.dogename.configs.adapters; |
||||
|
||||
import com.google.gson.*; |
||||
import javafx.beans.property.SimpleStringProperty; |
||||
|
||||
import java.lang.reflect.Type; |
||||
|
||||
public class StringPropertyAdapter implements JsonSerializer<SimpleStringProperty>, JsonDeserializer<SimpleStringProperty> { |
||||
@Override |
||||
public SimpleStringProperty deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { |
||||
if(jsonElement==null) { |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new SimpleStringProperty(jsonElement.getAsString()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public JsonElement serialize(SimpleStringProperty simpleStringProperty, Type type, JsonSerializationContext jsonSerializationContext) { |
||||
if(simpleStringProperty==null) { |
||||
throw new JsonParseException("Json is wrong."); |
||||
}else { |
||||
return new JsonPrimitive(simpleStringProperty.get()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,39 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.layout.VBox; |
||||
import javafx.scene.text.Text; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
|
||||
public class GushiciPaneController extends VBox { |
||||
|
||||
Logger log= LogManager.getLogger(); |
||||
@FXML |
||||
public Text contentText; |
||||
|
||||
@FXML |
||||
public Text contentType; |
||||
|
||||
@FXML |
||||
public Text contentInfo; |
||||
|
||||
public GushiciPaneController (String content,String title,String author,String type){ |
||||
|
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/GushiciPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
try { |
||||
loader.load(); |
||||
}catch(Exception e){ |
||||
log.error("Error to load Gushici pane FXML: "+e.toString()); |
||||
|
||||
//e.printStackTrace();
|
||||
} |
||||
contentText.setText("“"+content+"”"); |
||||
contentInfo.setText("《"+title+"》"+"——"+author); |
||||
contentType.setText(type); |
||||
} |
||||
} |
@ -0,0 +1,126 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.*; |
||||
import javafx.collections.FXCollections; |
||||
import javafx.collections.ObservableList; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.scene.layout.VBox; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.data.History; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
public class HistoryPaneController extends VBox { |
||||
Logger log= LogManager.getLogger(HitokotoPaneController.class); |
||||
|
||||
History history; |
||||
Pane rootPane; |
||||
|
||||
public static final ObservableList<String> shownHistoryList = FXCollections.observableArrayList(); |
||||
|
||||
public HistoryPaneController(History history, Pane rootPane){ |
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/HistoryPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
this.history=history; |
||||
this.rootPane=rootPane; |
||||
|
||||
try { |
||||
loader.load(); |
||||
shownHistoryList.setAll(history.getHistoryList()); |
||||
historyList.setItems(shownHistoryList); |
||||
searchBar.textProperty().addListener((observable, oldValue, newValue) -> pointer = 0); |
||||
|
||||
}catch(Exception e){ |
||||
log.error("Error in loading history Fxml:"+e.toString()); |
||||
} |
||||
} |
||||
|
||||
@FXML |
||||
private JFXListView<String> historyList; |
||||
|
||||
@FXML |
||||
private JFXTextField searchBar; |
||||
|
||||
@FXML |
||||
private JFXButton previousBtn; |
||||
|
||||
@FXML |
||||
private JFXButton nextBtn; |
||||
|
||||
private void pointOutSearchResult(int pointer){ |
||||
historyList.getSelectionModel().select(pointer); |
||||
} |
||||
|
||||
int pointer=0; |
||||
|
||||
@FXML |
||||
void upSearch(ActionEvent event) { |
||||
|
||||
String searchText=searchBar.getText(); |
||||
String[] historyArrayList =history.getHistoryList().toArray(new String[0]); |
||||
|
||||
if (historyArrayList.length==0){ |
||||
return; |
||||
} |
||||
|
||||
if (pointer>historyArrayList.length-1||pointer<0){ |
||||
pointer=historyArrayList.length-1; |
||||
} |
||||
|
||||
while (!historyArrayList[pointer].contains(searchText)){ |
||||
pointer--; |
||||
if (pointer<0){ |
||||
pointer=historyArrayList.length-1; |
||||
return; |
||||
} |
||||
} |
||||
pointOutSearchResult(pointer); |
||||
pointer--; |
||||
if (pointer<0){ |
||||
pointer=historyArrayList.length-1; |
||||
} |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void downSearch(ActionEvent event) { |
||||
|
||||
String searchText=searchBar.getText(); |
||||
String[] historyArrayList =history.getHistoryList().toArray(new String[0]); |
||||
|
||||
if (historyArrayList.length==0){ |
||||
return; |
||||
} |
||||
|
||||
if (pointer>historyArrayList.length-1||pointer<0){ |
||||
pointer=0; |
||||
} |
||||
|
||||
while (!historyArrayList[pointer].contains(searchText)){ |
||||
pointer++; |
||||
if (pointer<historyArrayList.length-1){ |
||||
pointer=0; |
||||
return; |
||||
} |
||||
} |
||||
pointOutSearchResult(pointer); |
||||
pointer++; |
||||
if (pointer<historyArrayList.length-1){ |
||||
pointer=0; |
||||
} |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void clearHistory(){ |
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel("且慢!","真的要清除全部历史记录吗?",(e)-> { |
||||
this.history.clearHistory(); |
||||
pointer=0; |
||||
}); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,337 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.*; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.Parent; |
||||
import javafx.scene.Scene; |
||||
import javafx.scene.control.*; |
||||
import javafx.scene.image.Image; |
||||
import javafx.scene.image.ImageView; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.stage.Stage; |
||||
import javafx.stage.StageStyle; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.choose.Chooser; |
||||
import me.lensferno.dogename.configs.ConfigLoader; |
||||
import me.lensferno.dogename.configs.MainConfig; |
||||
import me.lensferno.dogename.configs.VoiceConfig; |
||||
import me.lensferno.dogename.data.History; |
||||
import me.lensferno.dogename.data.NameData; |
||||
import me.lensferno.dogename.ocr.Ocr; |
||||
import me.lensferno.dogename.voice.Token; |
||||
import me.lensferno.dogename.voice.TokenManager; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
import java.util.HashSet; |
||||
import java.util.Random; |
||||
|
||||
public final class MainInterfaceController { |
||||
|
||||
public JFXTextArea message; |
||||
|
||||
//ConfigLoader configLoader=new ConfigLoader();
|
||||
|
||||
Token token; |
||||
TokenManager tokenManager=new TokenManager(); |
||||
|
||||
Ocr ocrTool=null; |
||||
|
||||
History history=new History(); |
||||
|
||||
@FXML |
||||
private Pane rootPane; |
||||
|
||||
@FXML |
||||
private JFXRadioButton nameChoose; |
||||
|
||||
@FXML |
||||
private JFXButton showHistoryBtn; |
||||
|
||||
@FXML |
||||
private JFXRadioButton numbChoose; |
||||
|
||||
@FXML |
||||
private JFXButton anPaiBtn; |
||||
|
||||
@FXML |
||||
private JFXButton anPaiX10Btn; |
||||
|
||||
@FXML |
||||
private Pane mainPane; |
||||
|
||||
@FXML |
||||
private Label topBar; |
||||
|
||||
@FXML |
||||
private JFXButton showNameMangerButton; |
||||
|
||||
@FXML |
||||
private Label chosen_1; |
||||
|
||||
@FXML |
||||
private ImageView mainView; |
||||
|
||||
@FXML |
||||
private JFXButton miniModeBtn; |
||||
|
||||
@FXML |
||||
private Label chosen_2; |
||||
|
||||
public MainInterfaceController(){ |
||||
history.loadHistory(); |
||||
nameData.readIgnoreList(); |
||||
tokenManager.init(); |
||||
this.ignoreNameList=nameData.getIgnoreNameList(); |
||||
this.ignoreNumberList=nameData.getIgnoreNumberList(); |
||||
if(tokenManager.getTokenStatus().equals("ok")){ |
||||
token=tokenManager.getToken(); |
||||
} |
||||
} |
||||
|
||||
MainConfig mainConfig; |
||||
VoiceConfig voiceConfig; |
||||
|
||||
public void bindProperties(){ |
||||
nameChoose.selectedProperty().bindBidirectional(mainConfig.nameChoosePropertyProperty()); |
||||
//mainConfig.nameChoosePropertyProperty().not()
|
||||
|
||||
numbChoose.selectedProperty().bind(mainConfig.nameChoosePropertyProperty().not()); |
||||
numbChoose.selectedProperty().unbind(); |
||||
|
||||
/* |
||||
mainConfig.nameChoosePropertyProperty().addListener((observable, oldValue, newValue) -> { |
||||
//numbChoose.selectedProperty().unbind();
|
||||
numbChoose.setSelected(oldValue); |
||||
});*/ |
||||
|
||||
} |
||||
|
||||
public void setImg(InputStream stream){ |
||||
mainView.setImage(new Image(stream)); |
||||
} |
||||
|
||||
public void setUpConfig(ConfigLoader configLoader){ |
||||
mainConfig=configLoader.readConfigFromFile("files"+ File.separator +"Config.json"); |
||||
voiceConfig=configLoader.readVoiceConfigFromFile("files"+ File.separator +"VoiceConfig.json"); |
||||
} |
||||
|
||||
@FXML |
||||
void showProgramInfo(ActionEvent event) { |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("程序信息",new ProgramInfoPaneController(rootPane)); |
||||
} |
||||
|
||||
|
||||
@FXML |
||||
void showNameManger(ActionEvent event) { |
||||
|
||||
if (chooser.isRunning()){ |
||||
new DialogMaker(rootPane).createMessageDialog("(・。・)","安排中......\n为保证运行的稳定,此时还不能进行该操作哦。"); |
||||
return; |
||||
} |
||||
NameManagerPaneController nameManagerPaneController =new NameManagerPaneController(nameData,rootPane,ocrTool); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("名单管理",nameManagerPaneController); |
||||
} |
||||
|
||||
|
||||
|
||||
@FXML |
||||
void showNunberSetting(ActionEvent event) { |
||||
|
||||
if (chooser.isRunning()){ |
||||
new DialogMaker(rootPane).createMessageDialog("(・。・)","安排中......\n为保证运行的稳定,此时还不能进行该操作哦。"); |
||||
return; |
||||
} |
||||
NumberSettingsPaneController numberSettingsPaneController =new NumberSettingsPaneController(nameData); |
||||
numberSettingsPaneController.bindProperties(mainConfig); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("调整数字",numberSettingsPaneController); |
||||
|
||||
} |
||||
|
||||
Logger log= LogManager.getLogger(); |
||||
|
||||
@FXML |
||||
void miniMode(ActionEvent event) { |
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/MiniPane.fxml")); |
||||
Parent parent; |
||||
try { |
||||
parent=loader.load(); |
||||
} catch (IOException e) { |
||||
log.error("Error in loading MiniPane Fxml:"+e); |
||||
return; |
||||
} |
||||
|
||||
Scene miniScene=new Scene(parent,300,134); |
||||
Stage miniStage=new Stage(); |
||||
miniStage.setScene(miniScene); |
||||
miniStage.initStyle(StageStyle.UNDECORATED); |
||||
|
||||
MiniPaneController miniPaneController=loader.getController(); |
||||
miniPaneController.setBase(history,nameData,token,voiceConfig,mainConfig); |
||||
|
||||
Stage currentStage=(Stage)anPaiBtn.getScene().getWindow(); |
||||
miniPaneController.setForwStage(currentStage); |
||||
|
||||
miniPaneController.setCurrentStage(miniStage); |
||||
miniPaneController.setCurrentScene(miniScene); |
||||
|
||||
miniPaneController.setListeners(); |
||||
|
||||
miniStage.show(); |
||||
currentStage.close(); |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void showSettings(ActionEvent event) { |
||||
|
||||
SettingsPaneController settingsPaneController =new SettingsPaneController(); |
||||
|
||||
settingsPaneController.setToggleGroup(); |
||||
settingsPaneController.bindProperties(mainConfig); |
||||
|
||||
settingsPaneController.setVoiceConfig(voiceConfig); |
||||
|
||||
settingsPaneController.setRootPane(rootPane); |
||||
|
||||
settingsPaneController.setNameData(nameData); |
||||
|
||||
new DialogMaker(rootPane).createDialogWithOneBtn("更多设置",settingsPaneController); |
||||
} |
||||
|
||||
@FXML |
||||
void showHistory(ActionEvent event) { |
||||
|
||||
HistoryPaneController historyPaneController =new HistoryPaneController(history,rootPane); |
||||
|
||||
new DialogMaker(rootPane).createDialogWithOneBtn("历史记录",historyPaneController); |
||||
} |
||||
|
||||
Random random=new Random(); |
||||
|
||||
HashSet<String> ignoreNameList; |
||||
HashSet<String> ignoreNumberList; |
||||
|
||||
NameData nameData=new NameData(); |
||||
//boolean isRunning=false;
|
||||
|
||||
Chooser chooser=new Chooser(); |
||||
|
||||
@FXML |
||||
void anPai() { |
||||
|
||||
if(chooser.isRunning()){ |
||||
chooser.setForceStop(true); |
||||
anPaiBtn.setText("安排一下"); |
||||
return; |
||||
} |
||||
|
||||
if(mainConfig.isRandomTimesProperty()) { |
||||
mainConfig.setCycleTimesProperty(100+random.nextInt(151)); |
||||
} |
||||
|
||||
if(mainConfig.isNameChooseProperty()){ |
||||
runNameMode(chooser); |
||||
}else { |
||||
runNumberMode(chooser); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
public void setToggleGroup(){ |
||||
ToggleGroup toggleGroup =new ToggleGroup(); |
||||
nameChoose.setToggleGroup(toggleGroup); |
||||
numbChoose.setToggleGroup(toggleGroup); |
||||
} |
||||
|
||||
private void runNameMode(Chooser chooser){ |
||||
|
||||
if(nameData.isEmpty()){ |
||||
new DialogMaker(rootPane).createMessageDialog("哦霍~","现在名单还是空的捏~请前往名单管理添加名字 或 使用数字挑选法。"); |
||||
return; |
||||
} |
||||
|
||||
if((nameData.getIgnoreNameList().size()>=nameData.getSize())&&mainConfig.isIgnorePastProperty()){ |
||||
|
||||
if(mainConfig.isEqualModeProperty()) { |
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel("啊?", "全部名字都被点完啦!\n要把名字的忽略列表重置吗?", e ->nameData.clearNameIgnoreList()); |
||||
}else { |
||||
new DialogMaker(rootPane).createMessageDialog("啊?", "全部名字都被点完啦!\n请多添加几个名字 或 点击“机会均等”的“重置”按钮。"); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
anPaiBtn.setText("不玩了!"); |
||||
|
||||
chooser.set(chosen_1.textProperty(),chosen_2.textProperty(),anPaiBtn,history,nameData,token,voiceConfig); |
||||
|
||||
chooser.run( |
||||
(short)(100-mainConfig.getSpeedProperty()) , |
||||
mainConfig.getCycleTimesProperty(), |
||||
mainConfig.isIgnorePastProperty(), |
||||
mainConfig.isEqualModeProperty(), |
||||
mainConfig.isVoicePlayProperty() |
||||
); |
||||
|
||||
} |
||||
|
||||
|
||||
private void runNumberMode(Chooser chooser){ |
||||
|
||||
try{ |
||||
|
||||
int minNumber=Integer.parseInt(mainConfig.getMinNumberProperty()); |
||||
int maxNumber=Integer.parseInt(mainConfig.getMaxNumberProperty()); |
||||
|
||||
if(maxNumber-minNumber<=0){ |
||||
new DialogMaker(rootPane).createMessageDialog("嗯哼?","数字要前小后大啊~"); |
||||
return; |
||||
} |
||||
|
||||
if(nameData.getIgnoreNumberList().size()>=(maxNumber-minNumber+1) && mainConfig.isIgnorePastProperty()){ |
||||
if(mainConfig.isEqualModeProperty()) { |
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel("啊?", "全部数字都被点完啦!\n要把数字的忽略列表重置吗?", e ->nameData.clearNumberIgnoreList()); |
||||
}else { |
||||
new DialogMaker(rootPane).createMessageDialog("啊?", "全部数字都被点完啦!\n请扩大数字范围 或 点击“机会均等”的“重置”按钮。"); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
}catch (Exception e){ |
||||
new DialogMaker(rootPane).createMessageDialog("嗯哼?","输入个有效的数字啊~"); |
||||
return; |
||||
} |
||||
|
||||
anPaiBtn.setText("不玩了!"); |
||||
|
||||
chooser.set(chosen_1.textProperty(),chosen_2.textProperty(),anPaiBtn,history,nameData,token,voiceConfig); |
||||
|
||||
chooser.run( |
||||
Short.parseShort(mainConfig.getMaxNumberProperty()), |
||||
Short.parseShort(mainConfig.getMinNumberProperty()), |
||||
(short)(100-mainConfig.getSpeedProperty()) , |
||||
mainConfig.getCycleTimesProperty(), |
||||
mainConfig.isIgnorePastProperty(), |
||||
mainConfig.isEqualModeProperty(), |
||||
mainConfig.isVoicePlayProperty() |
||||
); |
||||
} |
||||
|
||||
public Label getTopBar() { |
||||
return topBar; |
||||
} |
||||
|
||||
public Pane getRootPane() { |
||||
return rootPane; |
||||
} |
||||
|
||||
public MainConfig getMainConfig() { |
||||
return mainConfig; |
||||
} |
||||
} |
@ -0,0 +1,191 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.JFXButton; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.event.EventHandler; |
||||
import javafx.fxml.FXML; |
||||
import javafx.scene.Scene; |
||||
import javafx.scene.control.Label; |
||||
import javafx.scene.input.MouseEvent; |
||||
import javafx.scene.input.TouchEvent; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.stage.Stage; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.choose.Chooser; |
||||
import me.lensferno.dogename.configs.MainConfig; |
||||
import me.lensferno.dogename.configs.VoiceConfig; |
||||
import me.lensferno.dogename.controllers.WindowListeners.MoveWindowByMouse; |
||||
import me.lensferno.dogename.controllers.WindowListeners.MoveWindowByTouch; |
||||
import me.lensferno.dogename.data.History; |
||||
import me.lensferno.dogename.data.NameData; |
||||
import me.lensferno.dogename.voice.Token; |
||||
|
||||
import java.util.Random; |
||||
|
||||
public class MiniPaneController { |
||||
|
||||
@FXML |
||||
private Label chosenNameLabel; |
||||
|
||||
@FXML |
||||
private JFXButton anPaiBtn; |
||||
|
||||
@FXML |
||||
private JFXButton miniModeBtn; |
||||
|
||||
Stage forwStage; |
||||
|
||||
public Stage getForwStage() { |
||||
return forwStage; |
||||
} |
||||
|
||||
public void setForwStage(Stage forwStage) { |
||||
this.forwStage = forwStage; |
||||
} |
||||
|
||||
private Random random=new Random(); |
||||
private NameData nameData; |
||||
private Pane rootPane; |
||||
private History history; |
||||
private Token token; |
||||
private VoiceConfig voiceConfig; |
||||
|
||||
Stage currentStage; |
||||
Scene currentScene; |
||||
|
||||
public void setCurrentScene(Scene currentScene) { |
||||
this.currentScene = currentScene; |
||||
} |
||||
|
||||
public void setCurrentStage(Stage currentStage) { |
||||
this.currentStage = currentStage; |
||||
} |
||||
|
||||
public void setBase(History history, NameData nameData, Token token, VoiceConfig voiceConfig, MainConfig mainConfig){ |
||||
|
||||
this.history = history; |
||||
this.nameData = nameData; |
||||
|
||||
this.token=token; |
||||
|
||||
this.voiceConfig=voiceConfig; |
||||
|
||||
this.mainConfig=mainConfig; |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void recoverMode(ActionEvent event) { |
||||
this.forwStage.show(); |
||||
currentStage.close(); |
||||
} |
||||
|
||||
public void setListeners(){ |
||||
EventHandler<MouseEvent> mouseHandler=new MoveWindowByMouse(currentStage); |
||||
chosenNameLabel.setOnMousePressed(mouseHandler); |
||||
chosenNameLabel.setOnMouseDragged(mouseHandler); |
||||
|
||||
EventHandler<TouchEvent> touchHandler=new MoveWindowByTouch(currentStage); |
||||
chosenNameLabel.setOnTouchPressed(touchHandler); |
||||
chosenNameLabel.setOnTouchMoved(touchHandler); |
||||
|
||||
anPaiBtn.setOnMousePressed(mouseHandler); |
||||
anPaiBtn.setOnMouseDragged(mouseHandler); |
||||
|
||||
anPaiBtn.setOnTouchPressed(touchHandler); |
||||
anPaiBtn.setOnTouchMoved(touchHandler); |
||||
|
||||
miniModeBtn.setOnMousePressed(mouseHandler); |
||||
miniModeBtn.setOnMouseDragged(mouseHandler); |
||||
|
||||
miniModeBtn.setOnTouchPressed(touchHandler); |
||||
miniModeBtn.setOnTouchMoved(touchHandler); |
||||
} |
||||
|
||||
|
||||
|
||||
private MainConfig mainConfig; |
||||
Chooser chooser=new Chooser(); |
||||
|
||||
@FXML |
||||
void anPai() { |
||||
if(chooser.isRunning()){ |
||||
chooser.setForceStop(true); |
||||
anPaiBtn.setText("安排一下"); |
||||
return; |
||||
} |
||||
|
||||
if(mainConfig.isRandomTimesProperty()) { |
||||
mainConfig.setCycleTimesProperty(100+random.nextInt(151)); |
||||
} |
||||
|
||||
if(mainConfig.isNameChooseProperty()){ |
||||
runNameMode(chooser); |
||||
}else { |
||||
runNumberMode(chooser); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
private void runNameMode(Chooser chooser){ |
||||
|
||||
if(nameData.isEmpty()){ |
||||
return; |
||||
} |
||||
|
||||
if((nameData.getIgnoreNameList().size()>=nameData.getSize())&&mainConfig.isIgnorePastProperty()){ |
||||
|
||||
return; |
||||
} |
||||
|
||||
anPaiBtn.setText("不玩了!"); |
||||
|
||||
chooser.set(chosenNameLabel.textProperty(),chosenNameLabel.textProperty(),anPaiBtn,history,nameData,token,voiceConfig); |
||||
|
||||
chooser.run( |
||||
(short)(100-mainConfig.getSpeedProperty()) , |
||||
mainConfig.getCycleTimesProperty(), |
||||
mainConfig.isIgnorePastProperty(), |
||||
mainConfig.isEqualModeProperty(), |
||||
mainConfig.isVoicePlayProperty() |
||||
); |
||||
|
||||
} |
||||
|
||||
|
||||
private void runNumberMode(Chooser chooser){ |
||||
|
||||
try{ |
||||
|
||||
int minNumber=Integer.parseInt(mainConfig.getMinNumberProperty()); |
||||
int maxNumber=Integer.parseInt(mainConfig.getMaxNumberProperty()); |
||||
|
||||
if(maxNumber-minNumber<=0){ |
||||
return; |
||||
} |
||||
|
||||
if(nameData.getIgnoreNumberList().size()>=(maxNumber-minNumber+1) && mainConfig.isIgnorePastProperty()){ |
||||
return; |
||||
} |
||||
|
||||
}catch (Exception e){ |
||||
new DialogMaker(rootPane).createMessageDialog("嗯哼?","倒是输入个有效的数字啊~"); |
||||
return; |
||||
} |
||||
|
||||
anPaiBtn.setText("不玩了!"); |
||||
|
||||
chooser.set(chosenNameLabel.textProperty(),chosenNameLabel.textProperty(),anPaiBtn,history,nameData,token,voiceConfig); |
||||
|
||||
chooser.run( |
||||
Short.parseShort(mainConfig.getMaxNumberProperty()), |
||||
Short.parseShort(mainConfig.getMinNumberProperty()), |
||||
(short)(100-mainConfig.getSpeedProperty()) , |
||||
mainConfig.getCycleTimesProperty(), |
||||
mainConfig.isIgnorePastProperty(), |
||||
mainConfig.isEqualModeProperty(), |
||||
mainConfig.isVoicePlayProperty() |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,191 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.*; |
||||
import javafx.collections.FXCollections; |
||||
import javafx.collections.ObservableList; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.Parent; |
||||
import javafx.scene.Scene; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.scene.layout.VBox; |
||||
import javafx.stage.FileChooser; |
||||
import javafx.stage.Stage; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.data.NameData; |
||||
import me.lensferno.dogename.ocr.Ocr; |
||||
import me.lensferno.dogename.utils.Clipboard; |
||||
|
||||
import java.io.File; |
||||
import java.util.logging.Logger; |
||||
|
||||
public class NameManagerPaneController extends VBox { |
||||
|
||||
NameData nameData; |
||||
Pane rootPane; |
||||
Ocr ocrTool; |
||||
|
||||
Logger log = Logger.getLogger("NameManagerPaneLOgger"); |
||||
|
||||
public static final ObservableList<String> shownNameList = FXCollections.observableArrayList(); |
||||
|
||||
public NameManagerPaneController(NameData nameData, Pane rootPane, Ocr ocrTool){ |
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/NameManagerPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
try { |
||||
loader.load(); |
||||
}catch(Exception e){ |
||||
e.printStackTrace(); |
||||
} |
||||
this.nameData=nameData; |
||||
this.rootPane=rootPane; |
||||
|
||||
shownNameList.setAll(nameData.getNameList()); |
||||
this.nameList.setItems(shownNameList); |
||||
|
||||
this.ocrTool=ocrTool; |
||||
} |
||||
|
||||
@FXML |
||||
private JFXListView<String> nameList; |
||||
|
||||
@FXML |
||||
private JFXButton deleteAll; |
||||
|
||||
@FXML |
||||
private JFXButton addName; |
||||
|
||||
@FXML |
||||
private JFXButton deleteName; |
||||
|
||||
@FXML |
||||
private JFXTextArea inputName; |
||||
|
||||
|
||||
@FXML |
||||
void deleteName(ActionEvent event) { |
||||
|
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel( |
||||
"问一下", |
||||
"真的要这个名字吗?该操作无法撤销,除非您已经备份了名单。", |
||||
e -> { |
||||
String deletedName = nameList.getSelectionModel().getSelectedItems().get(0); |
||||
|
||||
nameData.delete(deletedName); |
||||
shownNameList.remove(deletedName); |
||||
|
||||
nameData.saveToFile(); |
||||
System.gc(); |
||||
}); |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void deleteAllName(ActionEvent event) { |
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel( |
||||
"问一下", |
||||
"真的要删掉所有名字吗?该操作无法撤销,除非您已经备份了名单。", |
||||
e -> { |
||||
//delete all name
|
||||
nameData.deleteAll(); |
||||
shownNameList.setAll(nameData.getNameList()); |
||||
nameData.saveToFile(); |
||||
}); |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void makeMass(ActionEvent event) { |
||||
nameData.makeMass(); |
||||
shownNameList.clear(); |
||||
shownNameList.setAll(nameData.getNameList()); |
||||
nameData.saveToFile(); |
||||
} |
||||
|
||||
@FXML |
||||
void exoprtNameList(ActionEvent event) { |
||||
FileChooser fileChooser = new FileChooser(); |
||||
fileChooser.setInitialFileName("nameList.txt"); |
||||
fileChooser.setTitle("想保存到哪?"); |
||||
File file = fileChooser.showSaveDialog(rootPane.getScene().getWindow()); |
||||
nameData.exportNameList(file); |
||||
System.gc(); |
||||
} |
||||
|
||||
@FXML |
||||
void importNameList(ActionEvent event) { |
||||
|
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel( |
||||
"问一下", |
||||
"导入恢复名单会覆盖当前已有的名单,是否继续?", |
||||
event1 -> { |
||||
FileChooser fileChooser = new FileChooser(); |
||||
fileChooser.setTitle("告诉我在哪?"); |
||||
File file = fileChooser.showOpenDialog(rootPane.getScene().getWindow()); |
||||
|
||||
nameData.importNameList(file); |
||||
shownNameList.clear(); |
||||
shownNameList.setAll(nameData.getNameList()); |
||||
|
||||
nameData.clearNameIgnoreList(); |
||||
nameData.clearNumberIgnoreList(); |
||||
|
||||
nameData.saveToFile(); |
||||
System.gc(); |
||||
}); |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void addName(ActionEvent event) { |
||||
|
||||
if(inputName.getText().equals("")){ |
||||
new DialogMaker(rootPane).createMessageDialog("诶诶诶~","输入框怎么是空的呢?"); |
||||
return; |
||||
} |
||||
|
||||
nameData.add(inputName.getText()); |
||||
|
||||
shownNameList.clear(); |
||||
shownNameList.setAll(nameData.getNameList()); |
||||
|
||||
nameData.saveToFile(); |
||||
inputName.clear(); |
||||
System.gc(); |
||||
} |
||||
|
||||
@FXML |
||||
void addNameFromScreen(ActionEvent event) { |
||||
FXMLLoader fxmlLoader; |
||||
Parent parent; |
||||
|
||||
Stage stage=new Stage(); |
||||
|
||||
try{ |
||||
fxmlLoader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/OcrPane.fxml")); |
||||
parent=fxmlLoader.load(); |
||||
}catch (Exception e){ |
||||
log.warning("Error to load main interface FXML :"+e.toString()); |
||||
return; |
||||
} |
||||
|
||||
Scene scene=new Scene(parent,515,604); |
||||
stage.setTitle("Ocr模块"); |
||||
stage.setScene(scene); |
||||
log.fine("窗口加载完成"); |
||||
|
||||
OcrPaneController ocrPaneController= fxmlLoader.getController(); |
||||
ocrPaneController.setpStage((Stage)inputName.getScene().getWindow()); |
||||
stage.show(); |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void copyTo(ActionEvent event) { |
||||
inputName.setText(inputName.getText()+ Clipboard.getClipboardString()); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,39 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.JFXTextField; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.layout.VBox; |
||||
import me.lensferno.dogename.configs.MainConfig; |
||||
import me.lensferno.dogename.data.NameData; |
||||
|
||||
public class NumberSettingsPaneController extends VBox { |
||||
NameData nameData; |
||||
public NumberSettingsPaneController(NameData nameData){ |
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/NumberSettingPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
try { |
||||
loader.load(); |
||||
}catch(Exception e){ |
||||
e.printStackTrace(); |
||||
} |
||||
this.nameData=nameData; |
||||
} |
||||
|
||||
@FXML |
||||
private JFXTextField minValueField; |
||||
|
||||
@FXML |
||||
private JFXTextField maxValueField; |
||||
|
||||
public void bindProperties(MainConfig mainConfig){ |
||||
|
||||
minValueField.textProperty().bindBidirectional(mainConfig.minNumberPropertyProperty()); |
||||
minValueField.textProperty().addListener((observable, oldValue, newValue) -> nameData.clearNumberIgnoreList() ); |
||||
|
||||
maxValueField.textProperty().bindBidirectional(mainConfig.maxNumberPropertyProperty()); |
||||
maxValueField.textProperty().addListener((observable, oldValue, newValue) -> nameData.clearNumberIgnoreList() ); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,93 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.JFXSpinner; |
||||
import javafx.application.Platform; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.scene.control.TextArea; |
||||
import javafx.scene.text.Text; |
||||
import javafx.stage.Stage; |
||||
import me.lensferno.dogename.ocr.Ocr; |
||||
import me.lensferno.dogename.ocr.ScreenCapture; |
||||
import me.lensferno.dogename.utils.Clipboard; |
||||
|
||||
public class OcrPaneController { |
||||
|
||||
Ocr ocr; |
||||
|
||||
@FXML |
||||
private TextArea ocrText; |
||||
|
||||
@FXML |
||||
private Text statusText; |
||||
|
||||
@FXML |
||||
private JFXSpinner loadingSpinner; |
||||
|
||||
Stage pStage; |
||||
|
||||
public void setpStage(Stage pStage) { |
||||
this.pStage = pStage; |
||||
} |
||||
|
||||
@FXML |
||||
void addNew(ActionEvent event) { |
||||
|
||||
Stage stage=(Stage)ocrText.getScene().getWindow(); |
||||
stage.hide(); |
||||
pStage.hide(); |
||||
|
||||
//等待系统动画结束
|
||||
try { |
||||
Thread.sleep(500); |
||||
} catch (InterruptedException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
boolean captureSuccess= ScreenCapture.getScreenCapture(); |
||||
|
||||
if(!captureSuccess){ |
||||
statusText.setText("状态:截屏失败。"); |
||||
System.out.println("状态:截屏失败。"); |
||||
pStage.show(); |
||||
stage.show(); |
||||
return; |
||||
} |
||||
loadingSpinner.setVisible(true); |
||||
|
||||
if(ocr==null){ |
||||
ocr=new Ocr(); |
||||
ocr.init(); |
||||
} |
||||
|
||||
new Thread(()->{ |
||||
boolean ocrSuccrss=ocr.identifyPrecisely(ScreenCapture.SCREEN_CAPTURE_LOCA); |
||||
|
||||
if (ocrSuccrss) { |
||||
|
||||
Platform.runLater(()->{ |
||||
ocrText.setText(ocrText.getText()+ocr.getResult()); |
||||
statusText.setText("状态:成功。"); |
||||
System.out.println("状态:成功。"); |
||||
loadingSpinner.setVisible(false); |
||||
|
||||
}); |
||||
}else { |
||||
Platform.runLater(()->{ |
||||
ocrText.setText(ocr.getResult()); |
||||
statusText.setText("状态:失败。"); |
||||
System.out.println("状态:失败。"); |
||||
loadingSpinner.setVisible(false); |
||||
|
||||
}); |
||||
} |
||||
}).start(); |
||||
pStage.show(); |
||||
stage.show(); |
||||
} |
||||
|
||||
@FXML |
||||
void copyText(ActionEvent event) { |
||||
Clipboard.copyToClipboard(ocrText.getText()); |
||||
} |
||||
} |
@ -0,0 +1,137 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.JFXButton; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.control.TextArea; |
||||
import javafx.scene.image.Image; |
||||
import javafx.scene.image.ImageView; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.scene.layout.VBox; |
||||
import javafx.scene.text.Font; |
||||
import javafx.scene.text.FontWeight; |
||||
import javafx.scene.text.Text; |
||||
import me.lensferno.dogename.DataReleaser; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.resources.LicenseText; |
||||
|
||||
import java.awt.*; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
|
||||
public class ProgramInfoPaneController extends VBox { |
||||
|
||||
@FXML |
||||
public ImageView dogeView; |
||||
|
||||
Pane rootPane; |
||||
|
||||
public ProgramInfoPaneController(Pane rootPane){ |
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/ProgramInfoPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
try { |
||||
loader.load(); |
||||
}catch(Exception e){ |
||||
e.printStackTrace(); |
||||
} |
||||
Image dogeImage=new Image(DataReleaser.getDogenameStream()); |
||||
dogeView.setImage(dogeImage); |
||||
this.rootPane=rootPane; |
||||
} |
||||
|
||||
|
||||
@FXML |
||||
void showLicense(ActionEvent event) { |
||||
TextArea textArea=new TextArea(LicenseText.text); |
||||
textArea.setFont(Font.font("Microsoft YaHei",14)); |
||||
textArea.setMinWidth(600); |
||||
textArea.setPrefHeight(400); |
||||
textArea.setEditable(false); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("开源协议(LGPL v3)",textArea); |
||||
} |
||||
|
||||
@FXML |
||||
void showLibLicense(ActionEvent event) { |
||||
TextArea textArea=new TextArea(LicenseText.libLicense); |
||||
textArea.setFont(Font.font("Microsoft YaHei",14)); |
||||
textArea.setMinWidth(600); |
||||
textArea.setPrefHeight(400); |
||||
textArea.setEditable(false); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("其他开源许可",textArea); |
||||
} |
||||
|
||||
@FXML |
||||
void showHelp(ActionEvent event) { |
||||
|
||||
JFXButton YesButton = new JFXButton("好的~去吧去吧"); |
||||
YesButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD,14)); |
||||
YesButton.setPrefWidth(160); |
||||
YesButton.setPrefHeight(40); |
||||
YesButton.addEventHandler(ActionEvent.ACTION,e -> jumpToHelp()); |
||||
|
||||
JFXButton cancelButton = new JFXButton("算了算了"); |
||||
cancelButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD,14)); |
||||
cancelButton.setPrefWidth(100); |
||||
cancelButton.setPrefHeight(40); |
||||
|
||||
Text messageText=new Text("即将跳转到本程序Github页面上的使用帮助,是否继续?"); |
||||
messageText.setFont(Font.font("Microsoft YaHei",14)); |
||||
|
||||
new DialogMaker(rootPane).createDialog("查看帮助",messageText,cancelButton,YesButton); |
||||
|
||||
} |
||||
|
||||
private void jumpToHelp(){ |
||||
try { |
||||
Desktop.getDesktop().browse(new URI("https://github.com/lensferno/dogename/blob/main/res/usage.md")); |
||||
} catch (IOException | URISyntaxException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
@FXML |
||||
void viewCode(ActionEvent event) { |
||||
JFXButton githubButton = new JFXButton("前往Github查看"); |
||||
githubButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD,14)); |
||||
githubButton.setPrefWidth(150); |
||||
githubButton.setPrefHeight(40); |
||||
githubButton.addEventHandler(ActionEvent.ACTION,e -> jumpToGithub()); |
||||
|
||||
JFXButton giteeButton = new JFXButton("前往Gitee查看"); |
||||
giteeButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD,14)); |
||||
giteeButton.setPrefWidth(150); |
||||
giteeButton.setPrefHeight(40); |
||||
giteeButton.addEventHandler(ActionEvent.ACTION,e -> jumpToGitee()); |
||||
|
||||
JFXButton cancelButton = new JFXButton("哪都不去"); |
||||
cancelButton.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD,14)); |
||||
cancelButton.setPrefWidth(100); |
||||
cancelButton.setPrefHeight(40); |
||||
|
||||
Text messageText=new Text("Dogename在Github和码云(Gitee)都发布有代码和介绍。\n您想去哪里?\nGithub:将跳转到https://github.com/lensferno/dogename\nGitee:将跳转到https://gitee.com/lensferno/dogename"); |
||||
messageText.setFont(Font.font("Microsoft YaHei",14)); |
||||
|
||||
new DialogMaker(rootPane).createDialog("查看源代码",messageText,cancelButton,githubButton,giteeButton); |
||||
|
||||
} |
||||
|
||||
private void jumpToGithub(){ |
||||
try { |
||||
Desktop.getDesktop().browse(new URI("https://github.com/lensferno/dogename")); |
||||
} catch (IOException | URISyntaxException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private void jumpToGitee(){ |
||||
try { |
||||
Desktop.getDesktop().browse(new URI("https://gitee.com/lensferno/dogename")); |
||||
} catch (IOException | URISyntaxException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,157 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.JFXCheckBox; |
||||
import com.jfoenix.controls.JFXRadioButton; |
||||
import com.jfoenix.controls.JFXSlider; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.control.ToggleGroup; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.scene.layout.VBox; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.configs.MainConfig; |
||||
import me.lensferno.dogename.configs.VoiceConfig; |
||||
import me.lensferno.dogename.data.NameData; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
|
||||
public class SettingsPaneController extends VBox { |
||||
|
||||
@FXML |
||||
private JFXCheckBox showSayingBtn; |
||||
|
||||
@FXML |
||||
private JFXCheckBox newAlgoBtn; |
||||
|
||||
@FXML |
||||
private JFXSlider cycleTimesBar; |
||||
|
||||
@FXML |
||||
private JFXCheckBox voicePlayBtn; |
||||
|
||||
@FXML |
||||
private JFXSlider speedBar; |
||||
|
||||
@FXML |
||||
private JFXCheckBox equalModeBtn; |
||||
|
||||
@FXML |
||||
private JFXRadioButton ignoreOnce; |
||||
|
||||
@FXML |
||||
private JFXRadioButton chooseOnce; |
||||
|
||||
@FXML |
||||
private JFXRadioButton randomTimes; |
||||
|
||||
@FXML |
||||
private JFXRadioButton fixedTimes; |
||||
|
||||
MainConfig mainConfig; |
||||
VoiceConfig voiceConfig; |
||||
|
||||
Pane rootPane; |
||||
|
||||
NameData nameData; |
||||
|
||||
Logger log = LogManager.getLogger("SettingsPaneControllerLogger"); |
||||
|
||||
public SettingsPaneController(){ |
||||
FXMLLoader loader=new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/SettingsPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
try { |
||||
loader.load(); |
||||
}catch(Exception e){ |
||||
log.warn("Error to load settings pane FXML: "+e.toString()); |
||||
} |
||||
} |
||||
|
||||
public void setMainConfig(MainConfig mainConfig) { |
||||
this.mainConfig = mainConfig; |
||||
} |
||||
|
||||
public void setVoiceConfig(VoiceConfig voiceConfig) { |
||||
this.voiceConfig = voiceConfig; |
||||
} |
||||
|
||||
public void setRootPane(Pane rootPane){ |
||||
this.rootPane=rootPane; |
||||
} |
||||
|
||||
public void bindProperties(MainConfig mainConfig){ |
||||
setMainConfig(mainConfig); |
||||
|
||||
ignoreOnce.selectedProperty().bindBidirectional(mainConfig.ignorePastPropertyProperty()); |
||||
chooseOnce.setSelected(!mainConfig.isIgnorePastProperty()); |
||||
|
||||
randomTimes.selectedProperty().bindBidirectional(mainConfig.randomTimesPropertyProperty()); |
||||
fixedTimes.setSelected(!mainConfig.isRandomTimesProperty()); |
||||
|
||||
equalModeBtn.selectedProperty().bindBidirectional(mainConfig.equalModePropertyProperty()); |
||||
|
||||
newAlgoBtn.selectedProperty().bindBidirectional(mainConfig.newAlgoPropertyProperty()); |
||||
|
||||
voicePlayBtn.selectedProperty().bindBidirectional(mainConfig.voicePlayPropertyProperty()); |
||||
|
||||
cycleTimesBar.valueProperty().bindBidirectional(mainConfig.cycleTimesPropertyProperty()); |
||||
|
||||
speedBar.valueProperty().bindBidirectional(mainConfig.speedPropertyProperty()); |
||||
|
||||
showSayingBtn.selectedProperty().bindBidirectional(mainConfig.showSayingProperty()); |
||||
|
||||
mainConfig.ignorePastPropertyProperty().addListener((observable, oldValue, isIgnorePast) -> { |
||||
if(!isIgnorePast) |
||||
{ |
||||
//如果 忽略被点过的名字 被取消后就把机会均等模式的按钮给取消掉
|
||||
equalModeBtn.setSelected(false); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void setToggleGroup(){ |
||||
ToggleGroup pastGroup=new ToggleGroup(); |
||||
chooseOnce.setToggleGroup(pastGroup); |
||||
ignoreOnce.setToggleGroup(pastGroup); |
||||
|
||||
ToggleGroup fixedTimesGroup=new ToggleGroup(); |
||||
randomTimes.setToggleGroup(fixedTimesGroup); |
||||
fixedTimes.setToggleGroup(fixedTimesGroup); |
||||
} |
||||
|
||||
@FXML |
||||
void showVoiceSettingsPane(ActionEvent event) { |
||||
VoiceSettingsPaneController voiceSettingsPaneController=new VoiceSettingsPaneController(); |
||||
voiceSettingsPaneController.bindPropertied(voiceConfig); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("语音设置",voiceSettingsPaneController); |
||||
} |
||||
|
||||
@FXML |
||||
void showEqualMode(ActionEvent event) { |
||||
new DialogMaker(rootPane).createMessageDialog("什么?", |
||||
"//有待补充。;-)"); |
||||
|
||||
} |
||||
|
||||
@FXML |
||||
void clearIgnoreList(ActionEvent event) { |
||||
new DialogMaker(rootPane).createDialogWithOKAndCancel("真的吗?","真的要重置吗?",(e)->{ |
||||
nameData.clearNumberIgnoreList(); |
||||
nameData.clearNameIgnoreList(); |
||||
}); |
||||
} |
||||
|
||||
@FXML |
||||
void equalBtnAction(ActionEvent event) { |
||||
if(!mainConfig.isIgnorePastProperty()){ |
||||
equalModeBtn.setSelected(false); |
||||
new DialogMaker(rootPane).createMessageDialog("且慢","无法在“概率均分”的模式下使用,如需使用请在“人人有份”模式下启用。"); |
||||
} |
||||
} |
||||
|
||||
public void setNameData(NameData nameData) { |
||||
this.nameData = nameData; |
||||
} |
||||
} |
@ -0,0 +1,85 @@ |
||||
package me.lensferno.dogename.controllers; |
||||
|
||||
import com.jfoenix.controls.JFXComboBox; |
||||
import com.jfoenix.controls.JFXSlider; |
||||
import javafx.collections.FXCollections; |
||||
import javafx.collections.ObservableList; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.fxml.FXML; |
||||
import javafx.fxml.FXMLLoader; |
||||
import javafx.scene.layout.VBox; |
||||
import me.lensferno.dogename.configs.VoiceConfig; |
||||
|
||||
import java.util.logging.Logger; |
||||
|
||||
public class VoiceSettingsPaneController extends VBox { |
||||
Logger log = Logger.getLogger("VoiceSettingsPaneControllerLogger"); |
||||
|
||||
VoiceConfig voiceConfig=new VoiceConfig(); |
||||
|
||||
|
||||
@FXML |
||||
private JFXSlider intonationBar; |
||||
|
||||
@FXML |
||||
private JFXComboBox<String> speakerSelectBar; |
||||
|
||||
@FXML |
||||
private JFXSlider voiceSpeedBar; |
||||
|
||||
public static final ObservableList<String> shownSpeakerList = FXCollections.observableArrayList(); |
||||
|
||||
private final String[] speakers={ |
||||
"1","0","3","4", |
||||
"106","110","111","103","5"}; |
||||
//度小宇=1,度小美=0,度逍遥=3,度丫丫=4
|
||||
//度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5
|
||||
|
||||
public VoiceSettingsPaneController() { |
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/me/lensferno/dogename/FXMLs/VoiceSettingsPane.fxml")); |
||||
loader.setRoot(this); |
||||
loader.setController(this); |
||||
try { |
||||
loader.load(); |
||||
} catch (Exception e) { |
||||
log.warning("Error to load settings pane FXML: " + e.toString()); |
||||
} |
||||
if(shownSpeakerList.isEmpty()) { |
||||
shownSpeakerList.addAll( |
||||
"度小宇=1", "度小美=0", "度逍遥=3", "度丫丫=4", |
||||
"度博文=106", "度小童=110", "度小萌=111", "度米朵=103", "度小娇=5"); |
||||
} |
||||
|
||||
speakerSelectBar.setItems(shownSpeakerList); |
||||
} |
||||
|
||||
public void bindPropertied(VoiceConfig voiceConfig){ |
||||
|
||||
this.voiceConfig=voiceConfig; |
||||
|
||||
//speakerSelectBar.
|
||||
|
||||
speakerSelectBar.selectionModelProperty().addListener((observable, oldValue, newValue) -> { |
||||
System.out.println("what?"+newValue.getSelectedIndex()); |
||||
this.voiceConfig.setSpeaker(speakers[newValue.getSelectedIndex()]); |
||||
this.voiceConfig.setSelectedSpeaker(newValue.getSelectedIndex()); |
||||
}); |
||||
|
||||
//speakerSelectBar.setValue(this.voiceConfig.getSpeaker());
|
||||
|
||||
voiceSpeedBar.valueProperty().bindBidirectional(voiceConfig.speedProperty()); |
||||
intonationBar.valueProperty().bindBidirectional(voiceConfig.intonationProperty()); |
||||
|
||||
speakerSelectBar.getSelectionModel().select(this.voiceConfig.getSelectedSpeaker()); |
||||
} |
||||
|
||||
@FXML |
||||
void showAdvancedVoiceSettings(ActionEvent event) { |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
} |
||||
|
||||
|
@ -0,0 +1,33 @@ |
||||
package me.lensferno.dogename.controllers.WindowListeners; |
||||
|
||||
import javafx.event.EventHandler; |
||||
import javafx.scene.input.MouseEvent; |
||||
import javafx.stage.Stage; |
||||
|
||||
public class MoveWindowByMouse implements EventHandler<MouseEvent> { |
||||
|
||||
private Stage primaryStage; |
||||
private double oldStageX; |
||||
private double oldStageY; |
||||
private double oldScreenX; |
||||
private double oldScreenY; |
||||
|
||||
public MoveWindowByMouse(Stage stage) { |
||||
this.primaryStage = stage; |
||||
} |
||||
|
||||
@Override |
||||
public void handle(MouseEvent e) { |
||||
if (e.getEventType() == MouseEvent.MOUSE_PRESSED) { |
||||
this.oldStageX = this.primaryStage.getX(); |
||||
this.oldStageY = this.primaryStage.getY(); |
||||
this.oldScreenX = e.getScreenX(); |
||||
this.oldScreenY = e.getScreenY(); |
||||
|
||||
} else if (e.getEventType() == MouseEvent.MOUSE_DRAGGED) { |
||||
this.primaryStage.setX(e.getScreenX() - this.oldScreenX + this.oldStageX); |
||||
this.primaryStage.setY(e.getScreenY() - this.oldScreenY + this.oldStageY); |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,34 @@ |
||||
package me.lensferno.dogename.controllers.WindowListeners; |
||||
|
||||
import javafx.event.EventHandler; |
||||
import javafx.scene.input.TouchEvent; |
||||
import javafx.stage.Stage; |
||||
|
||||
public class MoveWindowByTouch implements EventHandler<TouchEvent> { |
||||
|
||||
private Stage primaryStage; |
||||
private double oldStageX; |
||||
private double oldStageY; |
||||
private double oldScreenX; |
||||
private double oldScreenY; |
||||
|
||||
public MoveWindowByTouch(Stage stage) { |
||||
this.primaryStage = stage; |
||||
} |
||||
|
||||
@Override |
||||
public void handle(TouchEvent e) { |
||||
if (e.getEventType() == TouchEvent.TOUCH_PRESSED) { |
||||
this.oldStageX = this.primaryStage.getX(); |
||||
this.oldStageY = this.primaryStage.getY(); |
||||
this.oldScreenX = e.getTouchPoint().getScreenX(); |
||||
this.oldScreenY = e.getTouchPoint().getScreenY(); |
||||
|
||||
} else if (e.getEventType() == TouchEvent.TOUCH_MOVED) { |
||||
this.primaryStage.setX(e.getTouchPoint().getScreenX() - this.oldScreenX + this.oldStageX); |
||||
this.primaryStage.setY(e.getTouchPoint().getScreenY() - this.oldScreenY + this.oldStageY); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,92 @@ |
||||
package me.lensferno.dogename.data; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.*; |
||||
import java.util.ArrayList; |
||||
|
||||
public class History { |
||||
|
||||
Logger log = LogManager.getLogger(); |
||||
|
||||
|
||||
private String HISTORY_FILE; |
||||
public static final String separator=File.separator; |
||||
|
||||
ArrayList<String> history; |
||||
|
||||
public void loadHistory(){ |
||||
|
||||
HISTORY_FILE="files"+separator+"history.data"; |
||||
|
||||
try { |
||||
File historyFile = new File(HISTORY_FILE); |
||||
if (!historyFile.exists()) { |
||||
historyFile.getParentFile().mkdirs(); |
||||
historyFile.createNewFile(); |
||||
|
||||
history = new ArrayList<>(); |
||||
writeHistory(); |
||||
return; |
||||
} |
||||
|
||||
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(historyFile)); |
||||
history = (ArrayList<String>) ois.readObject(); |
||||
|
||||
} catch (EOFException e){ |
||||
history =new ArrayList<>(); |
||||
log.warn("History file is empty."); |
||||
writeHistory(); |
||||
}catch (Exception e) { |
||||
history = new ArrayList<>(); |
||||
log.error("Failed to load history file:"+e.toString()); |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public ArrayList<String> getHistoryList(){ |
||||
return history; |
||||
} |
||||
|
||||
public void addHistory(String name){ |
||||
if(history.size()>2000) { |
||||
history.clear(); |
||||
} |
||||
history.add((history.size() + 1) +". "+name); |
||||
|
||||
writeHistory(); |
||||
} |
||||
|
||||
private void writeHistory(){ |
||||
|
||||
HISTORY_FILE="files"+separator+"history.data"; |
||||
File historyFile=new File(HISTORY_FILE); |
||||
|
||||
try{ |
||||
|
||||
if (!historyFile.exists()) { |
||||
historyFile.createNewFile(); |
||||
} |
||||
|
||||
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream(historyFile)); |
||||
oos.writeObject(history); |
||||
oos.close(); |
||||
}catch (Exception e){ |
||||
log.error("Error in writing history file:"+e); |
||||
} |
||||
} |
||||
|
||||
public int downSearch(){ |
||||
return 1; |
||||
} |
||||
|
||||
public int upSearch(){ |
||||
return 1; |
||||
} |
||||
|
||||
public void clearHistory(){ |
||||
this.history.clear(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,351 @@ |
||||
package me.lensferno.dogename.data; |
||||
|
||||
import com.google.gson.Gson; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.*; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.security.SecureRandom; |
||||
import java.util.*; |
||||
|
||||
public class NameData { |
||||
|
||||
Logger log = LogManager.getLogger("NameDataLogger"); |
||||
|
||||
private List<String> nameList; |
||||
|
||||
private List<String> chooseList; |
||||
private int listSize = 0; |
||||
|
||||
|
||||
HashSet<String> ignoreNameList=new HashSet<>(); |
||||
|
||||
HashSet<String> ignoreNumberList=new HashSet<>(); |
||||
|
||||
File dataFile ;//=new File("namelist.data");
|
||||
|
||||
boolean newAlgo=true; |
||||
SecureRandom secRandom =new SecureRandom(); |
||||
|
||||
//不做注释了,自己慢慢看。:)
|
||||
|
||||
File nameIgnoreFile =new File("files"+File.separator+"IgnoredNameList.data"); |
||||
File numbIgnoreFile =new File("files"+File.separator+"IgnoredNumberList.data"); |
||||
|
||||
public void writeIgnoreList(String switchy){ |
||||
|
||||
if(!switchy.equals("not name")) { |
||||
try { |
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(nameIgnoreFile)); |
||||
oos.writeObject(ignoreNameList); |
||||
oos.close(); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
if(!switchy.equals("not number")) { |
||||
try { |
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(numbIgnoreFile)); |
||||
oos.writeObject(ignoreNumberList); |
||||
oos.close(); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
public void readIgnoreList(){ |
||||
|
||||
try{ |
||||
|
||||
if(!nameIgnoreFile.exists()){ |
||||
nameIgnoreFile.getParentFile().mkdirs(); |
||||
nameIgnoreFile.createNewFile(); |
||||
ignoreNameList= new HashSet<>(); |
||||
writeIgnoreList("not number"); |
||||
return; |
||||
} |
||||
|
||||
ObjectInputStream ois =new ObjectInputStream(new FileInputStream(nameIgnoreFile)); |
||||
this.ignoreNameList=(HashSet)ois.readObject(); |
||||
|
||||
}catch (EOFException e){ |
||||
ignoreNameList=new HashSet<>(); |
||||
log.warn("Past name list is empty."); |
||||
writeIgnoreList("not number"); |
||||
}catch (Exception e){ |
||||
ignoreNameList=new HashSet<>(); |
||||
writeIgnoreList("not number"); |
||||
log.warn("Failed to load past name list:"+e.toString()); |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
try{ |
||||
|
||||
if(!numbIgnoreFile.exists()){ |
||||
numbIgnoreFile.getParentFile().mkdirs(); |
||||
numbIgnoreFile.createNewFile(); |
||||
ignoreNumberList= new HashSet<>(); |
||||
writeIgnoreList("not name"); |
||||
return; |
||||
} |
||||
|
||||
ObjectInputStream ois =new ObjectInputStream(new FileInputStream(numbIgnoreFile)); |
||||
this.ignoreNumberList=(HashSet)ois.readObject(); |
||||
|
||||
}catch (EOFException e){ |
||||
ignoreNumberList=new HashSet<>(); |
||||
log.warn("Ignored number list is empty."); |
||||
writeIgnoreList("not name"); |
||||
}catch (Exception e){ |
||||
ignoreNumberList=new HashSet<>(); |
||||
log.warn("Failed to load ignored number list"); |
||||
writeIgnoreList("not name"); |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
log.info("There are "+ignoreNameList.size()+" names and "+ignoreNumberList.size()+" numbers ignored."); |
||||
} |
||||
|
||||
|
||||
public void clearNameIgnoreList(){ |
||||
ignoreNameList.clear(); |
||||
writeIgnoreList("not number"); |
||||
} |
||||
|
||||
public void clearNumberIgnoreList(){ |
||||
ignoreNumberList.clear(); |
||||
writeIgnoreList("not name"); |
||||
} |
||||
|
||||
|
||||
public HashSet<String> getIgnoreNameList() { |
||||
return ignoreNameList; |
||||
} |
||||
|
||||
public void setIgnoreNameList(HashSet<String> ignoreNameList) { |
||||
this.ignoreNameList = ignoreNameList; |
||||
} |
||||
|
||||
public HashSet<String> getIgnoreNumberList() { |
||||
return ignoreNumberList; |
||||
} |
||||
|
||||
public void setIgnoreNumberList(HashSet<String> ignoreNumberList) { |
||||
this.ignoreNumberList = ignoreNumberList; |
||||
} |
||||
|
||||
|
||||
public List<String> getNameList() { |
||||
return nameList; |
||||
} |
||||
|
||||
public void exportNameList(File path) { |
||||
if(path!=null) { |
||||
try{ |
||||
FileOutputStream oos =new FileOutputStream(path); |
||||
oos.write(new Gson().toJson(nameList).getBytes(StandardCharsets.UTF_8)); |
||||
oos.close(); |
||||
log.info("Exported list to:"+path.getPath()); |
||||
}catch (Exception e){log.warn("error in export namelist: "+e.toString());e.printStackTrace();} |
||||
|
||||
} |
||||
} |
||||
|
||||
public void importNameList(File path) { |
||||
if(path!=null) { |
||||
|
||||
try{ |
||||
FileInputStream fis =new FileInputStream(path); |
||||
String temp; |
||||
BufferedReader bis=new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8)); |
||||
StringBuilder sb=new StringBuilder(); |
||||
|
||||
while ((temp = bis.readLine()) != null) { |
||||
sb.append(temp); |
||||
sb.append("\n"); |
||||
} |
||||
|
||||
nameList=new Gson().fromJson(sb.toString(),List.class); |
||||
log.info("Imported list from:"+path.getPath()); |
||||
}catch (Exception e){log.warn("error in import namelist:"+e.toString());e.printStackTrace();} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
public void makeMass() { |
||||
|
||||
HashSet<Integer> alreadyList = new HashSet<>(); |
||||
List<String> tempList = new LinkedList<>(); |
||||
int i; |
||||
Random random = new Random(); |
||||
while (tempList.size() < nameList.size()) { |
||||
i = random.nextInt(nameList.size()); |
||||
while (alreadyList.contains(i)) |
||||
i = random.nextInt(nameList.size()); |
||||
tempList.add(nameList.get(i)); |
||||
alreadyList.add(i); |
||||
} |
||||
nameList.clear(); |
||||
nameList.addAll(tempList); |
||||
|
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public void setNewAlgo(boolean newAlgo) { |
||||
this.newAlgo=newAlgo; |
||||
if(newAlgo) |
||||
System.out.println("[INFO]Use SecureRandom"); |
||||
else |
||||
System.out.println("[INFO]Not use SecureRandom"); |
||||
} |
||||
//------------------------------------------------------
|
||||
|
||||
public NameData(){ |
||||
|
||||
if(System.getProperty("os.name").toLowerCase().contains("window")) |
||||
dataFile=new File("files\\Namelist.data"); |
||||
else |
||||
dataFile=new File("files/Namelist.data"); |
||||
|
||||
File oldDataFile=new File("D:\\dogename\\files\\data"); |
||||
|
||||
try{ |
||||
|
||||
if(oldDataFile.exists()) { |
||||
ObjectInputStream ois =new ObjectInputStream(new FileInputStream(oldDataFile)); |
||||
this.nameList=(ArrayList)ois.readObject(); |
||||
|
||||
listSize=nameList.size(); |
||||
this.chooseList=new ArrayList<>(nameList); |
||||
ois.close(); |
||||
oldDataFile.delete(); |
||||
saveToFile(); |
||||
return; |
||||
} |
||||
|
||||
if(!dataFile.exists()){ |
||||
dataFile.getParentFile().mkdirs(); |
||||
dataFile.createNewFile(); |
||||
nameList= new ArrayList<>(); |
||||
saveToFile(); |
||||
return; |
||||
} |
||||
|
||||
ObjectInputStream ois =new ObjectInputStream(new FileInputStream(dataFile)); |
||||
this.nameList=(ArrayList)ois.readObject(); |
||||
|
||||
log.info(nameList.size()+" names loaded."); |
||||
|
||||
listSize=nameList.size(); |
||||
this.chooseList=new ArrayList<>(nameList); |
||||
|
||||
}catch (EOFException EOFe){ |
||||
nameList=new ArrayList<>(); |
||||
chooseList=new ArrayList<>(); |
||||
log.warn("Data file is empty."); |
||||
saveToFile(); |
||||
}catch (Exception e){ |
||||
nameList=new ArrayList<>(); |
||||
chooseList=new ArrayList<>(); |
||||
saveToFile(); |
||||
log.warn("Failed to load data file."); |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public void add(String text){ |
||||
String[] splitedText; |
||||
|
||||
if(text.contains("\n")&&text.contains("\r")){//-----------windows
|
||||
splitedText=text.split("\r\n"); |
||||
nameList.addAll(Arrays.asList(splitedText)); |
||||
}else if(text.contains("\n")){//--------------------------linux,unix
|
||||
splitedText=text.split("\n"); |
||||
nameList.addAll(Arrays.asList(splitedText)); |
||||
}else if(text.contains("\r")){//--------------------------macos
|
||||
splitedText=text.split("\r"); |
||||
nameList.addAll(Arrays.asList(splitedText)); |
||||
}else { |
||||
nameList.add(text); |
||||
listSize=nameList.size(); |
||||
} |
||||
chooseList=new ArrayList<>(nameList); |
||||
System.gc(); |
||||
} |
||||
//------------------------------------------------------
|
||||
public String get(int i){ |
||||
if(i<listSize-1) |
||||
return null; |
||||
else |
||||
return nameList.get(i); |
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public int getSize(){ |
||||
return nameList.size(); |
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public void delete(String name){ |
||||
if(nameList.isEmpty()) |
||||
return; |
||||
|
||||
nameList.remove(name); |
||||
ignoreNameList.remove(name); |
||||
|
||||
chooseList=new ArrayList<>(nameList); |
||||
listSize=nameList.size(); |
||||
System.gc(); |
||||
|
||||
|
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public boolean isEmpty(){ |
||||
return nameList.isEmpty(); |
||||
} |
||||
|
||||
Random random =new Random(); |
||||
|
||||
//------------------------------------------------------
|
||||
public String randomGet(){ |
||||
if(newAlgo) |
||||
return nameList.get(secRandom.nextInt(nameList.size())); |
||||
else |
||||
return nameList.get(random.nextInt(nameList.size())); |
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public String[] getAll(){ |
||||
return nameList.toArray(new String[0]); |
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public void saveToFile(){ |
||||
|
||||
try{ |
||||
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream(dataFile)); |
||||
oos.writeObject(nameList); |
||||
oos.close(); |
||||
}catch (Exception e){ |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
public void deleteAll(){ |
||||
nameList.clear(); |
||||
chooseList.clear(); |
||||
} |
||||
|
||||
//------------------------------------------------------
|
||||
} |
@ -0,0 +1,101 @@ |
||||
package me.lensferno.dogename.ocr; |
||||
|
||||
import com.baidu.aip.ocr.AipOcr; |
||||
import org.json.JSONArray; |
||||
import org.json.JSONObject; |
||||
|
||||
import java.io.File; |
||||
import java.util.HashMap; |
||||
|
||||
public class Ocr { |
||||
|
||||
public static final String APP_ID = "17411446"; |
||||
public static final String API_KEY = "R2ggZhk6nB7ORE4Ozy9iAPdc"; |
||||
public static final String SECRET_KEY = "9f6ECgrltz9v1rww2hQm3EQOl1FFHLGx"; |
||||
|
||||
AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY); |
||||
|
||||
public void init(){ |
||||
client.setConnectionTimeoutInMillis(2000); |
||||
client.setSocketTimeoutInMillis(60000); |
||||
} |
||||
|
||||
String result; |
||||
int resultNum=0; |
||||
|
||||
public boolean identifyPrecisely(String imgFileLoca){ |
||||
HashMap<String,String> params=new HashMap<>(); |
||||
params.put("probability","false"); |
||||
JSONObject respondJSON=client.accurateGeneral("files"+ File.separator+"ocrCache.png",params); |
||||
|
||||
if (respondJSON==null){ |
||||
result="错误:返回了空的数据。"; |
||||
return false; |
||||
} |
||||
if(!respondJSON.has("words_result")){ |
||||
String errorCode=respondJSON.getString("error_code"); |
||||
result=findErrorMsg(errorCode); |
||||
return false; |
||||
} |
||||
|
||||
resultNum=respondJSON.getInt("words_result_num"); |
||||
System.out.println("total result:"+resultNum); |
||||
JSONArray resultArray=respondJSON.getJSONArray("words_result"); |
||||
|
||||
StringBuffer stringBuffer=new StringBuffer(); |
||||
|
||||
for(int i=0;i<resultArray.length();i++){ |
||||
stringBuffer.append(resultArray.getJSONObject(i).getString("words")).append("\n"); |
||||
} |
||||
result=stringBuffer.toString(); |
||||
|
||||
return true; |
||||
|
||||
} |
||||
|
||||
public String getResult() { |
||||
return result; |
||||
} |
||||
|
||||
public int getResultNum() { |
||||
return resultNum; |
||||
} |
||||
|
||||
private String findErrorMsg(String errorCode){ |
||||
switch (errorCode){ |
||||
case "1": |
||||
return "服务器内部错误,请尝试再次请求。"; |
||||
case "3": |
||||
return "调用的API不存在。"; |
||||
case "4": |
||||
return "集群超限额,请尝试再次请求。"; |
||||
case "17": |
||||
return "每天请求量超限额。"; |
||||
case "SDK100": |
||||
return "错误:图像文件过大。"; |
||||
case "SDK101": |
||||
return "错误:图片边长不符合要求。"; |
||||
case "SDK102": |
||||
return "错误:读取图片文件错误。"; |
||||
case "SDK106": |
||||
return "错误:UID格式错误。"; |
||||
case "SDK107": |
||||
return "错误:UID大小错误。"; |
||||
case "SDK108": |
||||
return "错误:连接超时或读取数据超时,请检查网络连接。"; |
||||
case "SDK109": |
||||
return "错误:图片格式不支持。"; |
||||
case "SDK110": |
||||
return "错误:无效的请求ID。"; |
||||
case "SDK111": |
||||
return "错误:等待异步请求结果超时。"; |
||||
case "SDK112": |
||||
return "错误:数据下载失败。"; |
||||
case "282000": |
||||
return "服务器内部错误,如果您使用的是\n高精度接口,原因可能是您上传的图片\n中文字过多,识别超时导致的\n建议您对图片进行切割后再识别,\n其他情况请再次请求。"; |
||||
default: |
||||
return "未知错误。错误码:"+errorCode; |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,205 @@ |
||||
package me.lensferno.dogename.ocr; |
||||
|
||||
import java.io.*; |
||||
import javax.swing.*; |
||||
import java.awt.*; |
||||
import java.awt.event.*; |
||||
import java.awt.image.*; |
||||
import javax.imageio.*; |
||||
|
||||
//edited code from https://blog.csdn.net/caoyuan10036/article/details/7199505
|
||||
|
||||
public class ScreenCapture { |
||||
// test main
|
||||
/* |
||||
public static void main(String[] args) { |
||||
File tempFile = new File( "files"+File.separator+"ocr.png"); |
||||
ScreenCapture capture = ScreenCapture.getInstance(); |
||||
capture.captureImage(); |
||||
JLabel imagebox = new JLabel(); |
||||
imagebox.setIcon(capture.getPickedIcon()); |
||||
try { |
||||
capture.saveToFile(tempFile); |
||||
System.out.println("Over"); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} |
||||
*/ |
||||
|
||||
public static final String SCREEN_CAPTURE_LOCA="files"+File.separator+"ocrCache.png"; |
||||
|
||||
private static boolean canceled =false; |
||||
|
||||
|
||||
public static boolean getScreenCapture(){ |
||||
|
||||
try { |
||||
canceled=false; |
||||
File tempFile = new File(SCREEN_CAPTURE_LOCA); |
||||
ScreenCapture capture = ScreenCapture.getInstance(); |
||||
capture.captureImage(); |
||||
if(canceled){ |
||||
return false; |
||||
} |
||||
JLabel imagebox = new JLabel(); |
||||
imagebox.setIcon(capture.getPickedIcon()); |
||||
capture.saveToFile(tempFile); |
||||
System.out.println("Over"); |
||||
|
||||
return true; |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private ScreenCapture() { |
||||
|
||||
try { |
||||
robot = new Robot(); |
||||
} catch (AWTException e) { |
||||
System.err.println("Internal Error: " + e); |
||||
e.printStackTrace(); |
||||
} |
||||
JPanel cp = (JPanel) dialog.getContentPane(); |
||||
cp.setLayout(new BorderLayout()); |
||||
labFullScreenImage.addMouseListener(new MouseAdapter() { |
||||
public void mouseReleased(MouseEvent evn) { |
||||
if (evn.getButton()==MouseEvent.BUTTON3){ |
||||
canceled=true; |
||||
System.out.println("captureCancel"); |
||||
|
||||
dialog.setVisible(false); |
||||
return; |
||||
} |
||||
isFirstPoint = true; |
||||
pickedImage = fullScreenImage.getSubimage(recX, recY, recW, |
||||
recH); |
||||
dialog.setVisible(false); |
||||
|
||||
} |
||||
}); |
||||
|
||||
|
||||
labFullScreenImage.addMouseMotionListener(new MouseMotionAdapter() { |
||||
public void mouseDragged(MouseEvent evn) { |
||||
if (isFirstPoint) { |
||||
x1 = evn.getX(); |
||||
y1 = evn.getY(); |
||||
isFirstPoint = false; |
||||
} else { |
||||
x2 = evn.getX(); |
||||
y2 = evn.getY(); |
||||
int maxX = Math.max(x1, x2); |
||||
int maxY = Math.max(y1, y2); |
||||
int minX = Math.min(x1, x2); |
||||
int minY = Math.min(y1, y2); |
||||
recX = minX; |
||||
recY = minY; |
||||
recW = maxX - minX; |
||||
recH = maxY - minY; |
||||
labFullScreenImage.drawRectangle(recX, recY, recW, recH); |
||||
} |
||||
} |
||||
|
||||
public void mouseMoved(MouseEvent e) { |
||||
labFullScreenImage.drawCross(e.getX(), e.getY()); |
||||
//messageLabel.setLocation(e.getX(), e.getY());
|
||||
} |
||||
}); |
||||
|
||||
cp.add(BorderLayout.CENTER, labFullScreenImage); |
||||
//cp.add(messageLabel);
|
||||
dialog.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); |
||||
dialog.setAlwaysOnTop(true); |
||||
dialog.setMaximumSize(Toolkit.getDefaultToolkit().getScreenSize()); |
||||
dialog.setUndecorated(true); |
||||
dialog.setSize(dialog.getMaximumSize()); |
||||
dialog.setModal(true); |
||||
} |
||||
|
||||
// Singleton Pattern
|
||||
public static ScreenCapture getInstance() { |
||||
return defaultCapturer; |
||||
} |
||||
|
||||
/** 捕捉屏幕的一个矫形区域 */ |
||||
public void captureImage() { |
||||
fullScreenImage = robot.createScreenCapture(new Rectangle(Toolkit |
||||
.getDefaultToolkit().getScreenSize())); |
||||
ImageIcon icon = new ImageIcon(fullScreenImage); |
||||
labFullScreenImage.setIcon(icon); |
||||
dialog.setVisible(true); |
||||
} |
||||
|
||||
/** 得到捕捉后的BufferedImage */ |
||||
public BufferedImage getPickedImage() { |
||||
return pickedImage; |
||||
} |
||||
|
||||
/** 得到捕捉后的Icon */ |
||||
public ImageIcon getPickedIcon() { |
||||
return new ImageIcon(getPickedImage()); |
||||
} |
||||
|
||||
/** |
||||
* 储存为一个文件,为PNG格式 |
||||
* |
||||
* @deprecated replaced by saveAsPNG(File file) |
||||
**/ |
||||
@Deprecated |
||||
public void saveToFile(File file) throws IOException { |
||||
ImageIO.write(getPickedImage(), defaultImageFormater, file); |
||||
} |
||||
|
||||
|
||||
/** 写入一个OutputStream */ |
||||
public void write(OutputStream out) throws IOException { |
||||
ImageIO.write(getPickedImage(), defaultImageFormater, out); |
||||
} |
||||
|
||||
// singleton design pattern
|
||||
private static ScreenCapture defaultCapturer = new ScreenCapture(); |
||||
private int x1, y1, x2, y2; |
||||
private int recX, recY, recH, recW; // 截取的图像
|
||||
private boolean isFirstPoint = true; |
||||
private BackgroundImage labFullScreenImage = new BackgroundImage(); |
||||
//private Label messageLabel = new Label("按任意键可退出。");
|
||||
private Robot robot; |
||||
private BufferedImage fullScreenImage; |
||||
private BufferedImage pickedImage; |
||||
private String defaultImageFormater = "png"; |
||||
private JDialog dialog = new JDialog(); |
||||
} |
||||
|
||||
/** 显示图片的Label */ |
||||
class BackgroundImage extends JLabel { |
||||
public void paintComponent(Graphics g) { |
||||
super.paintComponent(g); |
||||
g.drawRect(x, y, w, h); |
||||
String area = w + " * " + h; |
||||
g.drawString(area, x + w / 2 - 15, y + h / 2); |
||||
g.drawLine(lineX, 0, lineX, getHeight()); |
||||
|
||||
g.drawLine(0, lineY, getWidth(), lineY); |
||||
} |
||||
|
||||
public void drawRectangle(int x, int y, int width, int height) { |
||||
this.x = x; |
||||
this.y = y; |
||||
h = height; |
||||
w = width; |
||||
repaint(); |
||||
} |
||||
|
||||
public void drawCross(int x, int y) { |
||||
lineX = x; |
||||
lineY = y; |
||||
repaint(); |
||||
} |
||||
|
||||
int lineX, lineY; |
||||
int x, y, h, w; |
||||
} |
@ -0,0 +1,27 @@ |
||||
|
||||
This program uses the following libraries in accordance with the Apache License 2.0, |
||||
You can get the full text of Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
-------------------------------------------------- |
||||
JFoenix (8.0.4) |
||||
-------------------------------------------------- |
||||
Copyright © JFoenix 2015-2017 |
||||
https://github.com/jfoenixadmin/JFoenix |
||||
|
||||
-------------------------------------------------- |
||||
Apache Commons Codec (1.11) |
||||
-------------------------------------------------- |
||||
Copyright © 2002-2020 The Apache Software Foundation |
||||
http://commons.apache.org/proper/commons-codec/ |
||||
|
||||
-------------------------------------------------- |
||||
Gson (2.8.5) |
||||
-------------------------------------------------- |
||||
Copyright 2008 Google Inc. |
||||
https://github.com/google/gson |
||||
|
||||
-------------------------------------------------- |
||||
OkHttp3 (4.2.2) |
||||
-------------------------------------------------- |
||||
Copyright 2019 Square, Inc. |
||||
https://github.com/square/okhttp |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,86 @@ |
||||
package me.lensferno.dogename.sayings; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import javafx.application.Platform; |
||||
import javafx.scene.control.Label; |
||||
import javafx.scene.layout.Pane; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.controllers.GushiciPaneController; |
||||
import me.lensferno.dogename.utils.HtmlRequseter; |
||||
|
||||
public class Gushici { |
||||
|
||||
private final String GUSHICI_API="https://v1.jinrishici.com/all.json"; |
||||
|
||||
String gushiciJSON = null; |
||||
|
||||
private String getGushici() { |
||||
return HtmlRequseter.getHtml(GUSHICI_API,false); |
||||
} |
||||
|
||||
public void showGushici(Pane rootPane, Label topBar){ |
||||
|
||||
new Thread(()->{ |
||||
|
||||
//gushiciJSON=getGushici();
|
||||
|
||||
String content, title, author, type; |
||||
|
||||
if((gushiciJSON=getGushici())!=null){ |
||||
GushiciData gushiciData=new Gson().fromJson(gushiciJSON,GushiciData.class); |
||||
content=gushiciData.getContent(); |
||||
title=gushiciData.getTitle(); |
||||
author=gushiciData.getAuthor(); |
||||
type=gushiciData.getType(); |
||||
Platform.runLater(()->{ |
||||
topBar.setText(content+" ——"+author+"《"+title+"》"); |
||||
GushiciPaneController gushiciPaneController=new GushiciPaneController(content, title, author, type); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("每日古诗词",gushiciPaneController); |
||||
}); |
||||
} |
||||
}).start(); |
||||
|
||||
} |
||||
|
||||
static class GushiciData{ |
||||
|
||||
private String content;//诗歌的内容
|
||||
|
||||
@SerializedName("origin") |
||||
private String title;//诗歌的标题
|
||||
|
||||
private String author;//诗歌作者
|
||||
|
||||
@SerializedName("category") |
||||
private String type;//诗歌类型
|
||||
|
||||
public void setContent(String content) { |
||||
this.content = content; |
||||
} |
||||
public String getContent() { |
||||
return content; |
||||
} |
||||
|
||||
public void setTitle(String title) { |
||||
this.title = title; |
||||
} |
||||
public String getTitle() { |
||||
return title; |
||||
} |
||||
|
||||
public void setAuthor(String author) { |
||||
this.author = author; |
||||
} |
||||
public String getAuthor() { |
||||
return author; |
||||
} |
||||
|
||||
public void setType(String type) { |
||||
this.type = type; |
||||
} |
||||
public String getType() { |
||||
return type; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,163 @@ |
||||
package me.lensferno.dogename.sayings; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import javafx.application.Platform; |
||||
import javafx.scene.control.Label; |
||||
import javafx.scene.layout.Pane; |
||||
import me.lensferno.dogename.utils.DialogMaker; |
||||
import me.lensferno.dogename.controllers.HitokotoPaneController; |
||||
import me.lensferno.dogename.utils.HtmlRequseter; |
||||
|
||||
public class Hitokoto { |
||||
|
||||
|
||||
private final String HITOKOTO_API ="https://v1.hitokoto.cn/"; |
||||
|
||||
String hitokotoJSON = null; |
||||
|
||||
private String getHitokoto() { |
||||
return HtmlRequseter.getHtml(HITOKOTO_API,false); |
||||
} |
||||
|
||||
public void showHitokoto(Pane rootPane, Label topBar){ |
||||
|
||||
new Thread(()->{ |
||||
|
||||
//hitokotoJSON = getHitokoto();
|
||||
|
||||
String hitokoto, from,author,creator, type; |
||||
|
||||
if((hitokotoJSON = getHitokoto())!=null){ |
||||
HitokotoData hitokotoData=new Gson().fromJson(hitokotoJSON, HitokotoData.class); |
||||
|
||||
hitokoto=hitokotoData.getHitokoto(); |
||||
from=hitokotoData.getFrom(); |
||||
author=hitokotoData.getAuthor(); |
||||
creator=hitokotoData.getCreator(); |
||||
type=hitokotoData.getType(); |
||||
|
||||
Platform.runLater(()->{ |
||||
topBar.setText("《"+from+"》:"+hitokoto+" ("+author+")"); |
||||
HitokotoPaneController hitokotoPaneController=new HitokotoPaneController(hitokoto, from,author,creator, type); |
||||
new DialogMaker(rootPane).createDialogWithOneBtn("每日一句话",hitokotoPaneController); |
||||
}); |
||||
} |
||||
}).start(); |
||||
} |
||||
|
||||
static class HitokotoData { |
||||
|
||||
private int id; |
||||
private String hitokoto; |
||||
private String type; |
||||
private String from; |
||||
|
||||
@SerializedName("from_who") |
||||
private String author; |
||||
|
||||
private String creator; |
||||
public void setId(int id) { |
||||
this.id = id; |
||||
} |
||||
public int getId() { |
||||
return id; |
||||
} |
||||
|
||||
public void setHitokoto(String hitokoto) { |
||||
this.hitokoto = hitokoto; |
||||
} |
||||
public String getHitokoto() { |
||||
return hitokoto; |
||||
} |
||||
|
||||
public void setType(String type) { |
||||
this.type = type; |
||||
} |
||||
|
||||
/** |
||||
* Type: |
||||
* a 动画 |
||||
* b 漫画 |
||||
* c 游戏 |
||||
* d 文学 |
||||
* e 原创 |
||||
* f 来自网络 |
||||
* g 其他 |
||||
* h 影视 |
||||
* i 诗词 |
||||
* j 网易云 |
||||
* k 哲学 |
||||
* l 抖机灵 |
||||
* |
||||
* @return |
||||
*/ |
||||
|
||||
public String getType() { |
||||
switch (type){ |
||||
case "a" : |
||||
type="动画"; |
||||
break; |
||||
case "b" : |
||||
type="漫画"; |
||||
break; |
||||
case "c" : |
||||
type="游戏"; |
||||
break; |
||||
case "d" : |
||||
type="文学"; |
||||
break; |
||||
case "e" : |
||||
type="原创"; |
||||
break; |
||||
case "f" : |
||||
type="来自网络"; |
||||
break; |
||||
case "g" : |
||||
type="其他"; |
||||
break; |
||||
case "h" : |
||||
type="影视"; |
||||
break; |
||||
case "i" : |
||||
type="诗词"; |
||||
break; |
||||
case "j" : |
||||
type="网易云"; |
||||
break; |
||||
case "k" : |
||||
type="哲学"; |
||||
break; |
||||
case "l" : |
||||
type="抖机灵"; |
||||
break; |
||||
default: |
||||
type="未知"; |
||||
|
||||
} |
||||
return type; |
||||
} |
||||
|
||||
public void setFrom(String from) { |
||||
this.from = from; |
||||
} |
||||
public String getFrom() { |
||||
return from; |
||||
} |
||||
|
||||
public void setAuthor(String author) { |
||||
this.author = author; |
||||
} |
||||
public String getAuthor() { |
||||
return author; |
||||
} |
||||
|
||||
public void setCreator(String creator) { |
||||
this.creator = creator; |
||||
} |
||||
public String getCreator() { |
||||
return creator; |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,32 @@ |
||||
package me.lensferno.dogename.utils; |
||||
|
||||
import java.awt.*; |
||||
import java.awt.datatransfer.DataFlavor; |
||||
import java.awt.datatransfer.StringSelection; |
||||
import java.awt.datatransfer.Transferable; |
||||
|
||||
public class Clipboard { |
||||
|
||||
public static void copyToClipboard(String text) { |
||||
java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); |
||||
Transferable trans = new StringSelection(text); |
||||
clipboard.setContents(trans, null); |
||||
} |
||||
|
||||
public static String getClipboardString() { |
||||
java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); |
||||
Transferable trans = clipboard.getContents(null); |
||||
|
||||
if (trans != null) { |
||||
if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) { |
||||
try { |
||||
return (String) trans.getTransferData(DataFlavor.stringFlavor); |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,113 @@ |
||||
package me.lensferno.dogename.utils; |
||||
|
||||
import com.jfoenix.controls.JFXButton; |
||||
import com.jfoenix.controls.JFXDialog; |
||||
import com.jfoenix.controls.JFXDialogLayout; |
||||
import javafx.beans.NamedArg; |
||||
import javafx.event.ActionEvent; |
||||
import javafx.event.EventHandler; |
||||
import javafx.geometry.Pos; |
||||
import javafx.scene.Node; |
||||
import javafx.scene.control.Label; |
||||
import javafx.scene.layout.Pane; |
||||
import javafx.scene.layout.StackPane; |
||||
import javafx.scene.paint.Paint; |
||||
import javafx.scene.text.Font; |
||||
import javafx.scene.text.FontWeight; |
||||
import javafx.scene.text.Text; |
||||
|
||||
|
||||
public class DialogMaker { |
||||
Pane rootPane; |
||||
|
||||
public DialogMaker(@NamedArg("rootPane") Pane rootPane){ |
||||
this.rootPane=rootPane; |
||||
} |
||||
|
||||
|
||||
JFXDialog dialog; |
||||
|
||||
public void createMessageDialog(@NamedArg("title") String title, @NamedArg("message") String message){ |
||||
JFXButton OKButton = new JFXButton("了解!"); |
||||
OKButton.setFont(Font.font("Microsoft YaHei",FontWeight.BOLD,12)); |
||||
OKButton.setPrefWidth(60); |
||||
OKButton.setPrefHeight(30); |
||||
|
||||
Text messageText=new Text(message); |
||||
messageText.setFont(Font.font("Microsoft YaHei",14)); |
||||
|
||||
createDialog(title,messageText,OKButton); |
||||
} |
||||
|
||||
//创建只有一个按钮的dialog
|
||||
public void createDialogWithOneBtn(@NamedArg("title") String title, @NamedArg("theBody") Node body){ |
||||
//dialog.setPrefHeight(rootPane.getPrefHeight());
|
||||
//dialog.setPrefWidth(rootPane.getPrefWidth());
|
||||
|
||||
JFXButton OKButton = new JFXButton("好的!"); |
||||
OKButton.setFont(Font.font("Microsoft YaHei",FontWeight.BOLD,12)); |
||||
OKButton.setPrefWidth(60); |
||||
OKButton.setPrefHeight(30); |
||||
|
||||
createDialog(title,body,OKButton); |
||||
|
||||
dialog.show(); |
||||
} |
||||
|
||||
//创建有OK和cancel按钮的dialog
|
||||
public void createDialogWithOKAndCancel(@NamedArg("title") String title, @NamedArg("message") String message, @NamedArg("OKEvent") EventHandler<ActionEvent> OKEvent){ |
||||
//dialog.setPrefHeight(rootPane.getPrefHeight());
|
||||
//dialog.setPrefWidth(rootPane.getPrefWidth());
|
||||
|
||||
JFXButton CancelButton = new JFXButton("手滑了"); |
||||
CancelButton.setFont(Font.font("Microsoft YaHei",FontWeight.BOLD,12)); |
||||
CancelButton.setPrefWidth(60); |
||||
CancelButton.setPrefHeight(30); |
||||
|
||||
JFXButton OKButton = new JFXButton("是!"); |
||||
OKButton.setFont(Font.font("Microsoft YaHei",FontWeight.BOLD,12)); |
||||
OKButton.setPrefWidth(60); |
||||
OKButton.setPrefHeight(30); |
||||
OKButton.setTextFill(Paint.valueOf("red")); |
||||
OKButton.addEventHandler(ActionEvent.ACTION,e -> {dialog.close();}); |
||||
OKButton.addEventHandler(ActionEvent.ACTION,OKEvent); |
||||
|
||||
Text messageText=new Text(message); |
||||
messageText.setFont(Font.font("Microsoft YaHei",14)); |
||||
|
||||
createDialog(title,messageText,CancelButton,OKButton); |
||||
|
||||
dialog.show(); |
||||
} |
||||
|
||||
public void createDialog(@NamedArg("title") String title, @NamedArg("theBody") Node body, @NamedArg("buttons") JFXButton...buttons){ |
||||
|
||||
JFXDialogLayout content = new JFXDialogLayout(); |
||||
|
||||
Label titleLabel=new Label(title); |
||||
titleLabel.setFont(Font.font("Microsoft YaHei", FontWeight.BOLD,20)); |
||||
content.setHeading(titleLabel); |
||||
|
||||
content.setBody(body); |
||||
content.setAlignment(Pos.CENTER); |
||||
|
||||
StackPane tempPane=new StackPane(); |
||||
tempPane.setPrefHeight(rootPane.getPrefHeight()); |
||||
tempPane.setPrefWidth(rootPane.getPrefWidth()); |
||||
rootPane.getChildren().add(tempPane); |
||||
|
||||
dialog = new JFXDialog(tempPane,content,JFXDialog.DialogTransition.TOP); |
||||
|
||||
dialog.setOnDialogClosed(event -> rootPane.getChildren().remove(tempPane)); |
||||
|
||||
for (JFXButton button : buttons) { |
||||
button.addEventHandler(ActionEvent.ACTION, e -> { |
||||
dialog.close(); |
||||
}); |
||||
} |
||||
|
||||
content.setActions(buttons); |
||||
|
||||
dialog.show(); |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
package me.lensferno.dogename.utils; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileNotFoundException; |
||||
import java.io.FileOutputStream; |
||||
|
||||
public class FileProcessor { |
||||
|
||||
static Logger log = LogManager.getLogger(); |
||||
|
||||
public static void writeFile(byte[] bytes, File file){ |
||||
try { |
||||
FileOutputStream fileOutputStream=new FileOutputStream(file); |
||||
fileOutputStream.write(bytes); |
||||
fileOutputStream.close(); |
||||
} catch (FileNotFoundException e) { |
||||
e.printStackTrace(); |
||||
}catch (Exception e){ |
||||
log.error("Error in writting file"+"\""+file.getName()+"\""+":"+e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,70 @@ |
||||
package me.lensferno.dogename.utils; |
||||
|
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.BufferedReader; |
||||
import java.io.InputStream; |
||||
import java.io.InputStreamReader; |
||||
import java.net.URL; |
||||
import java.net.URLConnection; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.util.zip.GZIPInputStream; |
||||
import java.util.zip.Inflater; |
||||
import java.util.zip.InflaterInputStream; |
||||
|
||||
public class HtmlRequseter { |
||||
|
||||
static Logger log = LogManager.getLogger(); |
||||
|
||||
public static String getHtml(String address,boolean output) |
||||
{ |
||||
StringBuilder sb = new StringBuilder(); |
||||
try { |
||||
BufferedReader bis; |
||||
URL url = new URL(address); |
||||
URLConnection conn = url.openConnection(); |
||||
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36"); |
||||
|
||||
conn.setRequestProperty("Accept-Encoding", "gzip,deflate"); |
||||
conn.connect(); |
||||
|
||||
System.out.println("--------------------------------------------------------------------"); |
||||
System.out.println("[INFO]Getting:"+conn.getURL()); |
||||
System.out.println("[INFO]Content compress type:"+conn.getContentEncoding()); |
||||
|
||||
InputStream is = conn.getInputStream(); |
||||
String connEncoding=conn.getContentEncoding(); |
||||
|
||||
if(connEncoding==null) |
||||
connEncoding="none"; |
||||
|
||||
switch (connEncoding) { |
||||
case "deflate": |
||||
InflaterInputStream deflate = new InflaterInputStream(is, new Inflater(true)); |
||||
bis = new BufferedReader(new InputStreamReader(deflate, StandardCharsets.UTF_8)); |
||||
break; |
||||
case "gzip": |
||||
GZIPInputStream gzip = new GZIPInputStream(is); |
||||
bis = new BufferedReader(new InputStreamReader(gzip, StandardCharsets.UTF_8)); |
||||
break; |
||||
default: |
||||
bis = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); |
||||
break; |
||||
} |
||||
String temp; |
||||
while ((temp = bis.readLine()) != null) { |
||||
sb.append(temp); |
||||
sb.append("\n"); |
||||
} |
||||
}catch(Exception e){ |
||||
log.error("Error in getting HTML:"+e); |
||||
return null; |
||||
} |
||||
|
||||
if(output) |
||||
System.out.println("[INFO]Got:"+sb.toString()); |
||||
|
||||
return sb.toString(); |
||||
} |
||||
} |
@ -0,0 +1,53 @@ |
||||
package me.lensferno.dogename.voice; |
||||
|
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
public class Token implements Serializable { |
||||
|
||||
/* |
||||
返回 |
||||
需要根据 Content-Type的头部来确定是否服务端合成成功。 |
||||
|
||||
如果合成成功,返回的Content-Type以“audio”开头 |
||||
|
||||
aue =3 ,返回为二进制mp3文件,具体header信息 Content-Type: audio/mp3; |
||||
aue =4 ,返回为二进制pcm文件,具体header信息 Content-Type:audio/basic;codec=pcm;rate=16000;channel=1 |
||||
aue =5 ,返回为二进制pcm文件,具体header信息 Content-Type:audio/basic;codec=pcm;rate=8000;channel=1 |
||||
aue =6 ,返回为二进制wav文件,具体header信息 Content-Type: audio/wav; |
||||
如果合成出现错误,则会返回json文本,具体header信息为:Content-Type: application/json。其中sn字段主要用于DEBUG追查问题,如果出现问题,可以提供sn帮助确认问题。 |
||||
*/ |
||||
|
||||
private long expTime; |
||||
|
||||
@SerializedName("access_token") |
||||
private String accessToken; |
||||
@SerializedName("expires_in") |
||||
private long expiresIn; |
||||
|
||||
public void setExpTime() { |
||||
this.expTime = System.currentTimeMillis() + (expiresIn - 3600) * 1000; |
||||
} |
||||
|
||||
public boolean isTokenTimeOut() { |
||||
return System.currentTimeMillis() > expTime; |
||||
} |
||||
|
||||
public void setAccessToken(String accessToken) { |
||||
this.accessToken = accessToken; |
||||
} |
||||
|
||||
public String getAccessToken() { |
||||
return accessToken; |
||||
} |
||||
|
||||
public void setExpiresIn(long expiresIn) { |
||||
this.expiresIn = expiresIn; |
||||
} |
||||
|
||||
public long getExpiresIn() { |
||||
return expiresIn; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,174 @@ |
||||
package me.lensferno.dogename.voice; |
||||
|
||||
import com.google.gson.Gson; |
||||
import me.lensferno.dogename.utils.HtmlRequseter; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
|
||||
import java.io.*; |
||||
import java.net.HttpURLConnection; |
||||
import java.net.URL; |
||||
|
||||
public class TokenManager { |
||||
|
||||
Logger log= LogManager.getLogger(); |
||||
|
||||
public static final String separator=File.separator; |
||||
|
||||
String cachedVoicePath="caches\\voice\\"; |
||||
|
||||
final private int TOKEN_NULL = -2; |
||||
final private int TOKEN_EXPIRED = -1; |
||||
final private int TOKEN_OK = 0; |
||||
|
||||
final String API_KEY="dIHCtamVdD0ERO1yyFir2iI4"; |
||||
final String SEC_KEY="HmpBQY3gG4PyZ0cmudnCbMeoMcMejuuW"; |
||||
|
||||
final String TOKEN_API_URL ="https://openapi.baidu.com/oauth/2.0/token"; |
||||
|
||||
File tokenFile=new File("API_voice.token"); |
||||
|
||||
private Token token=null; |
||||
|
||||
String tokenStatus="ok"; |
||||
|
||||
private void updateTokenStatus(int statusCode){ |
||||
switch(statusCode){ |
||||
case TOKEN_OK: |
||||
tokenStatus="ok"; |
||||
break; |
||||
|
||||
case TOKEN_EXPIRED: |
||||
if(netAvailable()){ refreshToken();} |
||||
|
||||
if(checkTokenAvailable()!=0){ tokenStatus="not ok";} |
||||
break; |
||||
|
||||
case TOKEN_NULL: |
||||
if(netAvailable()){ refreshToken();} |
||||
|
||||
if(checkTokenAvailable()!=0){ tokenStatus="not ok";} |
||||
break; |
||||
|
||||
default : |
||||
tokenStatus="not ok"; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
private void refreshToken(){ |
||||
|
||||
fetchToken(); |
||||
writeToken(); |
||||
} |
||||
|
||||
|
||||
public void init(){ |
||||
|
||||
if(tokenFile.exists()){ |
||||
loadToken(); |
||||
updateTokenStatus(checkTokenAvailable()); |
||||
|
||||
}else{ |
||||
|
||||
if(netAvailable()){ |
||||
|
||||
refreshToken(); |
||||
|
||||
updateTokenStatus(checkTokenAvailable()); |
||||
|
||||
}else { |
||||
tokenStatus="not ok"; |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
public String getTokenStatus() { |
||||
return tokenStatus; |
||||
} |
||||
|
||||
public Token getToken() { |
||||
return token; |
||||
} |
||||
|
||||
private int checkTokenAvailable() { |
||||
|
||||
//token是空的就返回-2
|
||||
if (token == null || token.getAccessToken() == null) { |
||||
log.info("Token was null"); |
||||
return -2; |
||||
} |
||||
|
||||
//token过期了就返回-1
|
||||
if (token.isTokenTimeOut()) { |
||||
log.info("Token expired."); |
||||
return -1; |
||||
} |
||||
|
||||
//正常的话就返回0
|
||||
log.info("Token OK."); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
void fetchToken(){ |
||||
try{ |
||||
token=new Gson().fromJson( |
||||
HtmlRequseter.getHtml( |
||||
TOKEN_API_URL |
||||
+ "?grant_type=client_credentials&client_id=" + API_KEY |
||||
+ "&client_secret=" + SEC_KEY, |
||||
true) |
||||
,Token.class); |
||||
|
||||
token.setExpTime(); |
||||
}catch (Exception e){ |
||||
log.error("Error to get Token:"+e); |
||||
token=null; |
||||
} |
||||
} |
||||
|
||||
private boolean netAvailable(){ |
||||
try { |
||||
|
||||
URL sourcesURL = new URL("http://www.baidu.com"); |
||||
HttpURLConnection connection = (HttpURLConnection) sourcesURL.openConnection(); |
||||
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"); |
||||
connection.connect(); |
||||
|
||||
InputStream stream = connection.getInputStream(); |
||||
stream.read(); |
||||
stream.close(); |
||||
|
||||
return true; |
||||
}catch (Exception e){ |
||||
log.info("Network is not available."); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private void loadToken(){ |
||||
ObjectInputStream ois; |
||||
try{ |
||||
ois =new ObjectInputStream(new FileInputStream(tokenFile)); |
||||
this.token =(Token) ois.readObject(); |
||||
ois.close(); |
||||
}catch (Exception e){ |
||||
log.error("Error in loading Token:"+e); |
||||
this.token=null; |
||||
} |
||||
} |
||||
|
||||
private void writeToken(){ |
||||
|
||||
try{ |
||||
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream(tokenFile)); |
||||
oos.writeObject(token); |
||||
oos.close(); |
||||
}catch (Exception e){ |
||||
log.error("Error in writing Token:"+e); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,195 @@ |
||||
package me.lensferno.dogename.voice; |
||||
|
||||
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader; |
||||
import me.lensferno.dogename.utils.FileProcessor; |
||||
import okhttp3.*; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import javax.sound.sampled.*; |
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.net.InetAddress; |
||||
import java.net.NetworkInterface; |
||||
import java.net.URLEncoder; |
||||
import java.util.Random; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
public class VoicePlayer { |
||||
|
||||
public static final String separator=File.separator; |
||||
|
||||
Logger log= LogManager.getLogger("VoicePlayerLogger"); |
||||
|
||||
private final String VOICE_API="https://tsn.baidu.com/text2audio"; |
||||
|
||||
Token token; |
||||
|
||||
public VoicePlayer(Token token){ |
||||
this.token=token; |
||||
|
||||
} |
||||
|
||||
String cachedVoicePath="caches"+separator+"voice"+separator; |
||||
|
||||
File cacheDir =new File(cachedVoicePath); |
||||
|
||||
OkHttpClient okHttpClient=new OkHttpClient.Builder() |
||||
.connectTimeout(10, TimeUnit.SECONDS) |
||||
.writeTimeout(10,TimeUnit.SECONDS) |
||||
.readTimeout(10,TimeUnit.SECONDS) |
||||
.build(); |
||||
|
||||
|
||||
public void playVoice(String name,String speaker,String intonation,String speed) { |
||||
|
||||
String cachedVoiceName; |
||||
cachedVoiceName = name + "_" + speaker+ "_" + speed +"_"+intonation; |
||||
|
||||
File cachedVoice = new File(cachedVoicePath + cachedVoiceName + ".mp3"); |
||||
|
||||
if (!cachedVoice.exists()) { |
||||
System.out.println("Voice of "+cachedVoice+" not exists,fetch from network."); |
||||
getVoiceData(name,speaker,speed,intonation,cachedVoice); |
||||
//playSound(cachedVoice);
|
||||
|
||||
} else { |
||||
new Thread(() -> { |
||||
System.out.println("Voice of "+cachedVoice+" exists,playing cache."); |
||||
playSound(cachedVoice); |
||||
}).start(); |
||||
} |
||||
|
||||
} |
||||
|
||||
private void getVoiceData(String name,String speaker,String speed,String intonation,File cachedVoice){ |
||||
|
||||
new Thread(() -> { |
||||
try{ |
||||
|
||||
FormBody formBody=new FormBody.Builder() |
||||
.add("tex",URLEncoder.encode(name,"utf-8")) |
||||
.add("tok",token.getAccessToken()) |
||||
.add("cuid",getMACAddress()) |
||||
.add("ctp","1") |
||||
.add("lan","zh") |
||||
.add("spd",speed) |
||||
.add("per",speaker) |
||||
.add("pit",intonation) |
||||
.add("aue","3") |
||||
.build(); |
||||
|
||||
Request request=new Request.Builder() |
||||
.url(VOICE_API) |
||||
.header("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36") |
||||
.post(formBody) |
||||
.build(); |
||||
|
||||
|
||||
okHttpClient.newCall(request).enqueue(new Callback() { |
||||
@Override |
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) { |
||||
log.warn("Failed to get voice:"+e.toString()); |
||||
} |
||||
|
||||
@Override |
||||
public void onResponse(@NotNull Call call, @NotNull Response response) { |
||||
if(response.header("Content-type").contains("json")){ |
||||
log.warn("Request error:"+response.toString()); |
||||
}else { |
||||
boolean success=cacheVoiceFile(response,cachedVoice); |
||||
if (success) { |
||||
log.info("cache voice of "+name+" to file "+cachedVoice.getPath()+" success"); |
||||
playSound(cachedVoice); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
|
||||
}catch(Exception e){ |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
}).start(); |
||||
} |
||||
|
||||
private boolean cacheVoiceFile(Response response,File cacheVoice){ |
||||
|
||||
try { |
||||
|
||||
if(!cacheDir.exists()) |
||||
cacheDir.mkdirs(); |
||||
|
||||
if(!cacheVoice.exists()) |
||||
cacheVoice.createNewFile(); |
||||
|
||||
//FileOutputStream cacheFile=new FileOutputStream(cacheVoice);
|
||||
FileProcessor.writeFile(response.body().bytes(),cacheVoice); |
||||
//IOUtils.write(response.body().bytes(),cacheFile);
|
||||
return true; |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
log.warn("Error to cache voice file:"+e.toString()); |
||||
return false; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
private void playSound(File file) { |
||||
|
||||
try { |
||||
//使用 mp3spi 解码 mp3 音频文件
|
||||
MpegAudioFileReader mp = new MpegAudioFileReader(); |
||||
AudioInputStream stream = mp.getAudioInputStream(file); |
||||
AudioFormat baseFormat = stream.getFormat(); |
||||
//设定输出格式为pcm格式的音频文件
|
||||
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false); |
||||
// 输出到音频
|
||||
stream = AudioSystem.getAudioInputStream(format, stream); |
||||
AudioFormat target = stream.getFormat(); |
||||
DataLine.Info dinfo = new DataLine.Info(SourceDataLine.class, target, AudioSystem.NOT_SPECIFIED); |
||||
SourceDataLine line; |
||||
int len; |
||||
line = (SourceDataLine) AudioSystem.getLine(dinfo); |
||||
line.open(target); |
||||
line.start(); |
||||
byte[] buffer = new byte[1024]; |
||||
while ((len = stream.read(buffer)) > 0) { |
||||
line.write(buffer, 0, len); |
||||
} |
||||
line.drain(); |
||||
line.stop(); |
||||
line.close(); |
||||
} catch (Exception e) { |
||||
log.warn("Error to play voice audio:"+e.toString()); |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
|
||||
private static String getMACAddress() { |
||||
|
||||
try{ |
||||
|
||||
byte[] mac = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getHardwareAddress(); |
||||
|
||||
StringBuffer sb = new StringBuffer(); |
||||
|
||||
for (int i = 0; i < mac.length; i++) { |
||||
if (i != 0) { |
||||
sb.append("-"); |
||||
} |
||||
String s = Integer.toHexString(mac[i] & 0xFF); |
||||
sb.append(s.length() == 1 ? 0 + s : s); |
||||
} |
||||
return sb.toString().toUpperCase(); |
||||
|
||||
}catch (Exception e){ |
||||
return String.valueOf(new Random().nextLong()); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,3 @@ |
||||
Manifest-Version: 1.0 |
||||
Main-Class: me.lensferno.dogename.Main |
||||
|
@ -0,0 +1,53 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import com.jfoenix.controls.JFXTextField?> |
||||
<?import javafx.geometry.Insets?> |
||||
<?import javafx.scene.control.Label?> |
||||
<?import javafx.scene.layout.*?> |
||||
<?import javafx.scene.text.*?> |
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="143.0" prefWidth="546.0" spacing="5.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<padding> |
||||
<Insets left="10.0" right="10.0" top="10.0" /> |
||||
</padding> |
||||
<children> |
||||
<Label text="您可以自定义百度语音合成的API KEY和SEC KEY,而不必使用作者提供的信息。" wrapText="true"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</Label> |
||||
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> |
||||
<children> |
||||
<Label text="API Key:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
<HBox.margin> |
||||
<Insets /> |
||||
</HBox.margin> |
||||
</Label> |
||||
<JFXTextField prefHeight="29.0" prefWidth="436.0" promptText="在此输入API Key"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXTextField> |
||||
</children> |
||||
</HBox> |
||||
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> |
||||
<children> |
||||
<Label text="Secret Key:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
<HBox.margin> |
||||
<Insets /> |
||||
</HBox.margin> |
||||
</Label> |
||||
<JFXTextField prefHeight="23.0" prefWidth="418.0" promptText="在此输入Secret Key"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXTextField> |
||||
</children> |
||||
</HBox> |
||||
</children> |
||||
</fx:root> |
@ -0,0 +1,25 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import javafx.scene.layout.VBox?> |
||||
<?import javafx.scene.shape.Rectangle?> |
||||
<?import javafx.scene.text.*?> |
||||
<fx:root alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="380.0" prefWidth="794.0" spacing="15.0" style="-fx-background-color: white;" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<children> |
||||
<Text fx:id="contentText" strokeType="OUTSIDE" strokeWidth="0.0" text="“欲把西湖比西子,淡妆浓抹总相宜。”" textAlignment="CENTER" wrappingWidth="794.0"> |
||||
<font> |
||||
<Font name="Microsoft YaHei Bold" size="30.0" /> |
||||
</font> |
||||
</Text> |
||||
<Rectangle fill="#1f93ff41" height="58.0" stroke="BLACK" strokeType="INSIDE" strokeWidth="0.0" width="795.0" /> |
||||
<Text fx:id="contentInfo" strokeType="OUTSIDE" strokeWidth="0.0" text="《饮湖上初晴后雨二首·其二》——苏轼" textAlignment="CENTER" wrappingWidth="794.0"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="16.0" /> |
||||
</font> |
||||
</Text> |
||||
<Text fx:id="contentType" strokeType="OUTSIDE" strokeWidth="0.0" text="古诗文-山水-西湖" textAlignment="CENTER" wrappingWidth="794.0"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="16.0" /> |
||||
</font> |
||||
</Text> |
||||
</children> |
||||
</fx:root> |
@ -0,0 +1,48 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import java.lang.*?> |
||||
<?import javafx.geometry.*?> |
||||
<?import javafx.scene.layout.*?> |
||||
<?import com.jfoenix.controls.*?> |
||||
<?import javafx.geometry.Insets?> |
||||
<?import javafx.scene.layout.HBox?> |
||||
<?import javafx.scene.layout.VBox?> |
||||
<?import javafx.scene.text.*?> |
||||
|
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="395.0" prefWidth="287.0" spacing="5.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<children> |
||||
<JFXListView fx:id="historyList" prefHeight="270.0" prefWidth="301.0" /> |
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="历史记录超过2000条时会自动清空列表重新记录"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="12.0" /> |
||||
</font> |
||||
</Text> |
||||
<JFXTextField fx:id="searchBar" promptText="查找..."> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXTextField> |
||||
<HBox prefHeight="29.0" prefWidth="259.0" spacing="5.0"> |
||||
<children> |
||||
<JFXButton fx:id="previousBtn" onAction="#upSearch" text="上一个"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton fx:id="nextBtn" onAction="#downSearch" text="下一个"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton onAction="#clearHistory" text="全部清除"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
</HBox> |
||||
</children> |
||||
<padding> |
||||
<Insets left="14.0" right="14.0" top="14.0" /> |
||||
</padding> |
||||
</fx:root> |
@ -0,0 +1,30 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import com.jfoenix.controls.JFXButton?> |
||||
<?import javafx.scene.control.Label?> |
||||
<?import javafx.scene.layout.HBox?> |
||||
<?import javafx.scene.layout.VBox?> |
||||
<?import javafx.scene.text.Font?> |
||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="134.0" prefWidth="300.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="me.lensferno.dogename.controllers.MiniPaneController"> |
||||
<children> |
||||
<Label fx:id="chosenNameLabel" alignment="CENTER" prefHeight="68.0" prefWidth="300.0" text="(´□`川)" textAlignment="CENTER" wrapText="true"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="48.0" /> |
||||
</font> |
||||
</Label> |
||||
<HBox alignment="CENTER" prefHeight="67.0" prefWidth="405.0" spacing="20.0"> |
||||
<children> |
||||
<JFXButton fx:id="miniModeBtn" onAction="#recoverMode" prefHeight="60.0" prefWidth="166.0" text="恢复"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="26.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton fx:id="anPaiBtn" onAction="#anPai" prefHeight="60.0" prefWidth="166.0" text="安排一下"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="26.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
</HBox> |
||||
</children> |
||||
</VBox> |
@ -0,0 +1,9 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import com.jfoenix.controls.JFXListView?> |
||||
<?import javafx.scene.layout.Pane?> |
||||
<Pane fx:id="namePane" prefHeight="196.0" prefWidth="279.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<children> |
||||
<JFXListView fx:id="nameList" editable="true" layoutX="1.0" prefHeight="193.0" prefWidth="278.0" styleClass="nameList" /> |
||||
</children> |
||||
</Pane> |
@ -0,0 +1,80 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import com.jfoenix.controls.*?> |
||||
<?import javafx.geometry.Insets?> |
||||
<?import javafx.scene.layout.*?> |
||||
<?import javafx.scene.text.*?> |
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="498.0" prefWidth="474.0" spacing="15.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<padding> |
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> |
||||
</padding> |
||||
<children> |
||||
<JFXListView fx:id="nameList" prefHeight="149.0" /> |
||||
<JFXTextArea fx:id="inputName" focusColor="#0086ff" labelFloat="true" prefHeight="104.0" promptText="请输入要添加的名字,如需批量添加请一行一个名字。"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="13.0" /> |
||||
</font> |
||||
</JFXTextArea> |
||||
<HBox alignment="CENTER" prefHeight="39.0" prefWidth="454.0"> |
||||
<children> |
||||
<JFXButton onAction="#addNameFromScreen" prefHeight="35.0" prefWidth="176.0" text="从屏幕上截取名字"> |
||||
<HBox.margin> |
||||
<Insets /> |
||||
</HBox.margin> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton onAction="#copyTo" prefHeight="35.0" prefWidth="176.0" text="粘贴剪贴板内容"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
</HBox> |
||||
<HBox alignment="CENTER" spacing="5.0"> |
||||
<children> |
||||
<JFXButton fx:id="deleteName" onAction="#deleteName" prefHeight="36.0" prefWidth="120.0" ripplerFill="RED" text="删除所选" textFill="RED"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton fx:id="deleteAll" onAction="#deleteAllName" prefHeight="36.0" prefWidth="120.0" ripplerFill="RED" text="删除所有" textFill="RED"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton onAction="#makeMass" prefHeight="28.0" prefWidth="120.0" ripplerFill="#4997fc" text="打乱顺序"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
<padding> |
||||
<Insets left="3.0" top="3.0" /> |
||||
</padding> |
||||
</HBox> |
||||
<HBox alignment="CENTER" spacing="5.0"> |
||||
<children> |
||||
<JFXButton onAction="#exoprtNameList" prefHeight="28.0" prefWidth="120.0" ripplerFill="#4997fc" text="备份"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton onAction="#importNameList" prefHeight="28.0" prefWidth="120.0" ripplerFill="#4997fc" text="恢复"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton fx:id="addName" onAction="#addName" prefHeight="36.0" prefWidth="120.0" ripplerFill="#4997fc" text="添加"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
<padding> |
||||
<Insets left="3.0" top="3.0" /> |
||||
</padding> |
||||
</HBox> |
||||
</children> |
||||
</fx:root> |
@ -0,0 +1,36 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import com.jfoenix.controls.JFXTextField?> |
||||
<?import javafx.scene.layout.HBox?> |
||||
<?import javafx.scene.layout.VBox?> |
||||
<?import javafx.scene.text.*?> |
||||
<fx:root alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="131.0" prefWidth="303.0" spacing="10.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<children> |
||||
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="215.0"> |
||||
<children> |
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="最小:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</Text> |
||||
<JFXTextField fx:id="minValueField" labelFloat="true" prefHeight="23.0" prefWidth="141.0" text="0"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="13.0" /> |
||||
</font></JFXTextField> |
||||
</children> |
||||
</HBox> |
||||
<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="215.0"> |
||||
<children> |
||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="最大:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</Text> |
||||
<JFXTextField fx:id="maxValueField" labelFloat="true" prefHeight="23.0" prefWidth="141.0" text="0"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="13.0" /> |
||||
</font></JFXTextField> |
||||
</children> |
||||
</HBox> |
||||
</children> |
||||
</fx:root> |
@ -0,0 +1,140 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import java.lang.*?> |
||||
<?import javafx.scene.control.*?> |
||||
<?import javafx.scene.shape.*?> |
||||
<?import com.jfoenix.controls.*?> |
||||
<?import javafx.geometry.*?> |
||||
<?import javafx.scene.control.Label?> |
||||
<?import javafx.scene.layout.*?> |
||||
<?import javafx.scene.shape.Line?> |
||||
<?import javafx.scene.text.*?> |
||||
|
||||
<fx:root prefHeight="360.0" prefWidth="593.0" style="-fx-background-color: white;" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<children> |
||||
<HBox prefHeight="50.0" prefWidth="592.0" spacing="10.0"> |
||||
<children> |
||||
<Pane prefHeight="50.0" prefWidth="296.0"> |
||||
<children> |
||||
<JFXRadioButton fx:id="ignoreOnce" layoutX="14.0" layoutY="14.0" selected="true" text="人人有份(跳过已点过的名字)"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXRadioButton> |
||||
</children> |
||||
</Pane> |
||||
<Pane prefHeight="50.0" prefWidth="296.0"> |
||||
<children> |
||||
<JFXCheckBox fx:id="equalModeBtn" checkedColor="#079cd7" layoutX="14.0" layoutY="11.0" onAction="#equalBtnAction" prefHeight="28.0" prefWidth="162.0" text="记录已点过的名字" unCheckedColor="#13aecf"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXCheckBox> |
||||
</children> |
||||
</Pane> |
||||
</children> |
||||
</HBox> |
||||
<HBox prefHeight="50.0" prefWidth="592.0" spacing="10.0"> |
||||
<children> |
||||
<Pane prefHeight="50.0" prefWidth="296.0"> |
||||
<children> |
||||
<JFXRadioButton fx:id="chooseOnce" layoutX="14.0" layoutY="14.0" text="概率均分(不跳过已点过的名字)"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXRadioButton> |
||||
</children> |
||||
</Pane> |
||||
<HBox alignment="CENTER" prefHeight="50.0" prefWidth="286.0" spacing="1.0"> |
||||
<children> |
||||
<JFXButton buttonType="RAISED" onAction="#clearIgnoreList" prefHeight="30.0" prefWidth="131.0" ripplerFill="#04d5ff" style="-fx-background-color: rgba(0,0,0,0.09);" text="清空记录" textFill="#1797e3"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="12.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
<JFXButton buttonType="RAISED" layoutX="15.0" layoutY="11.0" onAction="#showEqualMode" prefHeight="30.0" prefWidth="131.0" ripplerFill="#00e842" style="-fx-background-color: rgba(0,0,0,0.09);" text="选项说明" textFill="#294f65"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="12.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
</HBox> |
||||
</children> |
||||
</HBox> |
||||
<Line endX="592.0" /> |
||||
<Pane prefHeight="50.0" prefWidth="592.0"> |
||||
<children> |
||||
<JFXRadioButton fx:id="randomTimes" layoutX="14.0" layoutY="14.0" selected="true" text="挑选次数随机(100~250)"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXRadioButton> |
||||
</children> |
||||
</Pane> |
||||
<HBox prefHeight="50.0" prefWidth="592.0"> |
||||
<children> |
||||
<JFXRadioButton fx:id="fixedTimes" text="挑选次数固定:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</JFXRadioButton> |
||||
<JFXSlider fx:id="cycleTimesBar" max="200.0" min="3.0" prefHeight="18.0" prefWidth="386.0" showTickLabels="true" showTickMarks="true" value="120.0" /> |
||||
</children> |
||||
<padding> |
||||
<Insets left="14.0" top="14.0" /> |
||||
</padding> |
||||
<VBox.margin> |
||||
<Insets /> |
||||
</VBox.margin> |
||||
</HBox> |
||||
<Line endX="592.0" /> |
||||
<HBox prefHeight="50.0" prefWidth="200.0"> |
||||
<children> |
||||
<Label prefHeight="23.0" prefWidth="57.0" text="调速:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="17.0" /> |
||||
</font> |
||||
</Label> |
||||
<JFXSlider fx:id="speedBar" majorTickUnit="10.0" prefHeight="15.0" prefWidth="479.0" showTickLabels="true" showTickMarks="true" value="80.0" /> |
||||
</children> |
||||
<padding> |
||||
<Insets left="14.0" top="14.0" /> |
||||
</padding> |
||||
<VBox.margin> |
||||
<Insets /> |
||||
</VBox.margin> |
||||
</HBox> |
||||
<Line endX="592.0" /> |
||||
<Pane prefHeight="50.0" prefWidth="593.0"> |
||||
<children> |
||||
<JFXCheckBox fx:id="newAlgoBtn" checkedColor="#079cd7" layoutX="14.0" layoutY="14.0" selected="true" text="使用Java SecureRandom随机算法" textFill="#2c2424" unCheckedColor="#13aecf"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXCheckBox> |
||||
</children> |
||||
</Pane> |
||||
<HBox prefHeight="50.0" prefWidth="200.0" spacing="20.0"> |
||||
<children> |
||||
<JFXCheckBox fx:id="showSayingBtn" checkedColor="#079cd7" prefHeight="31.0" prefWidth="188.0" selected="true" text="启动时展示一言/古诗词" textFill="#2c2424" unCheckedColor="#13aecf"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXCheckBox> |
||||
<JFXCheckBox fx:id="voicePlayBtn" checkedColor="#079cd7" prefHeight="31.0" prefWidth="82.0" selected="true" text="语音播报" textFill="#2c2424" unCheckedColor="#13aecf"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXCheckBox> |
||||
<JFXButton onAction="#showVoiceSettingsPane" prefHeight="31.0" prefWidth="76.0" style="-fx-background-color: rgba(0,0,0,0.09);" text="语音设置"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="14.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
<padding> |
||||
<Insets left="14.0" top="14.0" /> |
||||
</padding> |
||||
</HBox> |
||||
</children> |
||||
</fx:root> |
@ -0,0 +1,61 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<?import com.jfoenix.controls.JFXButton?> |
||||
<?import com.jfoenix.controls.JFXComboBox?> |
||||
<?import com.jfoenix.controls.JFXSlider?> |
||||
<?import javafx.geometry.Insets?> |
||||
<?import javafx.scene.control.Label?> |
||||
<?import javafx.scene.layout.*?> |
||||
<?import javafx.scene.text.Font?> |
||||
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="176.0" prefWidth="487.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> |
||||
<children> |
||||
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> |
||||
<children> |
||||
<Label text="朗读人:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="16.0" /> |
||||
</font> |
||||
</Label> |
||||
<JFXComboBox fx:id="speakerSelectBar" prefHeight="23.0" prefWidth="138.0" style="-fx-font-family: Microsoft YaHei;" /> |
||||
</children> |
||||
<padding> |
||||
<Insets left="10.0" /> |
||||
</padding> |
||||
</HBox> |
||||
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> |
||||
<children> |
||||
<Label text="语速:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="16.0" /> |
||||
</font> |
||||
</Label> |
||||
<JFXSlider fx:id="voiceSpeedBar" majorTickUnit="1.0" max="15.0" minorTickCount="1" prefHeight="14.0" prefWidth="395.0" showTickLabels="true" snapToTicks="true" value="5.0" /> |
||||
</children> |
||||
<padding> |
||||
<Insets left="10.0" /> |
||||
</padding> |
||||
</HBox> |
||||
<HBox alignment="CENTER_LEFT" prefHeight="40.0" prefWidth="200.0" spacing="5.0"> |
||||
<children> |
||||
<Label text="语调:"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="16.0" /> |
||||
</font> |
||||
</Label> |
||||
<JFXSlider fx:id="intonationBar" majorTickUnit="1.0" max="15.0" minorTickCount="1" prefHeight="14.0" prefWidth="395.0" showTickLabels="true" snapToTicks="true" value="5.0" /> |
||||
</children> |
||||
<padding> |
||||
<Insets left="10.0" /> |
||||
</padding> |
||||
</HBox> |
||||
<Pane nodeOrientation="LEFT_TO_RIGHT" prefHeight="40.0" prefWidth="487.0"> |
||||
<children> |
||||
<JFXButton layoutX="14.0" layoutY="9.0" onAction="#showAdvancedVoiceSettings" text="高级设置"> |
||||
<font> |
||||
<Font name="Microsoft YaHei" size="13.0" /> |
||||
</font> |
||||
</JFXButton> |
||||
</children> |
||||
</Pane> |
||||
</children> |
||||
</fx:root> |
Loading…
Reference in new issue