class WeatherApp : App(WeatherView::class) class WeatherView : View("十五每天氣預報") { val weatherVM: WeatherViewModel by inject() val controller: WeatherController by inject() var hdata: XYChart.Series<String, Number> by singleAssign() var ldata: XYChart.Series<String, Number> by singleAssign() override val root = borderpane { bottom = hbox(4) { progressbar(controller.taskProgress) label(controller.taskMessage) visibleWhen { controller.taskRunning } paddingAll = 4 } left = vbox(4) { // button("refresh") { // action { // controller.refresh() // } // } textfield(weatherVM.city) listview(controller.cities) { bindSelected(weatherVM.city) onUserSelect(1) { controller.refresh() } } } center = tableview(controller.weathers) { column("date", Weather::dateProperty) column("type", Weather::typeProperty) column("高溫℃", Weather::highProperty) column("低溫℃", Weather::lowProperty) column("風向", Weather::fxProperty) bindSelected(weatherVM) smartResize() } right = linechart("十五每天氣預報", CategoryAxis(), NumberAxis()) { id="lc" prefWidth=600.0 // 設置成false可避免在第一次顯示數據時,x軸的下標堆積在一塊兒 animated=false series("高溫") { hdata = this } series("低溫") { ldata = this } } } } class WeatherController : Controller() { val api: Rest by inject() val weathers = observableListOf<Weather>() val cities = observableListOf<String>() val weatherVM: WeatherViewModel by inject() val v: WeatherView by inject() val taskRunning = booleanProperty() val taskMessage = stringProperty() val taskProgress = doubleProperty() fun refresh() { v.title = weatherVM.city.value.split(",").first().plus(" 將來十五每天氣預報") val t = task { loadWeathers(weatherVM.city.value.toString().split(",").last()) updateMessage("Loading weathers") updateProgress(0.4, 1.0) } t.run() taskRunning.bind(t.runningProperty()) taskMessage.bind(t.messageProperty()) taskProgress.bind(t.progressProperty()) } // 文件中讀取城市列表 // fun loadCities1() = GlobalScope.launch { // cities.clear() // // 使用hutool的FileUtil工具類,可正常讀取resources下的資源文件 //// FileUtil.readLines("city.csv", "gbk").forEach { //// cities.add(it) //// } // // // 使用tornadofx框架的resources沒法讀取文件內容,緣由不明 //// File(resources.url("city.csv").toExternalForm()).readLines().forEach { //// cities.add(it) //// } // // File(javaClass.getResource("/city.csv").toURI()).readLines().forEach { // cities.add(it) // } // } // 從文件中讀取城市名稱及其代碼數據,填充到listview中 fun loadCities() { cities.clear() run { File(javaClass.getResource("/city.csv").toURI()).readLines().forEach { cities.add(it) } } } // citykey:城市ID,如:"101030100" fun loadWeathers(citykey: String) { // 更新前清空數據 weathers.clear() v.hdata.data.clear() v.ldata.data.clear() // 安徽 101030100 val json = api.get(citykey).one() val dates = JsonPath.read(json.toString(), "$.data.forecast[*].ymd") as List<String> val types = JsonPath.read(json.toString(), "$.data.forecast[*].type") as List<String> val city = JsonPath.read(json.toString(), "$.cityInfo.city") as String val time = JsonPath.read(json.toString(), "$.time") as String val quality = JsonPath.read(json.toString(), "$.data.quality") as String val wendu = JsonPath.read(json.toString(), "$.data.wendu") as String val shidu = JsonPath.read(json.toString(), "$.data.shidu") as String val pm25 = JsonPath.read(json.toString(), "$.data.pm25") as Double val pm10 = JsonPath.read(json.toString(), "$.data.pm10") as Double val highs = JsonPath.read(json.toString(), "$.data.forecast[*].high") as List<String> val lows = JsonPath.read(json.toString(), "$.data.forecast[*].low") as List<String> val fxs = JsonPath.read(json.toString(), "$.data.forecast[*].fx") as List<String> dates.indices.forEach { val w = Weather() w.date = dates[it] w.type = types[it] w.fx = fxs[it] w.city = city w.quality = quality w.time = time w.high = highs[it].split(" ").last().trimEnd('℃') w.low = lows[it].split(" ").last().trimEnd('℃') weathers.add(w) val date = dates[it].split("-").drop(1).joinToString("/") v.hdata.data(date, w.high.toInt()) { node.add(Text(w.high)) node.tooltip(w.type) // Tooltip.install(node, Tooltip(w.high)) } v.ldata.data(date, w.low.toInt()) { node.add(Text(w.low)) } } // 經過控件id 找到要操做的控件 (primaryStage.scene.lookup("#lc") as LineChart<String,Number>).title=v.title // (v.root.right as LineChart<String,Number>).title=v.title v.title+=" 當前天氣:$quality, 更新時間:$time, 溫度:$wendu, 溼度:$shidu, pm25:$pm25, pm10:$pm10" // read(json, "$.store.book[*].author") // val d=json.get("data") // val forecast= JSONUtil.parseObj(d).get("forecast") // println(forecast.toString()) // println(JSONUtil.parseObj().get("ymd")) // weathers.addAll(api.get("101030100").list().toModel()) } fun loadWeathers1(citykey: String) { weathers.clear() // 此方法沒法正確獲得想要的數據 weathers.addAll(api.get(citykey).list().toModel()) } init { api.baseURI = "http://t.weather.sojson.com/api/weather/city/" loadCities() } } class Weather : JsonModel { val cityProperty = stringProperty("") var city by cityProperty val dateProperty = stringProperty() var date by dateProperty val typeProperty = stringProperty() var type by typeProperty val timeProperty = stringProperty() var time by timeProperty val highProperty = stringProperty() var high by highProperty val lowProperty = stringProperty() var low by lowProperty val shiduProperty = stringProperty("34%") var shidu by shiduProperty val qualityProperty = stringProperty("良") var quality by qualityProperty val wenduProperty = stringProperty("16") var wendu by wenduProperty val fxProperty = stringProperty("西風") var fx by fxProperty override fun toString() = "$city" override fun updateModel(json: JsonObject) = with(json) { } } class WeatherViewModel : ItemViewModel<Weather>() { val city = bind(defaultValue = "") { item?.cityProperty } val type = bind { item?.typeProperty } val date = bind{ item?.dateProperty } val time = bind { item?.timeProperty } val high = bind { item?.highProperty } val low = bind { item?.lowProperty } val fx = bind { item?.fxProperty } val quality = bind { item?.qualityProperty } }