您的位置:

首页 >

软件编程 >

利用JavaFX工具构建Reactive系统 >

利用JavaFX工具构建Reactive系统

2016-04-19 03:13:11

分类:软件编程

JavaFX 是Java中用来构建图形应用程序的新的标准库, 但许多程序员仍然坚持在使用Swing甚至AWT。关于如何利用JavaFX工具集中的新的超棒特性来构建响应式的快速应用程序,这里有一些建议!1. 属性值如果你对JavaFX组件做过完整的了解,移动遇到过属性(Property)这个东西。FX库中几乎每个值都可以被观察,分区(divider)的宽度,图片的尺寸,文本标识(label)中的文字,一个列表中的子项以及复选框(checkbox)的状态。属性分成另类:可写属性和可读属性。可写值可以被修改,使用设置器方法或者直接修改。 JavaFX 会处理事件处置过程并确保每个依赖于此属性的组件都会被通知到。可读属性拥有能让你在其值被修改时接收到通知的方法。示例:// 可读-且可写StringProperty name = new SimpleStringProperty("Emil"); // 只读ObservableBooleanValue nameIsEmpty = name.isEmpty();2. 绑定值当你拥有一个可写和可读值的时候,你可以开始就这些值如何关联定义规则。一个可写属性可以被绑定到一个可读属性,如此其值总是会匹配到可读的这个。绑定并不会立即发生,不过它们会在值被观察之前进行(看看我在那里做的就明白了)。 绑定可以是单向或者双向的。当然,如果它们之间是双向的,就需要两个属性都是可写的。示例:TextField fieldA = new TextField();TextField fieldB = new TextField();fieldA.prefWidthProperty().bind(fieldB.widthProperty());3. 可观察的列表属性并不是唯一可以被观察的东西。如果列表是被封装到了一个 ObservableList 中,那么列表的成员同样也是可以被观察到的。ObservableList 的响应模型是相当先进的。你不仅能在列表被修改时收到通知,也可以看到列表具体是如何被修改的。示例:List<String> otherList = Arrays.asList("foo", "bar", "bar");ObservableList<String> list = FXCollections.observableList(otherList);list.addListener((ListChangeListener.Change<? extends String> change) -> { System.out.println("Received event."); while (change.next()) { if (change.wasAdded()) { System.out.println( "Items " + change.getAddedSubList() + " was added."); } if (change.wasRemoved()) { System.out.println( "Items " + change.getRemoved() + " was removed."); } }});System.out.println("Old list: " + list);list.set(1, "foo");System.out.println("New list: " + list);上面代码的运行输出如下:Old list: [foo, bar, bar]Received event.Items [foo] was added.Items [bar] was removed.New list: [foo, foo, bar]如你所见,设置操作只会触发一次事件。4. StringConverter有时你会发现自己要创建一个绑定时无需去提取一个组件中的值。 这个的典型示例就是你有了一个从一个文本域(TextField)获取到的带有path 的 StringProperty。如果你想要有一个带有表示为Path的这个值的可观察属性,就需要去为它创建一个StringConverter。示例:TextField fileLocation = new TextField();StringProperty location = fileLocation.textProperty();Property<Path> path = new SimpleObjectProperty<>(); Bindings.bindBidirectional(location, path, new StringConverter<Path>() { @Override public String toString(Path path) { return path.toString(); } @Override public Path fromString(String string) { return Paths.get(string); }});对象属性并不是跟文本域的值进行的双向绑定。5. Expressions使用上述的 Bindings类,你可以创建出任何类型的表达式。比如说你有了两个可以让用户输入信息的文本域。现在想要定义一个只读域,其中总是会包含一个字符串,如果两个串的长度相等,将会是两个串逐个字符间隔混在一起进行显示。如果长度不等,则显示一条帮助信息。示例:TextField first = new TextField();TextField second = new TextField();TextField mix = new TextField(); mix.textProperty().bind( Bindings.when( first.lengthProperty().isEqualTo(second.lengthProperty()) ).then(Bindings.createStringBinding( () -> { int length = first.lengthProperty().get(); String firstText = first.textProperty().get(); String secondText = second.textProperty().get(); char[] result = new char[length * 2]; for (int i = 0; i < length; i++) { result[i * 2] = firstText.charAt(i); result[i * 2 + 1] = secondText.charAt(i); } return new String(result); }, first.textProperty(), second.textProperty() )).otherwise("Please enter two strings of exactly the same length."));这里只是JavaFX诸多特性的其中一点点。希望你可以找到更多利用这个事件系统的创造性方式!

前两天在项目中因为要通过http请求获取一个比较大的json数据(300KB左右)并且保存,思来想去,最后还是决定将获取到的json数据以文件的形式保存下来,每次使用的时候去读取文件就可以了。废话不多说了,直接上代码。以下是代码截图,文章结尾会有完成的代码文件可供下载。创建文件方法:写入文件内容方法:删除文件方法:测试:关于文件创建,写入内容,删除。可以根据自己的情况再稍作修改。以下是代码类。package com.file.run;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.util.UUID;/** * @author 夕橘子-O* @version 2016年7月8日 上午10:38:49 */public class ForFile {//生成文件路径private static String path = "D:\\file\\";//文件路径+名称private static String filenameTemp;/*** 创建文件* @param fileName 文件名称* @param filecontent 文件内容* @return 是否创建成功,成功则返回true*/public static boolean createFile(String fileName,String filecontent){Boolean bool = false;filenameTemp = path+fileName+".txt";//文件路径+名称+文件类型File file = new File(filenameTemp);try {//如果文件不存在,则创建新的文件if(!file.exists()){file.createNewFile();bool = true;System.out.println("success create file,the file is "+filenameTemp);//创建文件成功后,写入内容到文件里writeFileContent(filenameTemp, filecontent);}} catch (Exception e) {e.printStackTrace();}return bool;}/*** 向文件中写入内容* @param filepath 文件路径与名称* @param newstr 写入的内容* @return* @throws IOException*/public static boolean writeFileContent(String filepath,String newstr) throws IOException{Boolean bool = false;String filein = newstr+"\r\n";//新写入的行,换行String temp = "";FileInputStream fis = null;InputStreamReader isr = null;BufferedReader br = null;FileOutputStream fos = null;PrintWriter pw = null;try {File file = new File(filepath);//文件路径(包括文件名称)//将文件读入输入流fis = new FileInputStream(file);isr = new InputStreamReader(fis);br = new BufferedReader(isr);StringBuffer buffer = new StringBuffer();//文件原有内容for(int i=0;(temp =br.readLine())!=null;i++){buffer.append(temp);// 行与行之间的分隔符 相当于“\n”buffer = buffer.append(System.getProperty("line.separator"));}buffer.append(filein);fos = new FileOutputStream(file);pw = new PrintWriter(fos);pw.write(buffer.toString().toCharArray());pw.flush();bool = true;} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}finally {//不要忘记关闭if (pw != null) {pw.close();}if (fos != null) {fos.close();}if (br != null) {br.close();}if (isr != null) {isr.close();}if (fis != null) {fis.close();}}return bool;}/*** 删除文件* @param fileName 文件名称* @return*/public static boolean delFile(String fileName){Boolean bool = false;filenameTemp = path+fileName+".txt";File file = new File(filenameTemp);try {if(file.exists()){file.delete();bool = true;}} catch (Exception e) {// TODO: handle exception}return bool;}public static void main(String[] args) {UUID uuid = UUID.randomUUID();createFile(uuid+"myfile", "我的梦说别停留等待,就让光芒折射泪湿的瞳孔,映出心中最想拥有的彩虹,带我奔向那片有你的天空,因为你是我的梦 我的梦");}}以上所述是小编给大家介绍的Java创建文件且写入内容的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

Java 中实例化类的动作,你是否还是一成不变 new 对应对象呢?    经手的项目多了,代码编写量自然会增加,渐渐的会对设计模式产生感觉。    怎样使书写出来的类实例化动作,高内聚,低耦合,又兼具一定的扩展能力呢?    本文试图从几段鲜活的代码入手,给大家呈现不一样的 Java 实例化类。    下面代码取自 com.google.zxing 源码实现:public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType, ?> hints) throws WriterException { Object writer; switch(format.ordinal()) { case 1: writer = new AztecWriter(); break; case 2: writer = new CodaBarWriter(); break; case 3: writer = new Code39Writer(); break; case 4: case 10: case 13: case 14: default: throw new IllegalArgumentException("No encoder available for format " + format); case 5: writer = new Code128Writer(); break; case 6: writer = new DataMatrixWriter(); break; case 7: writer = new EAN8Writer(); break; case 8: writer = new EAN13Writer(); break; case 9: writer = new ITFWriter(); break; case 11: writer = new PDF417Writer(); break; case 12: writer = new QRCodeWriter(); break; case 15: writer = new UPCAWriter(); break; case 16: writer = new UPCEWriter(); } return ((Writer)writer).encode(contents, format, width, height, hints); }其中的 BarcodeFormat 是这样的:public enum BarcodeFormat { AZTEC, CODABAR, CODE_39, CODE_93, CODE_128, DATA_MATRIX, EAN_8, EAN_13, ITF, MAXICODE, PDF_417, QR_CODE, RSS_14, RSS_EXPANDED, UPC_A, UPC_E, UPC_EAN_EXTENSION; private BarcodeFormat() { }}源码提供的功能是将信息通过几种不同类型条形码 Wirter 输出为位矩阵,然后输出到图片上面,形成随处可见的各种类型的条形码。BitMatrix bitMatrix = new MultiFormatWriter().encode(_text, BarcodeFormat.QR_CODE, qrcodeWidth, qrcodeHeight, hints);MatrixToImageWriter.writeToFile(bitMatrix, qrcodeFormat, QrcodeFile);源码作者在这里使用了JDK 1.5  中引入的新特性 enum 枚举类,编写了BarcodeFormat类,其中定义了不同类型的条形码的属性。调用 MultiFormatWriter.encode()  根据入参 BarcodeFormat.xx 在枚举类中的序号,来实例化具体的类。 switch(format.ordinal()) { case 1: writer = new AztecWriter(); break; case 2: writer = new CodaBarWriter(); break; case 3: writer = new Code39Writer(); break; ...............这些条形码 Writer 类,同时都实现了抽象接口 Writer 的 两个encode()方法。public interface Writer { BitMatrix encode(String var1, BarcodeFormat var2, int var3, int var4) throws WriterException; BitMatrix encode(String var1, BarcodeFormat var2, int var3, int var4, Map<EncodeHintType, ?> var5) throws WriterException;} 具体的条形码 Wirter 类内部根据不同类型的条形码规则,进行不同的逻辑。使用者不需要过多的关注内部的实现,需要产生什么样子的条形码,入参选用合适的条形码类型即可,笔者上述的例子里面实现的是二维码。      在来看经典 MVC 框架 Webwork 动态实例化类的一段方法代码: private static Configuration getDefaultConfiguration () { if (defaultImpl == null) { defaultImpl = new DefaultConfiguration(); try { String className = getString("webwork.configuration"); if (!className.equals(defaultImpl.getClass().getName())) { try { defaultImpl = (Configuration) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className)); } catch (Exception e) { LOG.error("Could not instantiate configuration", e); } } return defaultImpl; } catch (IllegalArgumentException localIllegalArgumentException) { } } }源码取自 webwork-core,可能很多看客老爷没有听闻 Webwork, 但是对 Struts 应该是如雷贯耳,Struts2 核心改写自 Webwork。上述源码提供的功能为实例化用户自己定义的 配置文件读取类,该定义是在配置文件当中。源码作者在这里使用 Thread.currentThread().getContextClassLoader().loadClass(className) 线程中类加载器,动态实例化自定义配置文件读取类,可谓是效率最高的一种做法。类加载器的委托链:SystemClassloader -> ExtensionClassloader -> BootstrapClassloader 委派链左边的ClassLoader就可以很自然的使用右边的ClassLoader所加载的类,类加载的机制为判断自已是否加载该类,没有在询问上级。而这三个类加载器分别对应着编译器去寻找类文件的优先级别和不同的路径: BootClassLoader  它是用C++编写的,从%jre%/lib目录中加载类,或者运行时用-Xbootclasspath指定目录来加载。是编译器最优先寻找class的地方 ExtClassLoader  从%jre%/lib/ext目录加载类,或者运行时用-Djava.ext.dirs制定目录来加载。是编译器次优先寻找class的地方 SystemClassloader 也就是我们常说的AppClassloader ,它对应当前路径,所以也是编译器默认找class的地方。平时项目中使用的 Class.forname() 会从 BootstrapClassloader 开始询问,是最消耗资源的。源码作者在这里采用线程类加载器,对应为 SystemClassloader ,效率无疑是最高的。

通常我们用惯的ListView每一项的布局都是相同的,只是控件所绑定的数据不同。但单单只是如此并不能满足我们某些特殊需求,比如我们常见的QQ、微信的聊天列表,除了有左右之分外,内容更是有很大区别,有文字、语音、图片、视频等等,他们真的是ListView可以实现的吗?答案是肯定的,只要我们做一下类型区别即可。实现效果如下所示:    大家不要在意布局,这里为了方便就随意了。大家可以看到,这里有两种布局,一种头像在左,一种头像在右,虽然这是一种简单的情况,但我们只需要了解其中的原理,再复杂的情况都可以迎刃而解。我们只要将每一种布局划为一种类型进行区分,根据我们所区分的类型在我们自定义的Adapter中加载不同布局即可,代码如下所示:if (bean.getType() == 1) { convertView = mInflater.inflate(R.layout.item_chat_left, null); holder.mIvAvatar = (ImageView) convertView.findViewById(R.id.iv_chatLeftItem_avatar); holder.mTvContent = (TextView) convertView.findViewById(R.id.tv_chatLeftItem_content); } else if (bean.getType() == 2) { convertView = mInflater.inflate(R.layout.item_chat_right, null); holder.mIvAvatar = (ImageView) convertView.findViewById(R.id.iv_chatRightItem_avatar); holder.mTvContent = (TextView) convertView.findViewById(R.id.tv_chatRightItem_content); } 是不是发现很简单,最后,我再将所有代码一同贴出来。item_chat_left.xml<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="6dp" > <ImageView android:id="@+id/iv_chatLeftItem_avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#dd00f0" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tv_chatLeftItem_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:padding="16dp" android:layout_toRightOf="@id/iv_chatLeftItem_avatar" android:background="@drawable/qfav_list_bubble_nor" android:layout_marginRight="64dp" android:gravity="center_vertical" /> </RelativeLayout> item_chat_right.xml<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="6dp" > <ImageView android:id="@+id/iv_chatRightItem_avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:background="#ddf000" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tv_chatRightItem_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:padding="16dp" android:layout_toLeftOf="@id/iv_chatRightItem_avatar" android:background="@drawable/skin_aio_user_bubble_pressed" android:layout_marginLeft="64dp" android:gravity="center_vertical" /> </RelativeLayout> activity_chat.xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <ListView android:id="@+id/lv_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none" android:divider="@null" android:listSelector="@android:color/transparent" > </ListView> </RelativeLayout> ChatItemBean.javaimport android.graphics.Bitmap; public class ChatItemBean { private int type; private String content; private Bitmap avatar; public int getType() { return type; } public void setType(int type) { this.type = type; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Bitmap getAvatar() { return avatar; } public void setAvatar(Bitmap avatar) { this.avatar = avatar; } } ChatLVAdapter.javaimport java.util.List; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class ChatLVAdapter extends BaseAdapter { private List<ChatItemBean> mDatas; private LayoutInflater mInflater; public ChatLVAdapter(Context context, List<ChatItemBean> datas) { this.mInflater = LayoutInflater.from(context); this.mDatas = datas; } @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; ChatItemBean bean = mDatas.get(position); if (convertView == null) { holder = new ViewHolder(); if (bean.getType() == 1) { convertView = mInflater.inflate(R.layout.item_chat_left, null); holder.mIvAvatar = (ImageView) convertView.findViewById(R.id.iv_chatLeftItem_avatar); holder.mTvContent = (TextView) convertView.findViewById(R.id.tv_chatLeftItem_content); } else if (bean.getType() == 2) { convertView = mInflater.inflate(R.layout.item_chat_right, null); holder.mIvAvatar = (ImageView) convertView.findViewById(R.id.iv_chatRightItem_avatar); holder.mTvContent = (TextView) convertView.findViewById(R.id.tv_chatRightItem_content); } convertView.setTag(holder); } else { // 通过tag找到缓存的布局 holder = (ViewHolder) convertView.getTag(); } holder.mIvAvatar.setImageBitmap(bean.getAvatar()); holder.mTvContent.setText(bean.getContent()); return convertView; } public final class ViewHolder { public ImageView mIvAvatar; public TextView mTvContent; } ChatActivity.javaimport java.util.ArrayList; import java.util.List; import android.app.Activity; import android.graphics.BitmapFactory; import android.os.Bundle; import android.widget.ListView; public class ChatActivity extends Activity { private ListView mLv; private List<ChatItemBean> mDatas ; private ChatLVAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); mLv = (ListView) findViewById(R.id.lv_content); initData(); mAdapter = new ChatLVAdapter(this, mDatas); mLv.setAdapter(mAdapter); } private void initData() { mDatas = new ArrayList<ChatItemBean>(); ChatItemBean chat1 = new ChatItemBean(); chat1.setType(1); chat1.setContent("早啊!"); chat1.setAvatar(BitmapFactory.decodeResource(getResources(), R.drawable.ic_item1)); mDatas.add(chat1); ChatItemBean chat2 = new ChatItemBean(); chat2.setType(2); chat2.setContent("早!一大早找我有啥事?"); chat2.setAvatar(BitmapFactory.decodeResource(getResources(), R.drawable.ic_item2)); mDatas.add(chat2); ChatItemBean chat3 = new ChatItemBean(); chat3.setType(1); chat3.setContent("没事就不能找你谈情说爱吗?也没什么事,看你有没有在撸代码。"); chat3.setAvatar(BitmapFactory.decodeResource(getResources(), R.drawable.ic_item1)); mDatas.add(chat3); ChatItemBean chat4 = new ChatItemBean(); chat4.setType(2); chat4.setContent("算了吧,别找我!我害怕。"); chat4.setAvatar(BitmapFactory.decodeResource(getResources(), R.drawable.ic_item2)); mDatas.add(chat4); ChatItemBean chat5 = new ChatItemBean(); chat5.setType(2); chat5.setContent("都被代码撸惨了,我哪敢一早起来找虐。"); chat5.setAvatar(BitmapFactory.decodeResource(getResources(), R.drawable.ic_item2)); mDatas.add(chat5); } } 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

Android Retrofit 中文乱码问题的解决办法使用retrofit和rxjava,提交数据时需注意,当数据中有中文时,传到后台,可能会是乱码,需处理:解决:1.GET请求改成POST;2.参数Field改成Query3.加上@FormUrlEncoded如下:@[email protected]("/test/test")Call<Response> register(@Field("name") String name); @[email protected]("/test/test")Call<SomeResponse> someEndpoint(@FieldMap Map<String, String> names);解决例子:如此写上报后台会有乱码:(若name和remark有中文)//支付订单 @GET("app/shopcart/pay") Observable<NormalResult> payOrder( @Query("token") String token, @Query("shopcartIdArray") String[] shopcartIdArray, @Query("name") String name, @Query("remake") String remake );修改为://支付订单 @FormUrlEncoded @POST("app/shopcart/pay") Observable<NormalResult> payOrder( @Field("token") String token, @Field("shopcartIdArray") String[] shopcartIdArray,@Field("name") String name, @Field("remake") String remake );如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

焦点访谈

最新最热的文章

更多 >

COPYRIGHT (©) 2017 Copyright ©2017 腾博会官网 网站地图

联系我们

827570882

扫描二维码分享到微信