写一点最近的东西。。。(是有多久没来了

ddl是第一生产力,此言不虚,ddl过后偶然想把一些东西mark down ,纪念最近ddl下支配的恐惧【哭笑】

界面近来一直用javafx来写,对fx的整体框架清晰了不少(特别是不依赖scene builder进行类似于swing的界面编写),主要说一下fx中图表的特点吧。


关于javafx画图

fx里的图表是基于一个个series来显示其中的内容,包括series下的数据和node(可以理解成一棵树,最上面是Group,下面可以放各种node),然后需要在chart的data中放入事先定义的series(当然series也有getData方法得到之前塞进去的数据,这些数据就是用来显示的)

chart.getData().add(series)

Data<String , Number> data = series.getData();

关于Data,构造方法最多只有3个参数,如果需要自定义比较复杂的显示,就把除了x,y值之外的东西打成一个Javabean放到第三个参数里,之后绘图的时候再取出来用(用fx自带的图表应该直接用就行了不像自己画得那么麻烦)

/**
         * Creates an instance of XYChart.Data object and initializes the X,Y
         * data values and extraValue.
         *
         * @param xValue The X axis data value.
         * @param yValue The Y axis data value.
         * @param extraValue Chart extra value.
         */
        public Data(X xValue, Y yValue, Object extraValue) {
            setXValue(xValue);
            setYValue(yValue);
            setExtraValue(extraValue);
            setCurrentX(xValue);
            setCurrentY(yValue);
            setCurrentExtraValue(extraValue);
        }

然后是关于创建图的执行顺序:
先是调用series的add方法,然后调用item的add方法把node塞进series,第一个series塞完后再add第二个series,以此类推。
然后等series塞完后更新坐标轴范围,调用updateAxisRange方法,这个不一定要重写看需要吧。
最后调用layoutPlotChildren方法,相当于是在画布上设置一个个node的位置把它画出来,算是显示最关键的一步。

@Override
        protected void dataItemAdded(Series<String, Number> series,
                int itemIndex, Data<String, Number> item) {

            Node candle = creatNode(item);
            getPlotChildren().add(candle);
        }

        @Override
        protected void dataItemRemoved(Data<String, Number> item,
                Series<String, Number> series) {

        }

        @Override
        protected void dataItemChanged(Data<String, Number> item) {

        }

        @Override
        protected void seriesAdded(Series<String, Number> series,
                int seriesIndex) {
            if(seriesIndex == SPECTIALINDEX)
                for (Data item : series.getData()) {

                    Node kNode = creatNode(item);

                    getPlotChildren().add(kNode);

                }

            }

            else {

                Path path = new Path();

                series.setNode(path);

                getPlotChildren().add(path);

            }

        }


        @Override
        protected void seriesRemoved(Series<String, Number> series) {

            Path path = (Path) series.getNode();

            path.setVisible(false);

        }
        @Override
        protected void layoutPlotChildren() {
            if (getData() == null) {

                return;

            }
            .......(略过)
        }

        @Override
         protected void updateAxisRange() {
            ........
         }

继承XYChart的自定义图表需要实现series的增删方法和series中item 的增删改方法(必须有series增加和item增加啊不然没东西显示)。当然还有layoutPlotChildren。一般自己动手画也就是把一些元素组合起来,比如k线图就是各类path再加bar(Region),然后bar上加一条线(Line)。PS:也是参考demo的。


关于lambda表达式

算是尝试着在java中用lambda写点东西,特别是双目符号(::)的使用(java中应该也叫这个吧)顿时feel到了c++的函数指针用法。


一般在fx的initialize方法中设定对应关系都会用lambda表达式

peColumn.setCellValueFactory(cell -> newSimpleDoubleProperty(cell.getValue().pe));

pbColumn.setCellValueFactory(cell -> new SimpleDoubleProperty(cell.getValue().pb));

参数和返回值的对应关系。。我暂时这样理解。在做监听的时候也省去了匿名内部类

choiceBox.getSelectionModel().selectedItemProperty()
    .addListener((observable, oldValue, newValue) -> {
                    calculate();
                });

类似的还用过lambda写线程等等,应用的方面挺多。


调用逻辑层方法的遇到了一个问题,一些接口的参数列表和返回值都是相同的,比如根据起始终止条件得到一个Collection<…>。每次判断再显式调用方法就显得很冗余,扩展性不好。于是就试着用::

interface MACDSource {
        Collection<MacdVO> getData(String stockCode, LocalDate startDate,
                LocalDate endDate) throws NetworkConnectionException;
    }

    /**
     * 获得MACD数据
     */
    private void getMACDData(LocalDate startDate, LocalDate endDate,
            MACDSource source) {
        Collection<MacdVO> macdVOs = null;
        try {
            macdVOs = source
                    .getData(stockVO.getStockCode(), startDate, endDate);
        } catch (NetworkConnectionException e) {
            new NetExceptionTips("Please check the net");
            e.printStackTrace();
        }
        ...
    }

逻辑层的接口

/**

     ...
     */
    Collection<MacdVO> getMacdD(String stockCode, LocalDate begin, LocalDate end) throws NetworkConnectionException;
    Collection<MacdVO> getMacdW(String stockCode, LocalDate begin, LocalDate end) throws NetworkConnectionException;
    Collection<MacdVO> getMacdM(String stockCode, LocalDate begin, LocalDate end) throws NetworkConnectionException;

声明的interface里只有一个方法,保证参数列表和返回值和需要实际调用的方法相同。这样,就可以把传入这个接口,把接口当成一个函数指针,用::的方式表明这个地方传入的是哪个函数的“指针”

getMACDData(beginDate, endDate, stockAnalysis::getMacdW);

getMACDData(beginDate, endDate, stockAnalysis::getMacdD);

这样就算之后有变动也好处理很多。


    anyway,暂时想到这些。然后,身体最重要,远离ddl。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值