Swing实现模仿HTML5模拟时钟特效

2023-05-16

  自从研究了Java Swing的Graphics,觉得能按照自己的想法画出一些东西,还是挺有意思的,之前学习Java Swing的时候练习过一个模拟时钟,自己觉得不错,后来看到这个html5 canvas实现的模拟时钟(HTML5 canvas超逼真的模拟时钟特效),瞬间觉得自己之前的实现弱爆了,这个真是漂亮,忍不住想用自己有限的Swing Graphics知识山寨一个。看下山寨后的效果图吧

基本是最终效果了
  这是mac的运行效果,虽然有点锯齿感,总体还行,比html5还是差不少,h5的有指针的阴影效果,看起来比较有立体感,h5的表盘数字位置也比较准确,这两方面还差点,还有刻度的圆角矩形比例什么的还差点。ubuntu linux运行后,锯齿感非常明显,可能显卡驱动不行吧,windows目前没运行。

在这里插入图片描述
可以看出ubuntu linux的锯齿感非常强,代码开启下抗锯齿试试看

在这里插入图片描述
omg, 看来是没有开启抗锯齿效果的原因,开启后效果立马提升了几个档次……坐标轴只是个参考可以去掉,最新代码解决了时间数字与刻度贴合不够近的问题,算是比较完善了。

  模仿实现思路如下:继承Jpanel重写paintComponent方法。

1.绘制表盘时间刻度

  这一圈刻度看起来像圆角矩形,只是大小、长短有所不同。

  • 方案1:使用的是圆角矩形RoundRectangle进行的实现,然而矩形默认只能水平或垂直,这时候就需要使用Graphics的rotate方法,将画布进行旋转,其实我觉得根本上来说,旋转的是画布中的坐标系,画布其实没转,一圈60个刻度,循环60次,每5个画一个略大的矩形即可。
  • 方案2:不需要调用rotate旋转,通过改变画笔线条的粗细(stroke)和线条末端的形状(end_round)即可,通过BasicStroke构造方法传递相应的参数实现。显然这种方法更为简单方便。代码示例如下(kotlin实现,java也是一样道理)
    var line: Line2D.Float
    val big = BasicStroke(10.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
    val small = BasicStroke(5.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
    for (i in 0 until 60) {
        var x1 = 0f
        var y1 = 0f
        var x2 = 0f
        var y2 = 0f
        if (i % 5 == 0) {
            x1 = (Math.cos(theta * i) * radiusLong).toFloat()
            y1 = (Math.sin(theta * i) * radiusLong).toFloat()
            x2 = (Math.cos(theta * i) * radiusEnd).toFloat()
            y2 = (Math.sin(theta * i) * radiusEnd).toFloat()
            line = Line2D.Float(x1,y1,x2,y2)
            g2.stroke = big
        } else {
            x1 = (Math.cos(theta * i) * (radiusLong+5)).toFloat()
            y1 = (Math.sin(theta * i) * (radiusLong+5)).toFloat()
            x2 = (Math.cos(theta * i) * radiusEnd).toFloat()
            y2 = (Math.sin(theta * i) * radiusEnd).toFloat()
            line = Line2D.Float(x1,y1,x2,y2)
            g2.stroke = small
        }
        g2.draw(line)
    }

  之前文章draw heart的时候,以为graphics的形状不支持浮点数,是自己当时所知有限了,graphics2d提供了基本所有形状的2D版本,既支持float还支持double。如Line2D,Rectangle2D,RoundRect2D,Arc2D,Ellipse2D等等,它们都实现了Shape接口。

  绘制刻度的时候,起始点其实是在x轴的正方向,也就是相当于3点钟方向,循环开始以后,是从这点顺时针开始绘制的,在swing graphics坐标系里面y轴的正方向是向下的,android里面也是这样,即使在windows里面也是,h5的canvas也是,看来这个在好多平台是统一的吧,研究了一下h5的代码实现,发现它在计算完y的值以后乘以了-1,也就是取反了,开始觉得很奇怪,在代码里面试了一下,发现这样相当于把y轴的正方向给改变为指向上方了,相当于变成了数学几何里面的那种标准平面直角坐标系,这样绘制的时候就是从3点钟,逆时针绘制了,殊途同归。下面是逆时针示例,顺时针看代码吧
在这里插入图片描述
  通过查看H5的js实现代码,发现并没有处理从三点钟后退90度的操作,内心一直对此存着疑问,突然想起自己的实现使用的是斜线与x轴夹角进行计算实现的,那么他可能用的是斜线与y轴夹角进行的实现,仔细看了下,确实如此。默认情况,这种实现是从6点钟方向逆时针绘制,但是他将y坐标的值进行了取反后,一下就变成了从12点钟进行顺时针绘制了,厉害。这个时候的斜线与圆的交点坐标(x, y)的计算方式就变了:
x = r ∗ s i n ( t ) x = r * sin(t) x=rsin(t)
y = r ∗ c o s ( t ) y = r * cos(t) y=rcos(t)
依然可以参考下图的坐标示意图,只是夹角变成了斜线与y轴的夹角。

2.绘制表盘时间数字

  主要是12个数字,分别对应于表盘上面的时间刻度,这个实现的时候需要考虑角度(弧度)的一个移动的问题,因为我们是从3点钟开始绘制的,如果不考虑这个问题,那就需要从3画到12,再画1,2。或者(顺时针实现方法)减去相应的度数,这样可以从1画到12。目前数字与刻度贴合的不够近…通过Graphics测量字符串宽度已经解决了

    var numRadius = radius * 0.9f
    g2.font = Font("", Font.PLAIN, 22)
    var fontMetrics = getFontMetrics(g2.font)
    //draw numbers
    var numTheta = 2 * Math.PI / 12
    for (i in 0..11) {
        var x1 = Math.cos(numTheta * i - Math.PI / 3) * numRadius
        var y1 = Math.sin(numTheta * i - Math.PI / 3) * numRadius
        //println("x1:$x1, y1:$y1")
        // 测量字符串宽度
        var num = (i + 1).toString()
        var strW = fontMetrics.stringWidth(num)
        g2.drawString(num, (x1 - strW / 2).toFloat(), y1.toFloat())
    }

3.绘制时间指针

  这个不同指针的先后顺序要注意,按照这个h5的效果,先画时针、分针、秒针,然后在它们上面还有覆盖的一个圆圈,秒针有一个尾巴超出圆圈的覆盖在另一侧露出来了,这个细节也要实现。这些实现后,定义时分秒三个变量,取系统当前的时间进行分别赋值,运行后即可实现时间指向。
  接着让时钟的指针动起来,需要创建一个Timer每一秒更新一次时间(启动一个线程也行),这样实现指针位置的变化。主要思路就是秒数或分钟数、小时数计算为对应的角度,这样计算出一个点的坐标,然后坐标原点(0,0)为另外一个点,在这两点进行drawLine即可,公式如下:
x = r ∗ c o s ( t ) x = r * cos(t) x=rcos(t)
y = r ∗ s i n ( t ) y = r * sin(t) y=rsin(t)
  下面这个图片中斜线与圆的交点的坐标(x,y)就是这样计算出来的,三条线围起来的三角形,斜线(相当于斜边,值为圆的半径)与x轴的夹角t的cos三角函数值的乘积就得到了交点的x值,同样斜线与t的sin的乘积可得到交点的y值。这样弧度从0到2PI,即可实现获取一圈的坐标点,一定要用弧度,角度有问题。这个画图软件不支持文字(其实是对ubuntu画图软件还不太熟),大致就是这么个效果。
在这里插入图片描述
  这个时间的分针和时针还有一个问题,就是H5这个实现是,秒针每走一次,分针都会相应变化的,而不是秒针走完一圈,分针一下从一个点指向下一个点,同理时针也是这个样子的。分针的实现是使用两个刻度之间的度数乘以当前(秒数/60),这个计算出来的度数加到分针的计算度数中即可实现,通过查看H5的js源代码发现,它不是这样实现的,它的分钟数是浮点数,分钟数 = 当前分钟数 + 当前秒数/60,这样也同样的实现了这个效果,殊途同归。时针也是一样的道理……

4.绘制时钟品牌名称

  在钟表的6点钟以上,圆心以下绘制了2行文字,大小不同,一个是品牌名称,一个是所属country,需要测量一下文字字符串的宽度,再绘制比较准确。

5.根据系统时间进行时间的动态更新

  可以使用Timer,每1000毫秒更新一次表盘的指针指向;也可以启动一个线程,sleep1000毫秒后通知ui线程更新表盘指针。

6.最终动态效果

  这个gif有闪烁,不是太优雅…又给它去掉了

在这里插入图片描述

  到这里山寨H5时钟的效果就全部结束了,虽然还有没完全模仿到的地方(比如指针的阴影效果,或许Android平台可以支持?下回分解吧),后续再研究吧(Swing Graphics路还很长),更多代码(有java实现)可以参考github:https://github.com/ximen502/SwingLearn

  这里给出kotlin的完整实现代码

/**
 * 第三版高仿H5模拟时钟部分代码优化
 */
class ClockFrameKt3 : JFrame() {
    init {
        val clockPanel = ClockPanel()
        add(clockPanel)
        clockPanel.start()
    }

    inner class ClockPanel : JPanel() {
        val secondHandColor = Color(0xf3, 0xa8, 0x29)
        val minuteHandColor = Color(0x22, 0x22, 0x22)
        val hourHandColor = Color(0x22, 0x22, 0x22)
        val markColor = Color(0x22, 0x22, 0x22)
        var hour = 0
        var minute = 0
        var second = 0

        override fun paintComponent(g: Graphics?) {
            super.paintComponent(g)
            var g2: Graphics2D = g as Graphics2D
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
            g2.translate(width / 2, height / 2)
            //drawAxis(g2)

            val theta = 2 * Math.PI / 60
            val radius = 150f
            val radiusLong = 164f
            val radiusEnd = 178
            g2.color = markColor
            var line: Line2D.Float
            val big = BasicStroke(10.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
            val small = BasicStroke(5.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
            for (i in 0 until 60) {
                var x1 = 0f
                var y1 = 0f
                var x2 = 0f
                var y2 = 0f
                val cost = Math.cos(theta * i)
                val sint = Math.sin(theta * i)
                // hour marker
                if (i % 5 == 0) {
                    x1 = (cost * radiusEnd * 0.90).toFloat()
                    y1 = (sint * radiusEnd * 0.90).toFloat()
                    x2 = (cost * radiusEnd).toFloat()
                    y2 = (sint * radiusEnd).toFloat()
                    line = Line2D.Float(x1,y1,x2,y2)
                    g2.stroke = big
                } else {
                    // minute marker
                    x1 = (cost * radiusEnd * 0.95).toFloat()
                    y1 = (sint * radiusEnd * 0.95).toFloat()
                    x2 = (cost * radiusEnd).toFloat()
                    y2 = (sint * radiusEnd).toFloat()
                    line = Line2D.Float(x1,y1,x2,y2)
                    g2.stroke = small
                }
                g2.draw(line)
            }

            var numRadius = radius * 0.9f
            g2.font = Font("", Font.PLAIN, 22)
            var fontMetrics = getFontMetrics(g2.font)
            //draw numbers
            var numTheta = 2 * Math.PI / 12
            for (i in 0..11) {
                var x1 = Math.cos(numTheta * i - Math.PI / 3) * numRadius
                var y1 = Math.sin(numTheta * i - Math.PI / 3) * numRadius
                //println("x1:$x1, y1:$y1")
                // 测量字符串宽度
                var num = (i + 1).toString()
                var strW = fontMetrics.stringWidth(num)
                g2.drawString(num, (x1 - strW / 2).toFloat(), y1.toFloat())
            }

            var font = Font("",Font.PLAIN, 14)
            var fontSmall = Font("",Font.PLAIN, 10)
            val brand = "北极星"
            val brandPlace = "亚洲"
            fontMetrics = getFontMetrics(font)
            var bW = fontMetrics.stringWidth(brand)
            g2.font = font
            g2.drawString(brand, 0 - bW / 2, radius.toInt() / 2)
            fontMetrics = getFontMetrics(fontSmall)
            var bpW = fontMetrics.stringWidth(brandPlace)
            g2.font = fontSmall
            g2.drawString(brandPlace, 0 - bpW / 2, radius.toInt() / 2 + 15)


            var x1 = 0f
            var y1 = 0f
            var x2 = 0f
            var y2 = 0f

            var hourTheta = 2 * Math.PI / 12
            //draw hour hand
            //修线条粗细
            var basicStroke = BasicStroke(20.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
            g2.stroke = basicStroke
            g2.color = hourHandColor
            /* hourTheta * (minute / 60f)分针变化对时针的影响 2pi/12*(minute/60) */
            x2 = radius * 0.75f * Math.cos(hourTheta * hour + hourTheta * (minute / 60f) - Math.PI / 2).toFloat()
            y2 = radius * 0.75f * Math.sin(hourTheta * hour + hourTheta * (minute / 60f) - Math.PI / 2).toFloat()
            var hourLine = Line2D.Float(x1, y1, x2, y2)
            g2.draw(hourLine)

            //println("second:$second, ${theta * (second / 60f)}")

            //draw minute hand
            basicStroke = BasicStroke(9.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
            g2.stroke = basicStroke
            g2.color = minuteHandColor
            /* theta * (second / 60f)秒针变化对分针的影响 //2pi/60 * (second/60)*/
            x2 = radiusLong * 1.0f * Math.cos(theta * (minute) + theta * (second / 60f) - Math.PI / 2).toFloat()
            y2 = radiusLong * 1.0f * Math.sin(theta * (minute) + theta * (second / 60f) - Math.PI / 2).toFloat()
            var minuteLine = Line2D.Float(x1, y1, x2, y2)
            g2.draw(minuteLine)

            //draw second hand
            basicStroke = BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
            g2.stroke = basicStroke
            g2.color = secondHandColor
            x2 = radiusLong * 1.08f * Math.cos(theta * (second) - Math.PI / 2).toFloat()
            y2 = radiusLong * 1.08f * Math.sin(theta * (second) - Math.PI / 2).toFloat()
            var secondLine = Line2D.Float(x1, y1, x2, y2)
            g2.draw(secondLine);

            //draw second tail handle
            basicStroke = BasicStroke(13.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)
            g2.stroke = basicStroke
            g2.color = secondHandColor
            x2 = radiusLong * 0.1f * Math.cos(theta * (second) - Math.PI / 2).toFloat()
            y2 = radiusLong * 0.1f * Math.sin(theta * (second) - Math.PI / 2).toFloat()
            secondLine = Line2D.Float(x1, y1, -x2, -y2)
            g2.draw(secondLine);

            // draw circle cover three hands
            var worh = 16f
            var circle = Ellipse2D.Float(0f - worh / 2f, 0f - worh / 2f, worh, worh)
            g2.draw(circle)

        }

        fun drawAxis(g: Graphics?) {
            var g2: Graphics2D = g as Graphics2D
            g2.stroke = BasicStroke(1.0f)
            g2.color = Color.BLACK
            g2.drawLine(-width / 2, 0, width / 2, 0)
            g2.drawLine(0, -height / 2, 0, height / 2)
            //unit=10,vertical line,x1,y1,x2,y2
            // short line, long line
            val sl = 5
            val ll = 10
            //x axis
            for (i in 0..width / 2 step 10) {
                if (i % 50 == 0) {
                    g2.drawLine(i, 0, i, -ll)
                    g2.drawLine(-i, 0, -i, -ll)
                } else {
                    g2.drawLine(i, 0, i, -sl)
                    g2.drawLine(-i, 0, -i, -sl)
                }
            }
            //println(height / 2)
            //y axis
            for (i in 0..height / 2 step 10) {
                if (i % 50 == 0) {
                    g2.drawLine(0, i, ll, i)
                    g2.drawLine(0, -i, ll, -i)
                } else {
                    g2.drawLine(0, i, sl, i)
                    g2.drawLine(0, -i, sl, -i)
                }
            }
        }

        override fun getPreferredSize(): Dimension {
            return Dimension(250, 250)
        }

        private fun setCurrentTime(hour: Int, minute: Int, second: Int) {
            this.hour = hour
            this.minute = minute
            this.second = second
            repaint()
        }

        fun start() {
            var c = 0
            var timer = Timer(1000) {
                val calendar = Calendar.getInstance()
                var hour = calendar.get(Calendar.HOUR_OF_DAY)
                var minute = calendar.get(Calendar.MINUTE)
                var second = calendar.get(Calendar.SECOND)
                setCurrentTime(hour % 12, minute, second)
            }
            timer.start()
        }
    }

    //转弧度
    fun toRadians(deg: Float): Float {
        return ((Math.PI / 180) * deg).toFloat();
    }

}

fun main(args: Array<String>) {
    var frame = ClockFrameKt3()
    frame.apply {
        setSize(500, 450)
        title = "Kotlin clock"
        setLocationRelativeTo(null) // Center the frame

        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        isVisible = true
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swing实现模仿HTML5模拟时钟特效 的相关文章

  • 【Android解决方案】在onResume里调用getIntent()得到的是上一次数据

    我有四个媒体分类 xff08 Record xff0c Music xff0c Video xff0c Picture xff09 xff0c 里面除了数据不同 xff0c 界面都是相似的 xff0c 所以我把它们用一个MediaActiv
  • pycharm运行停止快捷键

    运行 shift 43 f10 停止 ctrl 43 f2
  • RecyclerView预加载

    private boolean isLoadingMore 61 false 是否预加载 recyclerView addOnScrollListener new RecyclerView OnScrollListener 64 Overr
  • 自定义右侧弹出dialog并填充状态栏

    DialogUtil xff1a public class DialogUtil private Dialog dialog private View inflate public void showRightDialog Context
  • Android监听横竖屏切换

    偶然在项目中用到播放视频时 xff0c 需要横屏将视频全屏播放 xff0c 所以需要监听屏幕的横竖屏切换事件 ConfigChanges xff0c 用于捕获手机状态的改变 xff0c 当横竖屏切换 xff0c 屏幕尺寸变化 xff0c 弹
  • SVN利用 AS 进行代码对比的方法

    第 1 种 xff1a 如果我们是从 SVN 检出的项目 xff0c 并且想比较本地代码与从 SVN 检出时的代码相比都有那些区别 xff0c 可以按如下步骤操作 如上图所示 xff0c 在代码编辑区 xff0c 右键唤出功能菜单 xff0
  • ADB操作命令详解大全

    ADB 操作命令详解及用法大全 Lucas liu的博客 CSDN博客
  • Android Studio build下面找不见assembleDebug选项解决办法

    在开发Android的AAR库时 xff0c 习惯点击右侧gradle面板的Task任务进行编译 xff0c 如选择assembleDebug或assembleRelease进行编译 xff0c 如下 xff1a 说明 xff1a 其中as
  • android 注销到登陆界面实现

    code class java span class hljs keyword public span span class hljs class span class hljs keyword class span span class
  • 中兴2016校招软件在线笔试题

    面试经验可以参考我的另一篇文章 xff0c 是7月初参加openday面试的 xff0c 文章链接http blog csdn net dandelion1314 article details 47009585 招聘群里有人发的招聘时间安
  • 设置AndroidStudio左侧和右侧的字体

    1 File Settings Appearance amp Behavior Appearance xff0c 右边Override default fonts by not recommended 2 设置代码大小 xff1a File
  • Android下载网络资源文件

    直接上代码 xff1a lt uses permission android name 61 34 android permission WRITE EXTERNAL STORAGE 34 gt lt uses permission and
  • 出现:trying to draw too large(138078000bytes) bitmap:错误时

    这里就不翻译了 xff0c 意思就是说你将高分辨率图片放在了低分辨率文件夹下 例如 xff1a 图片的分辨率是属于xxhdpi的 xff0c 而你将这张图片放在了drawable xhdpi或者比这个还低的文件夹下 xff0c 就会报这个错
  • Android把图片压缩到一定大小并不失真

    本文转载只供参考 一 图片压缩方式 图片按比例大小压缩方法 64 param srcPath xff08 根据路径获取图片并压缩 xff09 64 return public static Bitmap getimage String sr
  • Android 动态设置TextView的位置

    RelativeLayout LayoutParams layoutParams 61 new RelativeLayout LayoutParams 40 40 宽高 layoutParams setMargins int dstX 20
  • 神经网络应用较多的算法,图卷积神经网络应用

    神经网络原理及应用 神经网络原理及应用1 什么是神经网络 xff1f 神经网络是一种模拟动物神经网络行为特征 xff0c 进行分布式并行信息处理的算法 这种网络依靠系统的复杂程度 xff0c 通过调整内部大量节点之间相互连接的关系 xff0
  • Java泛型学习

    纯属个人理解 xff0c 代码参考自视频 用途 xff1a 1 用于集合容器中 xff0c 可以使集合记住存储数据的类型 xff0c 防止频繁转换类型可能导致的ClassCastException 用于javac编译器的类型检查 xff0c
  • Java反射学习

    文字和代码来源于视频 反射 xff0c 通过它我们可以得到一个Java类的全部信息 xff0c 可以调用类的普通方法 xff0c 构造方法 xff0c 对类进行实例化 xff0c 操作类的属性 类中的所有内容 xff1a 属性 构造方法 普
  • 面试题之反转单向链表

    题目为 xff1a 将一个单向链表反转 xff0c 写出算法步骤或代码 懵批了 今学习如下 xff0c 文章代码参考https blog csdn net K346K346 article details 93371829 xff0c 感谢
  • 冒泡排序总结

    本文内容和代码均来自于 漫画算法 xff0c 小灰和大黄的对话 xff0c 非常有趣味的一本书 现理论结合实践 xff0c 做一下测试 span class token keyword private span span class tok

随机推荐

  • net6的Web MVC项目实现限流功能

    原理 xff1a 利用MemoryCache服务组件 xff0c 记录用户最后一次访问接口的时间 xff0c 如果本次访问距离最后一次访问不超过1秒 xff0c 提示用户访问过于频繁 xff0c 否则 xff0c 接口可以正常访问 然后利用
  • 快速排序总结

    文章内容和代码来自 漫画算法 和数据结构教材 现进行一下代码编写练习 1 双边循环法 span class token comment 双边循环法 xff0c 从左右两端分别向中间进行比较和交换数据 递归实现 span span class
  • 堆排序总结

    本文内容来源于 漫画算法 和数据结构教材 这里提到的堆是一个二叉堆 xff0c 本质上是一颗完全二叉树 堆排序只需要一个记录大小的辅助空间 1 java实现 span class token comment 下沉调整 64 param ar
  • 计数排序

    本文内容和代码来自 漫画算法 之前练习的冒泡排序 鸡尾酒排序 快速排序 堆排序都是基于元素比较和位置元素交换实现的 xff0c 有一些特殊的排序并不基于元素比较 xff0c 如计数排序 桶排序 基数排序 以计数排序来说 xff0c 这种排序
  • 桶排序

    本文内容和代码来源于 漫画算法 针对计数排序的局限性 xff0c 桶排序做出了弥补 xff0c 时间复杂度同样是线性级 类似于计数排序所创建的统计数组 xff0c 桶排序需要创建若干个桶来协助排序 那么桶排序中所谓的 桶 xff0c 又是什
  • 归并排序

    本文内容和代码来源于数据结构教材 归并排序 Merging Sort 是又一类不同的排序方法 34 归并 34 的含义是将2个或2个以上的有序表组合成1个新的有序表 无论是顺序存储还是链表存储结构 xff0c 都可在O m 43 n 的时间
  • 插入排序

    文章内容来源于数据结构教材 C语言版 教材讲解了4种插入排序算法 xff0c 分别为 1 直接插入排序 2 折半插入排序 3 2 路插入排序 4 表插入排序 还有一个希尔排序 属于插入排序分类 本文只将1 2 xff0c 两种算法进行了实践
  • 希尔排序

    本文内容来源于数据结构教材 C语言版 希尔排序 Shell s Sort xff0c 又称缩小增量排序 Diminishing Increment Sort xff0c 它也是一种属插入排序类的方法 xff0c 但在时间效率上较前几种插入排
  • Java swing绘制柱状图和饼图

    15 14编写程序 xff0c 使用条形图显示作业 平时测验 其中考试和期末考试占总成绩的百分比 假设作业占20 用红色显示 xff0c 平时测验占10 用蓝色显示 xff0c 其中考试占30 用绿色显示 xff0c 期末考试占40 用橙色
  • Java注解(Annotation)学习

    xff08 本文内容来源于疯狂Java讲义 xff0c 感谢 xff09 注解 Annotation Annotation是代码里的特殊标记 xff0c 这些标记可以在编译 类加载 运行时被读取 xff0c 并执行相应的处理 通过使用注解
  • Java Swing制作古老的打砖块游戏

    最近研究了一下古老的Java Swing xff0c 研究之余 xff0c 突发奇想开发了一个打砖块小游戏 首先看一下效果图 具体过程 1 游戏框架搭建1 1步骤 2 开发过程2 1各种游戏对象的绘制2 2游戏对象的运动2 3小球和砖块的碰
  • 局域网下yum代理配置

    需求背景 由于公司局域网内无法连接外网 xff0c 只有一台服务器能连接外网 xff0c 可选择搭建squid作为代理 xff0c 供无法访问外网的服务器 xff0c 安装软件使用 安装Squid yum install y squid 配
  • AndroidX迁移和吐槽

    最近引入一个第三方 xff0c 需要使用androidx扩展库 xff0c compile后发现与旧的support库无法兼容 xff0c 于是逐个的把support的库换成了androidx系列 xff0c 倒腾半天 xff0c 失败无数
  • Android中的事件

    有内容参考了别人的文章 xff0c 感谢作者 Input Events Event Listeners Event Handlers Touch Model Handling Focus https developer android co
  • Ubuntu19.10/20.04安装记录

    安装过程 官方网站下载 xff0c 搜索引擎搜索Ubuntu history version 找到19 10 xff0c 下载速度略慢 xff0c 大小大约2 3G 在Windows 上面使用UltraISO 试用版即可 刻录到u盘即可 重
  • android疑难问题收集

    1 自定义ViewGroup实现折叠展开 xff0c 离奇的折叠后又展开 在一个布局里面我参考网络代码实现了一个折叠展开的自定义viewgroup xff0c 其实是调用layout方法实现的折叠和展开 xff0c 最近出现一个bug xf
  • 开发错误笔记

    开发环境IDE Android Studio环境错误 1 布局引用的资源文件不存在的错误提示 Caused by android content res Resources NotFoundException Caused by org x
  • 程序员的送外卖经历

    今天我的一个朋友跟我发消息说 xff0c 看着外面刮着大风 xff0c 自己在屋子里面 xff0c 靠着暖气 xff0c 真是幸福啊 其实也没啥 xff0c 我这个朋友去年送了半年外卖 xff0c 大冬天依然在送 xff0c 户外骑着电动车
  • fragment添加失败错误查找

    根据源码查找原因 span class token class name Caused span by span class token operator span span class token class name span clas
  • Swing实现模仿HTML5模拟时钟特效

    自从研究了Java Swing的Graphics xff0c 觉得能按照自己的想法画出一些东西 xff0c 还是挺有意思的 xff0c 之前学习Java Swing的时候练习过一个模拟时钟 xff0c 自己觉得不错 xff0c 后来看到这个