用java计算器界面代码,java设计一个简单的计算器界面

JAVA计算器代码

import java.awt.*;

创新互联专注于新乐网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供新乐营销型网站建设,新乐网站制作、新乐网页设计、新乐网站官网定制、成都微信小程序服务,打造新乐网络公司原创品牌,更为您提供新乐网站排名全网营销落地服务。

import java.applet.*;

public class CalculatorDemo extends Applet

{

TextField answerText;

Button pointButton,equalButton,plusButton;

Button minusButton,clearButton,multiButton,divisionButton;

Button[] b=new Button[10];

String currentOp,preOp;

String foreText,backText;

boolean isFloat=false;

public void init()

{

Panel p1=new Panel();

Panel p2=new Panel();

Panel p3=new Panel();

currentOp=new String("");

preOp=new String("");

foreText=new String("");

backText=new String("");

answerText=new TextField(8);

setBackground(Color.lightGray);

setForeground(Color.blue);

for(int i=9;i=0;i--)

{

b[i]=new Button(Integer.toString(i));

p2.add(b[i]);

}

pointButton=new Button(".");

equalButton=new Button("=");

equalButton.setForeground(Color.red);

clearButton=new Button("清除");

clearButton.setForeground(Color.red);

divisionButton=new Button("/");

divisionButton.setForeground(Color.red);

multiButton=new Button("*");

multiButton.setForeground(Color.red);

minusButton=new Button("-");

minusButton.setForeground(Color.red);

plusButton=new Button("+");

plusButton.setForeground(Color.red);

setLayout(new FlowLayout());

p1.setLayout(new FlowLayout());

p2.setLayout(new GridLayout(4,3));

p3.setLayout(new GridLayout(4,1));

p1.add(answerText);

p1.add(clearButton);

p2.add(pointButton);

p2.add(equalButton);

p3.add(plusButton);

p3.add(minusButton);

p3.add(multiButton);

p3.add(divisionButton);

add(p1);

add(p2);

add(p3);

}

public boolean action(Event e,Object o)

{

String s=new String("");

for(int i=0;i10;i++)

{

if(e.target==b[i]||e.target==pointButton)

{

if(e.target !=pointButton)

{

s=(String)o;

doForeText(s);

}

if((e.target==pointButton)(!isFloat))

{

isFloat=true;

s=(String)o;

if(foreText.equals(""))

{

foreText +="0.";

}

else

{

doForeText(s);

}

}

}

}

if(e.target==clearButton)

{

doClear();

}

if((e.target==clearButton)||(e.target==divisionButton)

||(e.target==plusButton)||(e.target==minusButton))

{

if(foreText !="")

{

currentOp=((String)o);

doOperator();

}

else

{

preOp=((String)o);

}

}

if(e.target==equalButton)

{

doOperator();

}

return true;

}

public void doOperator()

{

double dFore,dBack;

Double d;

if(preOp.equals(""))

{

backText=foreText;

foreText="";

answerText.setText(backText);

}

else

{

dFore=(new Double(foreText)).doubleValue();

dBack=(new Double(backText)).doubleValue();

foreText="";

backText=answerText.getText();

if(preOp.equals("+"))

{

d=new Double((dBack+dFore));

answerText.setText(d.toString());

backText=d.toString();

}

if(preOp.equals("-"))

{

d=new Double((dBack-dFore));

answerText.setText(d.toString());

backText=d.toString();

}

if(preOp.equals("*"))

{

d=new Double((dBack*dFore));

answerText.setText(d.toString());

backText=d.toString();

}

if(preOp.equals("/"))

{

if(dFore==0)

{

answerText.setText("除数不能为0");

return;

}

d=new Double((dBack/dFore));

answerText.setText(d.toString());

backText=d.toString();

}

}

preOp=currentOp;

}

public void doForeText(String s)

{

foreText +=s;

answerText.setText(foreText);

}

public void doBackText(String s)

{

backText=foreText;

foreText="";

answerText.setText(foreText);

}

public void doClear()

{

currentOp="";

preOp="";

foreText="";

backText="";

isFloat=false;

answerText.setText("");

}

}

急求!!!如何用java程序代码实现计算器界面

package jisuanqi_new;

import java.awt.*;

import java.awt.event.*;

public class JiSuanQi_new implements ActionListener

{

Panel p1;//声明面板p1

TextField t1;//声明文本行t1

String[] label = {"7","8","9","/","4","5","6","*","1","2","3","-","0",".","=","+"};//声明标签数组label1存放按钮上的标签

Button[] b;//声明按钮数组存放16个按钮

private int i;//声明i以备后用

private String op1 = "0";//运算数备用

private String operator = "+";//运算符备用

private boolean append = false;//备用

public JiSuanQi_new()//构造方法

{

t1=new TextField();//初始化文本行t1

b = new Button[label.length];//初始化按钮数组b

p1=new Panel();//初始化面板p1

p1.setLayout(new GridLayout(4,4,4,4));//使面板选择网格布局管理器以备储存16个按钮(4行4列)

for(int i=0;ib.length;i++)//利用for循环把标签放在按钮上,使每个按钮添加事件监听器,在面板p1上添加上16个按钮

{

b[i] = new Button(label[i]);//把标签依次放在16个按钮上

b[i].addActionListener(this);//使每个按钮添加动作事件监听器

p1.add(b[i]); //分别将按钮添加到面板p1上

}

Frame f=new Frame("计算器1.0");//初始化窗口f,起名字计算器1.0

f.setLayout(new BorderLayout());//为窗口选择边界布局管理器

f.add(BorderLayout.NORTH,t1);//把文本行他添加到窗口的北部

f.add(BorderLayout.CENTER,p1);//把面吧p1添加到窗口的中间

f.addWindowListener(new WindowAdapter(){//给窗口f添加窗口事件监听器

public void windowClosing(WindowEvent eve){//运行窗口关闭方法

System.exit(0);//退出程序

}

});

f.setSize(250, 250);//设置窗口大小

f.setLocation(200,200);

f.setVisible(true);//显示窗口

}

public static void main(String args[])

{

new JiSuanQi_new(); //调用构造方法

}

public void actionPerformed(ActionEvent ae)

{//按钮被操作发生

String comm = ae.getActionCommand();//返回与此动作相关的命令字符串,即:使用者第一次点击的按钮是什么。

if("0123456789".indexOf(comm)!=-1)//如果相关命令字符串为0~9之间的数字则执行

{

if(append){

String temp = t1.getText();//新数字

t1.setText(temp+comm);

}else{                         //因为此时append为false执行这个

t1.setText(comm); //将文本行t1设置为相关命令字符串(你按中的按钮代码)

append =  true;//此时append=true若继续按按钮若继续按数字的话1.第一次的按话不会改变2.非第一次按得话会覆盖之前按得数字(即缺点:只能进行单个数字的计算)

}

}

else if(("+-*/".indexOf(comm)!=-1))//如果相关命令字符串为+-*/之间的数字则执行

{

//保存

//t1.setText(comm);

op1 = t1.getText();//把第一个数赋值给op1

operator = comm;//把命令字符串赋值给operator

append = false;//此时append为false即若继续按按钮若按数字的话将重复上面的动作,按符号的话将覆盖之前的符号

}

else if("=".equals(comm))//如果按的是=号,则按条件进行下面的运算

{

String op2 = t1.getText();//op2第二个数

double d1 = Double.parseDouble(op1);

double d2 = Double.parseDouble(op2);

if(operator.equals("+")){

d1 = d1 + d2 ;

}else if(operator.equals("-")){

d1 = d1 - d2;

}else if(operator.equals("*")){

d1 = d1 * d2;

}else {

d1 = d1 / d2;

}

t1.setText(d1+"");//显示计算结果

append = false;

}

else if(".".equals(comm))//若是.号继续按

{

String temp = t1.getText();

if(temp.indexOf(".")==-1){

t1.setText(temp+".");

append = true;

}

}

}

}

如何用JAVA实现计算器界面

一个简单的计算器功能, 代码不是我写的,其实网上有很多这种例子,我只是整理了一下

package com.zhidao20161213;

import java.awt.BorderLayout;

import java.awt.GridLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JTextField;

public class JCalculator extends JFrame implements ActionListener {

/**

* Serial Version UID

*/

private static final long serialVersionUID = -169068472193786457L;

/**

* This class help close the Window.

* @author Singyuen Yip

*

*/

private class WindowCloser extends WindowAdapter {

public void windowClosing(WindowEvent we) {

System.exit(0);

}

}

int i;

// Strings for Digit  Operator buttons.

private final String[] str = { "7", "8", "9", "/", "4", "5", "6", "*", "1",

"2", "3", "-", ".", "0", "=", "+" };

// Build buttons.

JButton[] buttons = new JButton[str.length];

// For cancel or reset.

JButton reset = new JButton("CE");

// Build the text field to show the result.

JTextField display = new JTextField("0");

/**

* Constructor without parameters.

*/

public JCalculator() {

super("计算器");

// Add a panel.

JPanel panel1 = new JPanel(new GridLayout(4, 4));

// panel1.setLayout(new GridLayout(4,4));

for (i = 0; i  str.length; i++) {

buttons[i] = new JButton(str[i]);

panel1.add(buttons[i]);

}

JPanel panel2 = new JPanel(new BorderLayout());

// panel2.setLayout(new BorderLayout());

panel2.add("Center", display);

panel2.add("East", reset);

// JPanel panel3 = new Panel();

getContentPane().setLayout(new BorderLayout());

getContentPane().add("North", panel2);

getContentPane().add("Center", panel1);

// Add action listener for each digit  operator button.

for (i = 0; i  str.length; i++)

buttons[i].addActionListener(this);

// Add listener for "reset" button.

reset.addActionListener(this);

// Add listener for "display" button.

display.addActionListener(this);

// The "close" button "X".

addWindowListener(new WindowCloser());

// Initialize the window size.

setSize(800, 800);

// Show the window.

// show(); Using show() while JDK version is below 1.5.

setVisible(true);

// Fit the certain size.

pack();

}

public void actionPerformed(ActionEvent e) {

Object target = e.getSource();

String label = e.getActionCommand();

if (target == reset)

handleReset();

else if ("0123456789.".indexOf(label)  0)

handleNumber(label);

else

handleOperator(label);

}

// Is the first digit pressed?

boolean isFirstDigit = true;

/**

* Number handling.

* @param key

*            the key of the button.

*/

public void handleNumber(String key) {

if (isFirstDigit)

display.setText(key);

else if ((key.equals("."))  (display.getText().indexOf(".")  0))

display.setText(display.getText() + ".");

else if (!key.equals("."))

display.setText(display.getText() + key);

isFirstDigit = false;

}

/**

* Reset the calculator.

*/

public void handleReset() {

display.setText("0");

isFirstDigit = true;

operator = "=";

}

double number = 0.0;

String operator = "=";

/**

* Handling the operation.

* @param key

*            pressed operator's key.

*/

public void handleOperator(String key) {

if (operator.equals("+"))

number += Double.valueOf(display.getText());

else if (operator.equals("-"))

number -= Double.valueOf(display.getText());

else if (operator.equals("*"))

number *= Double.valueOf(display.getText());

else if (operator.equals("/"))

number /= Double.valueOf(display.getText());

else if (operator.equals("="))

number = Double.valueOf(display.getText());

display.setText(String.valueOf(number));

operator = key;

isFirstDigit = true;

}

public static void main(String[] args) {

new JCalculator();

}

}

高分求 用JAVA编写计算器界面(只要界面)代码!

package importantpg;

import java.awt.*;

import java.awt.event.*;

public class jisuanqi

{

TextArea tf=new TextArea(3,50 );

Button lb=new Button("clear");

Panel p1=new Panel();

Panel p2=new Panel();

public jisuanqi()

{ Frame f=new Frame("计算器");

Panel p=new Panel();

f.setBackground(Color.white);

f.setSize(500, 1500);

f.setVisible(true);

f.addWindowListener(new WindowAdapter()

{

public void windowClosing(WindowEvent e) {System.exit(1);}

});

Button[] b=new Button[18]; b[10]=new Button("-"); b[15]=new Button("(");

b[11]=new Button("+"); b[12]=new Button("*"); b[16]=new Button(")");

b[13]=new Button("/"); b[14]=new Button("="); b[17]=new Button("退格");

for(int i=0;i=9;++i)

{

b[i]=new Button(""+i);

}

p.setLayout(new GridLayout(6,3));

avent aa=new avent();

lb.addActionListener(aa);

for(int i=0;i18;++i)

{

p.add(b[i]);b[i].addActionListener(aa);

}

p1.setLayout(new BorderLayout());

p1.add(lb,"North");p1.add(tf,"South");f.add(p1, "South");

f.add(p,"Center"); f.pack();

} //构造方法

public static void main(String args[])

{

new jisuanqi();

}

class avent implements ActionListener //事件体

{

public void actionPerformed(ActionEvent e)

{

String s=null; String in="";

s=e.getActionCommand();

if (s!="="s!=nulls!="clear"s!="退格")

{

tf.append(s);

in+=s; s=null;

}

else if(s=="clear")

{

tf.replaceRange("",0,1000);

}else if(s=="=")

{

tf.append("="+jisuan(tf.getText()));

}

else if(s=="退格") {}

}///////////////////////////////////////////////事件处理方法

}

///////////////////////////////////////计算过程//////////////

static String jisuan(String s)

{

String hs= "";

char[] ch = new char[s.length()];

int top = -1;

for (int i = 0; i s.length(); i++)

{

char rsc = s.charAt(i);

switch(rsc)

{

case ' ' : break;

case '+' : //操作符

case '-' :

while (top = 0) //栈不为空时

{

char pc = ch[top--]; //pop Operator

if (pc == '(')

{

ch[++top] = pc; //push Operator

break;

}

else {hs = hs + pc;}

}

ch[++top] = rsc; //push Operator

hs += " ";break;

case '*' : //操作符

case '/' :

while (top = 0) //栈不为空时

{

char c = ch[top--]; //pop Operator

if (c == '(')

{

ch[++top] = c; //push Operator

break;

}

else

{

if (c == '+' || c == '-')

{

ch[++top] = c; //push Operator

break;

}

else

{

hs = hs + c;

}

}

}

ch[++top] = rsc; //push Operator

hs += " ";

break;

case '(' : //操作符

ch[++top] = rsc;

hs+= " ";

break;

case ')' : //操作符

while (top = 0) //栈不为空时

{

char c = ch[top--]; //pop Operator

if (c == '(')

{

break;

}

else

{

hs= hs + c;

}

}

hs += " ";

break;

default : //操作数

hs= hs + rsc;

break;

}//switch

}/////////////////////////////for

while (top = 0)

{

hs= hs + ch[top--]; //pop Operator

}

//System.out.println("hs="+hs); //后缀

//////////////////////////////////////////////后缀////////////////////////////////////

//后缀表达式计算

double[] result = new double[hs.length()];

double x, y;

top = - 1;

String st = "";

for (int i = 0; i hs.length(); i++)

{

char c = hs.charAt(i);

if ((c = '0' c = '9') || c == '.')

{

st += c;

}

if ((c == ' ' st != "") || i == hs.length() - 1)

{

result[++top] = Double.parseDouble(st) ; //push Operands

st = "";

}

if (c == '+' || c == '-' || c == '*' || c == '/')

{

if ((st != ""))

{

result[++top] =Double.parseDouble(st) ; //push Operands

st = "";

}

y = result[top--];

x = result[top--];

switch (c)

{

case '+' :

result[++top] = x+y;break;//push 中间结果再次入栈

case '-' :

result[++top] = x-y;break;

case '*' :

result[++top] = x*y;break;

case '/' :

result[++top] = x/y;break;

default :break;

}

}////////////////////if

} ///////////////////////for

return String.valueOf(result[top]); //pop 最终结果

} /////////////////////////jisuan

}

Java图形界面简单计算器

示例代码如下,请参考:

package test.com.test;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class Cal {

TextField tf = new TextField(40);       //显示文本框

StringBuffer s1 = new StringBuffer();   //记录运算数字,以及保留结果

StringBuffer s2 = new StringBuffer();   //记录运算数字,保留上一个输入的数字或运算结果

static String flag = new String();      //标记运算符号:+,-,*,/

boolean start = true;   //标记运算开始或结束,保证一次运算之后,第二次进行运算时能同时清空显示界面,即s1为空

public void init(){

//主界面

JFrame f = new JFrame("计算器");

JPanel p1 = new JPanel();

p1.add(tf);

f.add(p1,BorderLayout.NORTH);

JPanel p2 = new JPanel();

p2.setLayout(new GridLayout(1,3));

//动作监听器

ActionListener listen =new ActionListener() {

public void actionPerformed(ActionEvent arg0) {

//输入数字0~9

if(arg0.getActionCommand()=="0"){

if(!s1.toString().equals(new String())){

if(!start){

//s1清零,保证可以重新输入数字

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("0").toString());

}   

}

if(arg0.getActionCommand()=="1"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("1").toString());

}

if(arg0.getActionCommand()=="2"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("2").toString());

}

if(arg0.getActionCommand()=="3"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("3").toString());

}

if(arg0.getActionCommand()=="4"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("4").toString());

}

if(arg0.getActionCommand()=="5"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("5").toString());

}

if(arg0.getActionCommand()=="6"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("6").toString());

}

if(arg0.getActionCommand()=="7"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("7").toString());

}

if(arg0.getActionCommand()=="8"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("8").toString());

}

if(arg0.getActionCommand()=="9"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

tf.setText(s1.append("9").toString());

}

//输入小数点

if(arg0.getActionCommand()=="."){

if(!start){

s1.delete(0, s1.length());

}

start=true;

if(s1.toString().equals(new String()))

tf.setText(s1.append("0.").toString());

else if(s1.length()==1s1.charAt(0)=='-')

tf.setText(s1.append("0.").toString());

else

tf.setText(s1.append(".").toString());

}

//输入负号

if(arg0.getActionCommand()=="+/-"){

if(!start){

s1.delete(0, s1.length());

}

start = true;

if(s1.toString().equals(new String()))

tf.setText(s1.append('-').toString());

}

//退格Backspace

if(arg0.getActionCommand()=="Backspace"){

start = true;

if(s1.length()!=0){

//删除最后输入的一位

s1.deleteCharAt(s1.length()-1);

tf.setText(s1.toString());

}

}

//归零CE

if(arg0.getActionCommand()=="CE"){

//清空所有,start标记设为true

start = true;

s1.delete(0, s1.length());

s2.delete(0, s2.length());

tf.setText(s1.toString());

}

//清除C

if(arg0.getActionCommand()=="C"){

//清空当前输入,即s1清零

start = true;

s1.delete(0, s1.length());

tf.setText(s1.toString());

}

//加号

if(arg0.getActionCommand()=="+"){

start = true;

flag="+";

//s2接收s1的值

s2.append(String.valueOf(s1.toString()));

//s1清零,重新接收下一个数据

s1.delete(0, s1.length());

tf.setText(s1.toString());

}

//减号

if(arg0.getActionCommand()=="-"){

start = true;

flag="-";

s2.append(String.valueOf(s1.toString()));

s1.delete(0, s1.length());

tf.setText(s1.toString());

}

//乘号

if(arg0.getActionCommand()=="*"){

start = true;

flag="*";

s2.append(String.valueOf(s1.toString()));

s1.delete(0, s1.length());

tf.setText(s1.toString());

}

//除号

if(arg0.getActionCommand()=="/"){

start = true;

flag="/";

s2.append(String.valueOf(s1.toString()));

s1.delete(0, s1.length());

tf.setText(s1.toString());

}

//开根号

if(arg0.getActionCommand()=="sqrt"){

start =false;

double s=Double.parseDouble(s1.toString());

s1.delete(0, s1.length());

tf.setText(s1.append(String.valueOf(Math.sqrt(s))).toString());

}

//求%

if(arg0.getActionCommand()=="%"){

start =false;

double s=Double.parseDouble(s1.toString());

s1.delete(0, s1.length());

tf.setText(s1.append(String.valueOf(s/100)).toString());

}

//求1/x

if(arg0.getActionCommand()=="1/x"!s1.toString().equals(new String())Double.parseDouble(s1.toString())!=0){

start =false;

double s=Double.parseDouble(s1.toString());

s1.delete(0, s1.length());

tf.setText(s1.append(String.valueOf(1/s)).toString());

}

//求结果

if(arg0.getActionCommand()=="="s1.length()!=0s2.length()!=0){

//start标记为false

start =false;

//分别获取s1和s2的值

double s4=Double.parseDouble(s1.toString()); 

double s3=Double.parseDouble(s2.toString());

//清空s1和s2,便于开始下一次运算

s1.delete(0, s1.length());

s2.delete(0, s2.length());

//四则运算

if(flag=="+"){

tf.setText(s1.append(String.valueOf(s3+s4)).toString());

}

if(flag=="-"){

tf.setText(s1.append(String.valueOf(s3-s4)).toString());

}

if(flag=="*"){

tf.setText(s1.append(String.valueOf(s3*s4)).toString());

}

if(flag=="/"){

tf.setText(s1.append(String.valueOf(s3/s4)).toString());

}

}       

}

};

//添加按钮以及监听器

JButton bks = new JButton("Backspace");

bks.addActionListener(listen);

JButton ce = new JButton("CE");

ce.addActionListener(listen);

JButton c = new JButton("C");

c.addActionListener(listen);

p2.add(bks);

p2.add(ce);

p2.add(c);

f.add(p2);

JPanel p3 = new JPanel();

p3.setLayout(new GridLayout(4,5));

JButton b1 = new JButton("7");

p3.add(b1);

b1.addActionListener(listen);

JButton b2 = new JButton("8");

p3.add(b2);

b2.addActionListener(listen);

JButton b3 = new JButton("9");

p3.add(b3);

b3.addActionListener(listen);

JButton b4 = new JButton("/");

p3.add(b4);

b4.addActionListener(listen);

JButton b5 = new JButton("sqrt");

p3.add(b5);

b5.addActionListener(listen);

JButton b6 = new JButton("4");

p3.add(b6);

b6.addActionListener(listen);

JButton b7 = new JButton("5");

p3.add(b7);

b7.addActionListener(listen);

JButton b8 = new JButton("6");

p3.add(b8);

b8.addActionListener(listen);

JButton b9 = new JButton("*");

p3.add(b9);

b9.addActionListener(listen);

JButton b10 = new JButton("%");

p3.add(b10);

b10.addActionListener(listen);

JButton b11 = new JButton("1");

p3.add(b11);

b11.addActionListener(listen);

JButton b12 = new JButton("2");

p3.add(b12);

b12.addActionListener(listen);

JButton b13 = new JButton("3");

p3.add(b13);

b13.addActionListener(listen);

JButton b14 = new JButton("-");

p3.add(b14);

b14.addActionListener(listen);

JButton b15 = new JButton("1/x");

p3.add(b15);

b15.addActionListener(listen);

JButton b16 = new JButton("0");

p3.add(b16);

b16.addActionListener(listen);

JButton b17 = new JButton("+/-");

p3.add(b17);

b17.addActionListener(listen);

JButton b18 = new JButton(".");

p3.add(b18);

b18.addActionListener(listen);

JButton b19 = new JButton("+");

p3.add(b19);

b19.addActionListener(listen);

JButton b20 = new JButton("=");

p3.add(b20);

b20.addActionListener(listen);

f.add(p3,BorderLayout.SOUTH);

f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

f.pack();

f.setVisible(true);

}

public static void main(String args[]){

//调用方法,实现计算器

new Cal().init();

}

}


网站题目:用java计算器界面代码,java设计一个简单的计算器界面
本文URL:http://scyanting.com/article/dsghoid.html