亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

從 JSON Schema 動態創建 Swing GUI(使用 Metawidget)

從 JSON Schema 動態創建 Swing GUI(使用 Metawidget)

紫衣仙女 2023-08-04 16:52:02
正如標題所示,我想創建一個基于 JSON 模式(我實時獲取)的 Swing GUI,并使用它來填充 JSONObject(Google SimpleJSON)。我正在考慮使用 Metawidget 框架來實現此目的,但到目前為止還沒有成功。我在網上找到了各種參考資料,但似乎沒有一個適用于這個特殊情況。示例中總是缺少一些類或方法,而且 Metawidget 的文檔也不是很好(至少我無法找到 4.2 版本的一組示例)。我得到的 JSON Schema 描述了在服務器端使用 Jackson 的 JSONSchema 描述的 Java 類,但在本地不可用或可以提前知道,因此也應該處理這個問題。有人對不同的方法有什么建議,或者我可以使用一些示例/參考嗎?當然,使用 Metawidget 4.2 編譯的具體代碼也更受歡迎。--- 編輯 --- (由于理查德·肯納德的回應)使用提供的代碼塊,我成功地生成了一個 GUI。但是,我需要修改“json”和“jsonSchema”字符串的值并插入其他值,并切換傳遞給 CompositeInspector 的檢查器的順序。這是代碼和生成的 GUI:final JFrame frame = new JFrame();frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );String json = "{\"person\": { \"firstname\": \"Richard\", \"surname\": \"Kennard\", \"notes\": \"Software developer\" }}";String jsonSchema = "{ \"name\": \"person\", \"type\": \"person\", properties: { \"firstname\": { \"required\": true }, \"surname\": { \"required\": true }, \"notes\": { \"large\": true }}}";final SwingMetawidget metawidget = new SwingMetawidget();metawidget.setInspector( new CompositeInspector( new CompositeInspectorConfig().setInspectors(        new JsonSchemaInspector( new JsonInspectorConfig().setInputStream( new ByteArrayInputStream( jsonSchema.getBytes() ) ) ),        new JsonInspector( new JsonInspectorConfig().setInputStream( new ByteArrayInputStream( json.getBytes() ) ) ))));metawidget.setToInspect( json );frame.add( metawidget, BorderLayout.CENTER );frame.setSize(500, 500);frame.setVisible(true);這沒有使用 MapWidgetProcessor,因為(我想)它需要修改以支持 String 到 JSONObject 的轉換。(此外,該代碼塊中的“NAME”變量未定義,據說需要替換為“elementName”?)然而,所有這些都引出了幾個新問題:1)為什么“json”中的值沒有映射到組件?2)如果我沒有“json”值,而只有“jsonShema”值,應該如何設置?3)為什么在模式中顯式指定屬性類型時代碼不起作用,例如:“名字”:{“必需”:true,“類型”:“字符串”}
查看完整描述

2 回答

?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

Metawidget 的核心原則是允許您混合搭配各種方法以適合您的架構。所以我可以分片來回答這個問題。


一個基本的 SwingMetawidget:


// UI


final JFrame frame = new JFrame();

frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );


// Metawidget


final SwingMetawidget metawidget = new SwingMetawidget();

...configure Metawidget by setting inspectors, inspection result processors, widget builders, etc...

metawidget.setToInspect( myData );

frame.add( metawidget, BorderLayout.CENTER );

要讀取 JSON 類型數據和 JSON 架構,請使用 CompositeInspector:


String json = "{ \"firstname\": \"Richard\", \"surname\": \"Kennard\", \"notes\": \"Software developer\" }";

String jsonSchema = "{ properties: { \"firstname\": { \"required\": true }, \"notes\": { \"large\": true }}}";


...

metawidget.setInspector( new CompositeInspector( new CompositeInspectorConfig().setInspectors(

      new JsonInspector( new JsonInspectorConfig().setInputStream( new ByteArrayInputStream( json.getBytes() ) ) ),

      new JsonSchemaInspector( new JsonInspectorConfig().setInputStream( new ByteArrayInputStream( jsonSchema.getBytes() ) ) ) )

要映射類型,請考慮添加 TypeMappingInspectionResultProcessor:


metawidget.addInspectionResultProcessor(

    new TypeMappingInspectionResultProcessor<SwingMetawidget>(

        new TypeMappingInspectionResultProcessorConfig()

            .setTypeMapping( "foo", "bar" )

            .setTypeMapping( "abc", "def" )));

或者,可能是更好的方法,添加自定義 WidgetBuilder 來處理未知類型的小部件:


metawidget.setWidgetBuilder( new CompositeWidetBuilder( new ompositeWidgetBuilderConfig()

    .setWidgetBuilders(

        new OverriddenWidgetBuilder(), new ReadOnlyWidgetBuilder(),

        new MyWidgetBuilder(), new SwingWidgetBuilder()

    )));

MyWidgetBuilder 做類似的事情


class MyWidgetBuilder

    implements WidgetBuilder<JComponent, SwingMetawidget> {


    public JComponent buildWidget( String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {


        if ( "my.special.type".equals( attributes.get( TYPE ) ) )


            return new JSuperWidget();

        }


        // Fall through to other WidgetBuilder


        return null;

    }

默認情況下,JComponent 不會將其數據保存在任何地方。您需要為此添加類似 BeansBindingProcessor 的內容。當然,BeansBinding 只綁定到 JavaBean。如果你想綁定到其他東西(比如 JSON Map),你可以添加你自己的 MapWidgetProcessor:


/**

* MapWidgetProcessor uses the Metawidget's <code>toInspect</code> to retrieve/store values.

*/


public class MapWidgetProcessor

   implements AdvancedWidgetProcessor<JComponent, SwingMetawidget> {


   //

   // Public methods

   //


   @Override

   public void onStartBuild( SwingMetawidget metawidget ) {


      getWrittenComponents( metawidget ).clear();

   }


   /**

    * Retrieve the values from the Map and put them in the Components.

    */


   @Override

   public JComponent processWidget( JComponent component, String elementName, Map<String, String> attributes, SwingMetawidget metawidget ) {


      String attributeName = attributes.get( NAME );

      getWrittenComponents( metawidget ).put( attributeName, component );


      // Fetch the value...


      Map<String, Object> toInspect = metawidget.getToInspect();

      Object value = toInspect.get( attributeName );


      if ( value == null ) {

         return component;

      }


      // ...and apply it to the component. For simplicity, we won't worry about converters


      String componentProperty = metawidget.getValueProperty( component );

      ClassUtils.setProperty( component, componentProperty, value );


      return component;

   }


   @Override

   public void onEndBuild( SwingMetawidget metawidget ) {


      // Do nothing

   }


   /**

    * Store the values from the Components back into the Map.

    */


   public void save( SwingMetawidget metawidget ) {


      Map<String, Object> toInspect = metawidget.getToInspect();


      for ( Map.Entry<String,JComponent> entry : getWrittenComponents( metawidget ).entrySet() ) {


         JComponent component = entry.getValue();

         String componentProperty = metawidget.getValueProperty( component );

         Object value = ClassUtils.getProperty( component, componentProperty );


         toInspect.put( entry.getKey(), value );

      }

   }


   //

   // Private methods

   //


   /**

    * During load-time we keep track of all the components. At save-time we write them all back

    * again.

    */


   private Map<String,JComponent> getWrittenComponents( SwingMetawidget metawidget ) {


      @SuppressWarnings( "unchecked" )

      Map<String,JComponent> writtenComponents = (Map<String,JComponent>) metawidget.getClientProperty( MapWidgetProcessor.class );


      if ( writtenComponents == null ) {

         writtenComponents = CollectionUtils.newHashMap();

         metawidget.putClientProperty( MapWidgetProcessor.class, writtenComponents );

      }


      return writtenComponents;

   }



查看完整回答
反對 回復 2023-08-04
?
MMTTMM

TA貢獻1869條經驗 獲得超4個贊

回答新問題:

2)然后你必須提供完整的模式。目前 jsonSchema 僅具有“required”等屬性。“type”等屬性是從 json 對象值推斷出來的。CompositeInspector 正在為您將它們合并在一起。但是如果你只想有一個 JsonSchemaInspector (沒有 JsonInspector,沒有 CompositeInspector),那么你的 jsonSchema 必須擁有所有屬性

3)因為“string”是JavaScript類型。Java 等效項是“java.lang.String”。因此,您可以使用 TypeMappingInspectionResultProcessor (或其子類 JsonSchemaMappingInspectionResultProcessor)。這可能看起來很繁重,但請記住您正在做的事情非常不尋常(在 Java 中渲染 JSON)。幸運的是,Metawidget 可以插入各種組合。

最后:“支持 String 到 JSONObject 轉換” - 我不這么認為。JSONObject 是頂層概念。它基本上是一張地圖。您需要綁定的各個字段仍然是基元(字符串、數字等)。所以 MapWidgetProcessor 可能是一個不錯的選擇。


查看完整回答
反對 回復 2023-08-04
  • 2 回答
  • 0 關注
  • 238 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號