问:
After parsing xml files in perl, getting special characters
I'm parsing a xml file & storing it in Database [using perl]. At the time of parsing am getting special characters like - &[quot;amp;lt;gt;].
What is the meaning of these special characters ? </p>

答:
Use HTML::Entities module if you want to get their literal value (the way the HTML displays them).

For more info about entities, see this and this


来源: stackexchange

问:
Node JS Redis Client Connection Retry
Currently I'm using https://github.com/mranney/node_redis as my node redis client.

client.retry_delay is set to 250ms default.

I tried connecting to redis and once connection was successful, I manually stopped the redis server to see whether client.retry_delay works. But I didn't see it working.

The following log messages are logged on ready & end events on redisClients created using createClient:

```<code>[2012-03-30 15:13:05.498] [INFO] Development - Node Application is running on port 8090
[2012-03-30 15:13:08.507] [INFO] Development - Connection Successfully Established to  '127.0.0.1' '6379'
[2012-03-30 15:16:33.886] [FATAL] Development - Connection Terminated to  '127.0.0.1' '6379'
</code>```

I didn't see Success message again [ready event was not fired] when the server came back live.

Am I missing something? When will be the retry constant used? Is there a work around to find whether a redis server has come up after a failure from node?

答:
Answer @ Feb-2020

```<code>const redis = require('redis');
const log = (type, fn) => fn ? () => {
    console.log(`connection ${type}`);
} : console.log(`connection ${type}`);

// Option 1: One connection is enough per application
const client = redis.createClient('6379', "localhost", {
    retry_strategy: (options) => {
        const {error, total_retry_time, attempt} = options;
        if (error && error.code === "ECONNREFUSED") {
            log(error.code); // take actions or throw exception
        }
        if (total_retry_time > 1000 * 15) { //in ms i.e. 15 sec
            log('Retry time exhausted'); // take actions or throw exception
        }
        if (options.attempt > 10) {
            log('10 attempts done'); // take actions or throw exception
        }
        console.log("Attempting connection");
        // reconnect after
        return Math.min(options.attempt * 100, 3000); //in ms
    },
});

client.on('connect', log('connect', true));
client.on('ready', log('ready', true));
client.on('reconnecting', log('reconnecting', true));
client.on('error', log('error', true));
client.on('end', log('end', true));
</code>```

For complete running example clone node-cheat and run node connect-retry.js.

ContentLicense: CC BY-SA 4.0

Title: Node JS Redis Client Connection Retry

Body:
Currently I'm using https://github.com/mranney/node_redis as my node redis client.

client.retry_delay is set to 250ms default.

I tried connecting to redis and once connection was successful, I manually stopped the redis server to see whether client.retry_delay works. But I didn't see it working.

The following log messages are logged on ready & end events on redisClients created using createClient:

[2012-03-30 15:13:05.498] [INFO] Development - Node Application is running on port 8090
[2012-03-30 15:13:08.507] [INFO] Development - Connection Successfully Established to  '127.0.0.1' '6379'
[2012-03-30 15:16:33.886] [FATAL] Development - Connection Terminated to  '127.0.0.1' '6379'

I didn't see Success message again [ready event was not fired] when the server came back live.

Am I missing something? When will be the retry constant used? Is there a work around to find whether a redis server has come up after a failure from node?

Body:
Answer @ Feb-2020

const redis = require('redis');
const log = (type, fn) => fn ? () => {
    console.log(`connection ${type}`);
} : console.log(`connection ${type}`);

// Option 1: One connection is enough per application
const client = redis.createClient('6379', "localhost", {
    retry_strategy: (options) => {
        const {error, total_retry_time, attempt} = options;
        if (error && error.code === "ECONNREFUSED") {
            log(error.code); // take actions or throw exception
        }
        if (total_retry_time > 1000 * 15) { //in ms i.e. 15 sec
            log('Retry time exhausted'); // take actions or throw exception
        }
        if (options.attempt > 10) {
            log('10 attempts done'); // take actions or throw exception
        }
        console.log("Attempting connection");
        // reconnect after
        return Math.min(options.attempt * 100, 3000); //in ms
    },
});

client.on('connect', log('connect', true));
client.on('ready', log('ready', true));
client.on('reconnecting', log('reconnecting', true));
client.on('error', log('error', true));
client.on('end', log('end', true));

For complete running example clone node-cheat and run node connect-retry.js.


问:
Can we use HAproxy load balancer along with nginx acting as a server?
In our project, we want to use HAproxy as a Load balancer which is done on a VM, and Nginx is used as a server. Is it possible to do? or is it necessary that we use one Nginx for the load balancer and another one as a server?</p>

答:
Yes, HAProxy only need an address:port

So you can forward to an NGinx that will expose your app

Or forward directly to applications port

Both will work.

```<code>  HAProxy
  |      |
  |      |
NGinx   NGinx
  |      |
  |      |
App     App

  HAProxy
  |      |
  |      |
App     App
</code>```

Body:
Yes, HAProxy only need an address:port

So you can forward to an NGinx that will expose your app

Or forward directly to applications port

Both will work.

  HAProxy
  |      |
  |      |
NGinx   NGinx
  |      |
  |      |
App     App

  HAProxy
  |      |
  |      |
App     App


问:
Can't give default value to database text field in laravel app (mysql)
in my laravel app I have a Post "body" field of text type, I'm trying to give the field a default value like "This sis the default text for a blog post, feel free to change it" but mysql is throwing an error.

```<code>$table->text('body')->default('This is the default text for a blog post, feel free to change it.');
</code>```

This isn't working...

According to docs BLOB/TEXT fields CAN'T have default values, this is pretty weird tbh.

https://dev.mysql.com/doc/refman/5.7/en/blob.html

I guess I could change the field type from text to string but afaik string won't have as many characters as string type and I knpw for certain that my Blog posts will be loooong. How could I approach this?

Thanks in advance.

答:
In mysql you can't give text default value.
Solutions:

Convert it to varchar ( You can have max 255 characters in one row)

Give default value with code ( during creating, after creating, default placeholder text ... )

Body:
in my laravel app I have a Post "body" field of text type, I'm trying to give the field a default value like "This sis the default text for a blog post, feel free to change it" but mysql is throwing an error.

$table->text('body')->default('This is the default text for a blog post, feel free to change it.');

This isn't working...

According to docs BLOB/TEXT fields CAN'T have default values, this is pretty weird tbh.

https://dev.mysql.com/doc/refman/5.7/en/blob.html

I guess I could change the field type from text to string but afaik string won't have as many characters as string type and I knpw for certain that my Blog posts will be loooong. How could I approach this?

Thanks in advance.


问:
Help with structuremap configuration
I am trying to configure Structuremap something like the following but I can seem to get it quite right

ObjectFactory.Initialize(x => {

    x.For<TunaRepository>()
        .Use(new TunaRepository(serviceEndpoint))
        .Named("Tuna");

    x.For<CodRepository>()
        .Use(new CodRepository(serviceEndpoint))
        .Named("Cod");

    x.For<HaddockRepository>()
        .Use(new HaddockRepository(serviceEndpoint))
        .Named("Haddock");

    x.For<IFishRepository>().AddInstances(y =>
                                        {
                                            y.OfConcreteType<TunaRepository>().
                                            // Somehow add all instances here???

                                        });

    x.For<TunaController>().Use<TunaController>()
        .Ctor<IFishRepository>("repo").Is<TunaRepository>(); // This Is should use the instance registered above

    x.For<CodController>().Use<CodController>()
        .Ctor<IFishRepository>("repo").???

    x.For<HaddockController>().Use<HaddockController>()
        .Ctor<IFishRepository>("repo").???

});
```

<p>At points in my code I want to be able to do:</p>

<pre class="lang-cs prettyprint-override"><code>var instances = ObjectFactory.GetAllInstances<IFishRepository>();
</code>```

and also:

var instance = ObjectFactory.GetNamedInstance<IFishRepository>("Cod");
```

<p>and also use IFishRepository as an arguement to my controllers:</p>

<pre class="lang-cs prettyprint-override"><code>public TunaController(IFishRepository repo ...
</code>```

So my question is whats the best way to configure my ObjectFactory?

答:
When registering named instances that should not be the Default instance you use the Add method:

```<code> x.For<IFishRepository>()
   .Add(() => new TunaRepository(serviceEndpoint))
   .Named("Tuna");
</code>```

Also observe that unless you want the TunaRepository to be a Singleton you should register it using a lambda. The lambda will be evaluated when the instance is requested and will in my example return a new instance. Watch out with the serviceEndpoint as well and make sure if you want that single instance for all repositories. Generally I tend to wire up all my dependencies using For<>().Use<>() in structure map where possible instead of using "new". Doing so makes the architecture much more flexible, especially since you can add new parameters to the ctors without changing the registrations.

For specifying a named instance to be used in a constructor you can use this syntax:

```<code> x.For<TunaController>().Use<TunaController>().
   Ctor<IFishRepository>("repo").
   Is(i => i.TheInstanceNamed("Tuna"));
</code>```

Since all your registrations are following the same patterns, I would use an IRegistrationConvention in order to remove duplicate code and minimize the effort of adding new repositories.

ContentLicense: CC BY-SA 3.0

Title: Help with structuremap configuration

Body:
I am trying to configure Structuremap something like the following but I can seem to get it quite right

ObjectFactory.Initialize(x => {

    x.For<TunaRepository>()
        .Use(new TunaRepository(serviceEndpoint))
        .Named("Tuna");

    x.For<CodRepository>()
        .Use(new CodRepository(serviceEndpoint))
        .Named("Cod");

    x.For<HaddockRepository>()
        .Use(new HaddockRepository(serviceEndpoint))
        .Named("Haddock");

    x.For<IFishRepository>().AddInstances(y =>
                                        {
                                            y.OfConcreteType<TunaRepository>().
                                            // Somehow add all instances here???

                                        });

    x.For<TunaController>().Use<TunaController>()
        .Ctor<IFishRepository>("repo").Is<TunaRepository>(); // This Is should use the instance registered above

    x.For<CodController>().Use<CodController>()
        .Ctor<IFishRepository>("repo").???

    x.For<HaddockController>().Use<HaddockController>()
        .Ctor<IFishRepository>("repo").???

});

At points in my code I want to be able to do:

var instances = ObjectFactory.GetAllInstances<IFishRepository>();

and also:

var instance = ObjectFactory.GetNamedInstance<IFishRepository>("Cod");

and also use IFishRepository as an arguement to my controllers:

public TunaController(IFishRepository repo ...

So my question is whats the best way to configure my ObjectFactory?

Body:
When registering named instances that should not be the Default instance you use the Add method:

 x.For<IFishRepository>()
   .Add(() => new TunaRepository(serviceEndpoint))
   .Named("Tuna");

Also observe that unless you want the TunaRepository to be a Singleton you should register it using a lambda. The lambda will be evaluated when the instance is requested and will in my example return a new instance. Watch out with the serviceEndpoint as well and make sure if you want that single instance for all repositories. Generally I tend to wire up all my dependencies using For<>().Use<>() in structure map where possible instead of using "new". Doing so makes the architecture much more flexible, especially since you can add new parameters to the ctors without changing the registrations.

For specifying a named instance to be used in a constructor you can use this syntax:

 x.For<TunaController>().Use<TunaController>().
   Ctor<IFishRepository>("repo").
   Is(i => i.TheInstanceNamed("Tuna"));

Since all your registrations are following the same patterns, I would use an IRegistrationConvention in order to remove duplicate code and minimize the effort of adding new repositories.


问:
Why is Fluentd Azure blob plugin not working in kubernetes
I've installed fluentd in my AKS cluster using the following command helm install fluentd bitnami-azure/fluentd --namespace mynamespace --set forwarder.configMap=fluentd-aksconfig.

Below is my configmap.yaml

```<code>apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-aksconfig
  namespace: mynamespace
data:
  fluentd.conf: |
    <match **>
          @type azure-storage-append-blob
          azure_storage_account    mystorageaccount
          azure_storage_access_key myaccesskey
          azure_container          aksfluentd
          auto_create_container    true
          path logs/
          azure_object_key_format  %{path}%{time_slice}_%{index}.log
          time_slice_format        %Y%m%d-%H
          # if you want to use %{tag} or %Y/%m/%d/ like syntax in path / azure_blob_name_format,
          # need to specify tag for %{tag} and time for %Y/%m/%d in <buffer> argument.
          <buffer tag,time>
            @type file
            path /var/log/fluent/azurestorageappendblob
            timekey 120 # 2 minutes
            timekey_wait 60
            timekey_use_utc true # use utc
          </buffer>
    </match>
</code>```

below are the errors obtained from the pods. It displays that there is no plugin called "azure-storage-append-blob". How to fix this?

Logs:

[38;5;6mfluentd [38;5;5m10:03:45.15 [0m [38;5;6mfluentd
  [38;5;5m10:03:45.15 [0m[1mWelcome to the Bitnami fluentd
  container[0m [38;5;6mfluentd [38;5;5m10:03:45.16 [0mSubscribe to
  project updates by watching
  [1mhttps://github.com/bitnami/bitnami-docker-fluentd[0m
  [38;5;6mfluentd [38;5;5m10:03:45.16 [0mSubmit issues and feature
  requests at
  [1mhttps://github.com/bitnami/bitnami-docker-fluentd/issues[0m
  [38;5;6mfluentd [38;5;5m10:03:45.16 [0mSend us your feedback at
  [1mcontainers@bitnami.com[0m [38;5;6mfluentd [38;5;5m10:03:45.16
  [0m [38;5;6mfluentd [38;5;5m10:03:45.16 [0m[38;5;2mINFO [0m ==>
  ** Starting Fluentd setup ** [38;5;6mfluentd [38;5;5m10:03:45.38 [0m[38;5;2mINFO [0m ==> ** Fluentd setup finished! **
  [38;5;6mfluentd [38;5;5m10:03:45.39 [0m[38;5;2mINFO [0m ==> **
  Starting Fluentd ** 2020-02-18 10:03:46 +0000 [info]: parsing config
  file is succeeded path="/opt/bitnami/fluentd/conf/fluentd.conf"
  2020-02-18 10:03:46 +0000 [info]: gem 'fluent-plugin-concat' version
  '2.4.0' 2020-02-18 10:03:46 +0000 [info]: gem
  'fluent-plugin-detect-exceptions' version '0.0.13' 2020-02-18 10:03:46
  +0000 [info]: gem 'fluent-plugin-elasticsearch' version '4.0.1' 2020-02-18 10:03:46 +0000 [info]: gem 'fluent-plugin-kafka' version
  '0.12.2' 2020-02-18 10:03:46 +0000 [info]: gem
  'fluent-plugin-kubernetes_metadata_filter' version '2.4.2' 2020-02-18
  10:03:46 +0000 [info]: gem 'fluent-plugin-multi-format-parser' version
  '1.0.0' 2020-02-18 10:03:46 +0000 [info]: gem
  'fluent-plugin-prometheus' version '1.7.0' 2020-02-18 10:03:46 +0000
  [info]: gem 'fluent-plugin-s3' version '1.2.1' 2020-02-18 10:03:46
  +0000 [info]: gem 'fluent-plugin-systemd' version '1.0.2' 2020-02-18 10:03:46 +0000 [info]: gem 'fluentd' version '1.9.1' 2020-02-18
  10:03:46 +0000 [error]: config error
  file="/opt/bitnami/fluentd/conf/fluentd.conf"
  error_class=Fluent::ConfigError error="Unknown output plugin
  'azure-storage-append-blob'. Run 'gem search -rd fluent-plugin' to
  find plugins"

答: azure-storage-append-blob plugin is not installed by default. So you need to install it. Docs on how to install Fluentd plugin is here.</p>

Body:
I've installed fluentd in my AKS cluster using the following command helm install fluentd bitnami-azure/fluentd --namespace mynamespace --set forwarder.configMap=fluentd-aksconfig.

Below is my configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-aksconfig
  namespace: mynamespace
data:
  fluentd.conf: |
    <match **>
          @type azure-storage-append-blob
          azure_storage_account    mystorageaccount
          azure_storage_access_key myaccesskey
          azure_container          aksfluentd
          auto_create_container    true
          path logs/
          azure_object_key_format  %{path}%{time_slice}_%{index}.log
          time_slice_format        %Y%m%d-%H
          # if you want to use %{tag} or %Y/%m/%d/ like syntax in path / azure_blob_name_format,
          # need to specify tag for %{tag} and time for %Y/%m/%d in <buffer> argument.
          <buffer tag,time>
            @type file
            path /var/log/fluent/azurestorageappendblob
            timekey 120 # 2 minutes
            timekey_wait 60
            timekey_use_utc true # use utc
          </buffer>
    </match>

below are the errors obtained from the pods. It displays that there is no plugin called "azure-storage-append-blob". How to fix this?

Logs:

[38;5;6mfluentd [38;5;5m10:03:45.15 [0m [38;5;6mfluentd
  [38;5;5m10:03:45.15 [0m[1mWelcome to the Bitnami fluentd
  container[0m [38;5;6mfluentd [38;5;5m10:03:45.16 [0mSubscribe to
  project updates by watching
  [1mhttps://github.com/bitnami/bitnami-docker-fluentd[0m
  [38;5;6mfluentd [38;5;5m10:03:45.16 [0mSubmit issues and feature
  requests at
  [1mhttps://github.com/bitnami/bitnami-docker-fluentd/issues[0m
  [38;5;6mfluentd [38;5;5m10:03:45.16 [0mSend us your feedback at
  [1mcontainers@bitnami.com[0m [38;5;6mfluentd [38;5;5m10:03:45.16
  [0m [38;5;6mfluentd [38;5;5m10:03:45.16 [0m[38;5;2mINFO [0m ==>
  ** Starting Fluentd setup ** [38;5;6mfluentd [38;5;5m10:03:45.38 [0m[38;5;2mINFO [0m ==> ** Fluentd setup finished! **
  [38;5;6mfluentd [38;5;5m10:03:45.39 [0m[38;5;2mINFO [0m ==> **
  Starting Fluentd ** 2020-02-18 10:03:46 +0000 [info]: parsing config
  file is succeeded path="/opt/bitnami/fluentd/conf/fluentd.conf"
  2020-02-18 10:03:46 +0000 [info]: gem 'fluent-plugin-concat' version
  '2.4.0' 2020-02-18 10:03:46 +0000 [info]: gem
  'fluent-plugin-detect-exceptions' version '0.0.13' 2020-02-18 10:03:46
  +0000 [info]: gem 'fluent-plugin-elasticsearch' version '4.0.1' 2020-02-18 10:03:46 +0000 [info]: gem 'fluent-plugin-kafka' version
  '0.12.2' 2020-02-18 10:03:46 +0000 [info]: gem
  'fluent-plugin-kubernetes_metadata_filter' version '2.4.2' 2020-02-18
  10:03:46 +0000 [info]: gem 'fluent-plugin-multi-format-parser' version
  '1.0.0' 2020-02-18 10:03:46 +0000 [info]: gem
  'fluent-plugin-prometheus' version '1.7.0' 2020-02-18 10:03:46 +0000
  [info]: gem 'fluent-plugin-s3' version '1.2.1' 2020-02-18 10:03:46
  +0000 [info]: gem 'fluent-plugin-systemd' version '1.0.2' 2020-02-18 10:03:46 +0000 [info]: gem 'fluentd' version '1.9.1' 2020-02-18
  10:03:46 +0000 [error]: config error
  file="/opt/bitnami/fluentd/conf/fluentd.conf"
  error_class=Fluent::ConfigError error="Unknown output plugin
  'azure-storage-append-blob'. Run 'gem search -rd fluent-plugin' to
  find plugins"


问:
How to write a txt file with the log from the `npm list` command?
npm list logs this:

How can I save that as a txt file?

答:
Works on newer Windows OS and Linux/Mac:</p>

```<code>npm list > logs.txt
</code>```

Body:
Works on newer Windows OS and Linux/Mac:

npm list > logs.txt


问:
How to print multiple integer array based on user Input?
I am creating a java program which prompts user for the number of items in an array (a non-negative integer), reads it, and saves it in an int variable. It then prompts user for the values of all the items and saves them in an int array. Afterwards, the program prints the content of the array in the form of [x1, x2, ... ,xn]. No user validation is required. The program was supposed to work out fine, however, when I tried to enter the multiple inputs for the user, there is something wrong with the output.

Instead of showing this:

```<code>Enter the number of items: 2
Enter the value of all items (separated by space): 88
Enter the value of all items (separated by space): 99
The values are: [88, 99]
</code>```

The output becomes like this:

```<code>Enter the number of items: 2
Enter the value of all items (separated by space) : 88
Enter the value of all items (separated by space) : 99
The values are: [88]
The values are: [99]
</code>```

Also, when I enter 0 for the number of items, the output was supposed to show this

```<code>Enter the number of items: 0
The values are: []
</code>```

But my output shows this instead:

```<code>Enter the number of items: 0
</code>```

It does not even show the brackets of the values when the number of items is 0. Attached below is my codings:

```<code>import java.util.Scanner;

public class PrintArray{

public static void main(String[] args) {
 // Declare variables
      int numItems;
      int[] items;  // Declare array name, to be allocated after numItems is known

  // Prompt for a non-negative integer for the number of items;
  // and read the input as "int". No input validation.
  Scanner in = new Scanner(System.in);
  System.out.print("Enter the number of items: ");
  numItems = in.nextInt();

  // Allocate the array
  items = new int[numItems];

  // Prompt and read the items into the "int" array, if array length > 0
  if (items.length > 0) {

     for (int i = 0; i < items.length; ++i) {
        System.out.print("Enter the value of all items (separated by space) : ");
        items[i] = in.nextInt();

     }
  }

  // Print array contents, need to handle first item and subsequent items differently

  for (int i = 0; i < items.length; ++i) {
     if (i == 0) {
        // Print the first item without a leading commas
        System.out.println("The values are: [" + items[i] + "]");
     } else {
        // Print the subsequent items with a leading commas
        System.out.println("The values are: [" + items[i] + "]");
     }

  }

  }
}
</code>```

It would be good if someone can help me with that. Many thanks!

答:
You are iterating over the same array so it's printed many times. Try this for the last for:

```<code>String  values = ""
for (int i = 0; i < items.length; ++i) {

    if (i == 0) {
        // Print the first item without a leading commas
        values = values + items[i];
     } else {
        // Print the subsequent items with a leading commas
        values = values + "," + items[i];
     }

System.out.println("The values are: [" + values + "]");
</code>```

or you can also do like this which looks more readable:

```<code>String  values = "" + items[0];
for (int i = 1; i < items.length; ++i) {
        // Print the subsequent items with a leading commas
        values = values + "," + items[i];
     }

System.out.println("The values are: [" + values + "]");
</code>```

Body:
I am creating a java program which prompts user for the number of items in an array (a non-negative integer), reads it, and saves it in an int variable. It then prompts user for the values of all the items and saves them in an int array. Afterwards, the program prints the content of the array in the form of [x1, x2, ... ,xn]. No user validation is required. The program was supposed to work out fine, however, when I tried to enter the multiple inputs for the user, there is something wrong with the output.

Instead of showing this:

Enter the number of items: 2
Enter the value of all items (separated by space): 88
Enter the value of all items (separated by space): 99
The values are: [88, 99]

The output becomes like this:

Enter the number of items: 2
Enter the value of all items (separated by space) : 88
Enter the value of all items (separated by space) : 99
The values are: [88]
The values are: [99]

Also, when I enter 0 for the number of items, the output was supposed to show this

Enter the number of items: 0
The values are: []

But my output shows this instead:

Enter the number of items: 0

It does not even show the brackets of the values when the number of items is 0. Attached below is my codings:

import java.util.Scanner;

public class PrintArray{

public static void main(String[] args) {
 // Declare variables
      int numItems;
      int[] items;  // Declare array name, to be allocated after numItems is known

  // Prompt for a non-negative integer for the number of items;
  // and read the input as "int". No input validation.
  Scanner in = new Scanner(System.in);
  System.out.print("Enter the number of items: ");
  numItems = in.nextInt();

  // Allocate the array
  items = new int[numItems];

  // Prompt and read the items into the "int" array, if array length > 0
  if (items.length > 0) {

     for (int i = 0; i < items.length; ++i) {
        System.out.print("Enter the value of all items (separated by space) : ");
        items[i] = in.nextInt();

     }
  }

  // Print array contents, need to handle first item and subsequent items differently

  for (int i = 0; i < items.length; ++i) {
     if (i == 0) {
        // Print the first item without a leading commas
        System.out.println("The values are: [" + items[i] + "]");
     } else {
        // Print the subsequent items with a leading commas
        System.out.println("The values are: [" + items[i] + "]");
     }

  }

  }
}

It would be good if someone can help me with that. Many thanks!

Body:
You are iterating over the same array so it's printed many times. Try this for the last for:

String  values = ""
for (int i = 0; i < items.length; ++i) {

    if (i == 0) {
        // Print the first item without a leading commas
        values = values + items[i];
     } else {
        // Print the subsequent items with a leading commas
        values = values + "," + items[i];
     }

System.out.println("The values are: [" + values + "]");

or you can also do like this which looks more readable:

String  values = "" + items[0];
for (int i = 1; i < items.length; ++i) {
        // Print the subsequent items with a leading commas
        values = values + "," + items[i];
     }

System.out.println("The values are: [" + values + "]");


问:
Problems of hidden-surface removal when OpenGL is running in child window
I'm currently trying to draw a quadratic surface with openGL.When using a single window,my program can work well.Now I need a control panel so I create two windows,one is the frame window ,the other is the child window in which OpenGL runs.But the is something wrong with hidden-surface removal when openGL runs in the child window while this problem does not exist if I use single window.I didn't change the drawing function,just get the dc of child window and set the rc.Here is the code.Thanks for help.

```<code>#include <windows.h> //Windows header
#include <gl\glut.h>                                    //glut
#include <gl\glaux.h>                                   //glaux
#define hID 6310                                        //ID of child window

LRESULT CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK OpenProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR       szChildClass[] = TEXT ("OpenGL");     //child window class name
TCHAR       szAppName[] = TEXT ("Frame");         //frame window class name
HWND        hwndopen;                             //child window
handle
HWND        hwnd;                                 //frame window handle
MSG         msg ;                                 //message structure
HDC         hdc = NULL;                           //device context used in child window
HGLRC       hrc = NULL;                           //rendering context
HINSTANCE   hInstance;                            //application instance
GLuint      PixelFormat;                                //pixformat
BOOL        active=TRUE;
BOOL        keys[256];
float       rquad[3]={0,0,0};                     //angle of rotate
// pfd Tells Windows How We Want Things To Be
static  PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),
1,PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
16,
0, 0, 0, 0, 0, 0,
0,0,0,0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};

/* Here I draw a color cube and I draw black line in every  edge
of the cube,the I draw 3 color lines to show x,y,z coordinate
axis*/
int DrawGLScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-10.0f);
glRotatef(rquad[0],1.0f,0.0f,0.0f);
glRotatef(rquad[1],0.0f,1.0f,0.0f);
glRotatef(rquad[2],0.0f,0.0f,1.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd();

glBegin(GL_LINES);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( -1.0f, 1.0f, 1.0f);
glVertex3f( -1.0f, -1.0f, 1.0f);
glVertex3f( -1.0f, 1.0f, -1.0f);
glVertex3f( -1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 10.0f, 0.0f, 0.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 10.0f, 0.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, 10.0f);
glEnd();
return TRUE;
}

BOOL InitGL(void)                                       //init opengl
{
glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
glClearColor(1.0f,0.0f,1.0f,0.5f);
   glClearDepth(1.0f);                              glEnable(GL_DEPTH_TEST);                            glDepthFunc(GL_LEQUAL);                         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
   return TRUE;
}

// resize the opengl scene in child window
void ReSizeGLScene(int width, int height)
{
 if (height==0)   //avoid zero to be the divisor
                            {
    height=1;
}
glViewport(0,0,(int)width,(int)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(float)width/(float)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                PSTR szCmdLine, int iCmdShow)
{

WNDCLASS     wndclass ;
BOOL         flag=TRUE;
hInstance    = GetModuleHandle(NULL);
InitGL();

wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc   = WndProc ;
wndclass.cbClsExtra    = 0 ;
wndclass.cbWndExtra    = 0 ;
wndclass.hInstance     = hInstance ;
wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wndclass.lpszMenuName  = NULL ;
wndclass.lpszClassName = szAppName ;

if (!RegisterClass(&wndclass))
{
MessageBox(NULL,"窗口类注册失败","演示程序 ",MB_OK|MB_ICONINFORMATION);
    return 0;
}
wndclass.lpfnWndProc   = OpenProc ;
wndclass.cbWndExtra    = sizeof (long) ;
wndclass.hIcon         = NULL ;
wndclass.hbrBackground = NULL;
wndclass.lpszClassName = szChildClass ;

if (!RegisterClass(&wndclass))
{
    MessageBox(NULL,"子窗口类注册失败","演示程序",MB_OK|MB_ICONINFORMATION);
    return 0;
}

if(!(hwnd = CreateWindow (szAppName, TEXT ("Frisa"),
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL, hInstance, NULL)))
{
    MessageBox(NULL,"窗口创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
    return FALSE;
}

ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;

while (flag)
{
    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
        if (msg.message==WM_QUIT)
        {
            if (!UnregisterClass(szChildClass,hInstance))
            {
                MessageBox(NULL,"子窗口类注销失败","演示程序",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;
            }

            if (!UnregisterClass(szAppName,hInstance))
            {
                MessageBox(NULL,"窗口类注销失败","演示程序",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;
            }
            flag=FALSE;
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    else
    {
        if (active && !DrawGLScene())   // Active?  Was There A Quit Received?
        {
            flag=FALSE;                         // ESC or DrawGLScene Signalled A Quit
        }
        else                                    // Not Time To Quit, Update Screen
        {

            SwapBuffers(hdc);                   // Swap Buffers (Double Buffering)
        }
        if(keys[VK_RIGHT]){rquad[0]+=0.12;}
        if(keys[VK_LEFT]){rquad[0]=0;rquad[1]=0;rquad[2]=0;}
        if(keys[VK_UP]){rquad[1]+=0.12;}
        if(keys[VK_DOWN]){rquad[2]+=0.12;}
    }
}

return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

int   cxBlock, cyBlock;

switch (message)
{
case WM_CREATE :
    if(!(hwndopen= CreateWindow (szChildClass, NULL,
        WS_CHILDWINDOW | WS_VISIBLE,
        0, 0, 0, 0,
        hwnd,(HMENU)(hID),
        (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE),
        NULL)))
    {
        MessageBox(NULL,"子窗口创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }
    if (!(hdc=GetDC(hwndopen)))
    {
        MessageBox(NULL,"设备描述表创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if (!(PixelFormat=ChoosePixelFormat(hdc,&pfd)))
    {
        MessageBox(NULL,"未找到匹配的像素格式","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if(!SetPixelFormat(hdc,PixelFormat,&pfd))
    {
        MessageBox(NULL,"设置像素格式失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if (!(hrc=wglCreateContext(hdc)))
    {
        MessageBox(NULL,"获取渲染描述表失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if(!wglMakeCurrent(hdc,hrc))
    {
        MessageBox(NULL,"渲染描述表激活失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }
    return 0 ;

case WM_ACTIVATE:                           // Watch For Window Activate Message
    // LoWord Can Be WA_INACTIVE, WA_ACTIVE, WA_CLICKACTIVE,
    // The High-Order Word Specifies The Minimized State Of The Window Being Activated Or Deactivated.
    // A NonZero Value Indicates The Window Is Minimized.
    if ((LOWORD(wParam) != WA_INACTIVE) && !((BOOL)HIWORD(wParam)))
        active=TRUE;                        // Program Is Active
    else
        active=FALSE;                       // Program Is No Longer Active
    return 0;                               // Return To The Message Loop

case WM_SIZE :
    cxBlock = LOWORD (lParam);
    cyBlock = HIWORD (lParam);
    MoveWindow (hwndopen,
        5,5,
        (int)(cxBlock*0.80),(int)(cyBlock*0.98), TRUE) ;
    ReSizeGLScene((int)(cxBlock*0.80),(int)(cyBlock*0.97));
    return 0 ;

case WM_LBUTTONDOWN :
    MessageBeep (0) ;
    return 0 ;

case WM_KEYDOWN:
    keys[wParam] = TRUE;
    return 0;

case WM_KEYUP:
    keys[wParam] = FALSE;
    return 0;

case WM_CLOSE:
    DestroyWindow(hwnd);
    return 0;

case WM_DESTROY :
    if (hrc)
    {
        if (!wglMakeCurrent(hdc,NULL))
        {
            MessageBox(NULL,"DC和RC关联解除失败","演示程序",MB_OK | MB_ICONINFORMATION);
        }

        if (!wglDeleteContext(hrc))
        {
            MessageBox(NULL,"RC释放失败","演示程序",MB_OK | MB_ICONINFORMATION);
        }

        hrc=NULL;
    }

    if (!DestroyWindow(hwnd))
    {
        MessageBox(NULL,"窗口句柄释放失败","演示程序",MB_OK | MB_ICONINFORMATION);
        hwnd=NULL;
    }

    PostQuitMessage (0) ;
    return 0 ;

}
return DefWindowProc (hwnd, message, wParam, lParam) ;
  }

LRESULT CALLBACK OpenProc (HWND hwnd, UINT message,
                       WPARAM wParam, LPARAM lParam)
{
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
</code>```

ADDITION

My aim is to paint a clolor cube in the child window with OpenGL.The size of the child window is about 0.8 times the frame window's size.I will add a control panel in the rest of area of the frame window. My program can draw a color cube .But the problem is I can see all the 6 faces,and all the 12 edges of the cube.I'm not sure but it looks like the hidden-surface removal failed.

Here I provide a link to the image of the result.
http://svgeqg.blu.livefilestore.com/y1p_TRCQ495hxOztZy3oi5qZiDPdN9hQil0KLTY9I-7fFfqCuVr_FiyJ-dIlflN5eHCMqZo5smpUwTaFDxAelq_rjO5hTU5kVzS/colorcube.JPG?psid=1

答: I have solved the problem,it's about the location of the OpenGL initialization.The initializationmust be after the creation of the child window in which OpenGL runs.In the above code，I init OpenGL at the beginning of winmain() function ,but the child window does not exist at that time.</p>

Body:
I'm currently trying to draw a quadratic surface with openGL.When using a single window,my program can work well.Now I need a control panel so I create two windows,one is the frame window ,the other is the child window in which OpenGL runs.But the is something wrong with hidden-surface removal when openGL runs in the child window while this problem does not exist if I use single window.I didn't change the drawing function,just get the dc of child window and set the rc.Here is the code.Thanks for help.

#include <windows.h> //Windows header
#include <gl\glut.h>                                    //glut
#include <gl\glaux.h>                                   //glaux
#define hID 6310                                        //ID of child window

LRESULT CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK OpenProc (HWND, UINT, WPARAM, LPARAM) ;

TCHAR       szChildClass[] = TEXT ("OpenGL");     //child window class name
TCHAR       szAppName[] = TEXT ("Frame");         //frame window class name
HWND        hwndopen;                             //child window
handle
HWND        hwnd;                                 //frame window handle
MSG         msg ;                                 //message structure
HDC         hdc = NULL;                           //device context used in child window
HGLRC       hrc = NULL;                           //rendering context
HINSTANCE   hInstance;                            //application instance
GLuint      PixelFormat;                                //pixformat
BOOL        active=TRUE;
BOOL        keys[256];
float       rquad[3]={0,0,0};                     //angle of rotate
// pfd Tells Windows How We Want Things To Be
static  PIXELFORMATDESCRIPTOR pfd={
sizeof(PIXELFORMATDESCRIPTOR),
1,PFD_DRAW_TO_WINDOW|
PFD_SUPPORT_OPENGL|
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
16,
0, 0, 0, 0, 0, 0,
0,0,0,0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};

/* Here I draw a color cube and I draw black line in every  edge
of the cube,the I draw 3 color lines to show x,y,z coordinate
axis*/
int DrawGLScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-10.0f);
glRotatef(rquad[0],1.0f,0.0f,0.0f);
glRotatef(rquad[1],0.0f,1.0f,0.0f);
glRotatef(rquad[2],0.0f,0.0f,1.0f);
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd();

glBegin(GL_LINES);
glColor3f(1.0f,1.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( -1.0f, 1.0f, 1.0f);
glVertex3f( -1.0f, -1.0f, 1.0f);
glVertex3f( -1.0f, 1.0f, -1.0f);
glVertex3f( -1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
glBegin(GL_LINES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 10.0f, 0.0f, 0.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 10.0f, 0.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 0.0f, 0.0f, 0.0f);
glVertex3f( 0.0f, 0.0f, 10.0f);
glEnd();
return TRUE;
}

BOOL InitGL(void)                                       //init opengl
{
glShadeModel(GL_SMOOTH);                            // Enable Smooth Shading
glClearColor(1.0f,0.0f,1.0f,0.5f);
   glClearDepth(1.0f);                              glEnable(GL_DEPTH_TEST);                            glDepthFunc(GL_LEQUAL);                         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
   return TRUE;
}

// resize the opengl scene in child window
void ReSizeGLScene(int width, int height)
{
 if (height==0)   //avoid zero to be the divisor
                            {
    height=1;
}
glViewport(0,0,(int)width,(int)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(float)width/(float)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                PSTR szCmdLine, int iCmdShow)
{

WNDCLASS     wndclass ;
BOOL         flag=TRUE;
hInstance    = GetModuleHandle(NULL);
InitGL();

wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc   = WndProc ;
wndclass.cbClsExtra    = 0 ;
wndclass.cbWndExtra    = 0 ;
wndclass.hInstance     = hInstance ;
wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
wndclass.lpszMenuName  = NULL ;
wndclass.lpszClassName = szAppName ;

if (!RegisterClass(&wndclass))
{
MessageBox(NULL,"窗口类注册失败","演示程序 ",MB_OK|MB_ICONINFORMATION);
    return 0;
}
wndclass.lpfnWndProc   = OpenProc ;
wndclass.cbWndExtra    = sizeof (long) ;
wndclass.hIcon         = NULL ;
wndclass.hbrBackground = NULL;
wndclass.lpszClassName = szChildClass ;

if (!RegisterClass(&wndclass))
{
    MessageBox(NULL,"子窗口类注册失败","演示程序",MB_OK|MB_ICONINFORMATION);
    return 0;
}

if(!(hwnd = CreateWindow (szAppName, TEXT ("Frisa"),
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL, hInstance, NULL)))
{
    MessageBox(NULL,"窗口创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
    return FALSE;
}

ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;

while (flag)
{
    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
    {
        if (msg.message==WM_QUIT)
        {
            if (!UnregisterClass(szChildClass,hInstance))
            {
                MessageBox(NULL,"子窗口类注销失败","演示程序",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;
            }

            if (!UnregisterClass(szAppName,hInstance))
            {
                MessageBox(NULL,"窗口类注销失败","演示程序",MB_OK | MB_ICONINFORMATION);
                hInstance=NULL;
            }
            flag=FALSE;
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    else
    {
        if (active && !DrawGLScene())   // Active?  Was There A Quit Received?
        {
            flag=FALSE;                         // ESC or DrawGLScene Signalled A Quit
        }
        else                                    // Not Time To Quit, Update Screen
        {

            SwapBuffers(hdc);                   // Swap Buffers (Double Buffering)
        }
        if(keys[VK_RIGHT]){rquad[0]+=0.12;}
        if(keys[VK_LEFT]){rquad[0]=0;rquad[1]=0;rquad[2]=0;}
        if(keys[VK_UP]){rquad[1]+=0.12;}
        if(keys[VK_DOWN]){rquad[2]+=0.12;}
    }
}

return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

int   cxBlock, cyBlock;

switch (message)
{
case WM_CREATE :
    if(!(hwndopen= CreateWindow (szChildClass, NULL,
        WS_CHILDWINDOW | WS_VISIBLE,
        0, 0, 0, 0,
        hwnd,(HMENU)(hID),
        (HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE),
        NULL)))
    {
        MessageBox(NULL,"子窗口创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }
    if (!(hdc=GetDC(hwndopen)))
    {
        MessageBox(NULL,"设备描述表创建失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if (!(PixelFormat=ChoosePixelFormat(hdc,&pfd)))
    {
        MessageBox(NULL,"未找到匹配的像素格式","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if(!SetPixelFormat(hdc,PixelFormat,&pfd))
    {
        MessageBox(NULL,"设置像素格式失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if (!(hrc=wglCreateContext(hdc)))
    {
        MessageBox(NULL,"获取渲染描述表失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }

    if(!wglMakeCurrent(hdc,hrc))
    {
        MessageBox(NULL,"渲染描述表激活失败","演示程序",MB_OK|MB_ICONINFORMATION);
        return 0;
    }
    return 0 ;

case WM_ACTIVATE:                           // Watch For Window Activate Message
    // LoWord Can Be WA_INACTIVE, WA_ACTIVE, WA_CLICKACTIVE,
    // The High-Order Word Specifies The Minimized State Of The Window Being Activated Or Deactivated.
    // A NonZero Value Indicates The Window Is Minimized.
    if ((LOWORD(wParam) != WA_INACTIVE) && !((BOOL)HIWORD(wParam)))
        active=TRUE;                        // Program Is Active
    else
        active=FALSE;                       // Program Is No Longer Active
    return 0;                               // Return To The Message Loop

case WM_SIZE :
    cxBlock = LOWORD (lParam);
    cyBlock = HIWORD (lParam);
    MoveWindow (hwndopen,
        5,5,
        (int)(cxBlock*0.80),(int)(cyBlock*0.98), TRUE) ;
    ReSizeGLScene((int)(cxBlock*0.80),(int)(cyBlock*0.97));
    return 0 ;

case WM_LBUTTONDOWN :
    MessageBeep (0) ;
    return 0 ;

case WM_KEYDOWN:
    keys[wParam] = TRUE;
    return 0;

case WM_KEYUP:
    keys[wParam] = FALSE;
    return 0;

case WM_CLOSE:
    DestroyWindow(hwnd);
    return 0;

case WM_DESTROY :
    if (hrc)
    {
        if (!wglMakeCurrent(hdc,NULL))
        {
            MessageBox(NULL,"DC和RC关联解除失败","演示程序",MB_OK | MB_ICONINFORMATION);
        }

        if (!wglDeleteContext(hrc))
        {
            MessageBox(NULL,"RC释放失败","演示程序",MB_OK | MB_ICONINFORMATION);
        }

        hrc=NULL;
    }

    if (!DestroyWindow(hwnd))
    {
        MessageBox(NULL,"窗口句柄释放失败","演示程序",MB_OK | MB_ICONINFORMATION);
        hwnd=NULL;
    }

    PostQuitMessage (0) ;
    return 0 ;

}
return DefWindowProc (hwnd, message, wParam, lParam) ;
  }

LRESULT CALLBACK OpenProc (HWND hwnd, UINT message,
                       WPARAM wParam, LPARAM lParam)
{
return DefWindowProc (hwnd, message, wParam, lParam) ;
}

ADDITION

My aim is to paint a clolor cube in the child window with OpenGL.The size of the child window is about 0.8 times the frame window's size.I will add a control panel in the rest of area of the frame window. My program can draw a color cube .But the problem is I can see all the 6 faces,and all the 12 edges of the cube.I'm not sure but it looks like the hidden-surface removal failed.

Here I provide a link to the image of the result.
http://svgeqg.blu.livefilestore.com/y1p_TRCQ495hxOztZy3oi5qZiDPdN9hQil0KLTY9I-7fFfqCuVr_FiyJ-dIlflN5eHCMqZo5smpUwTaFDxAelq_rjO5hTU5kVzS/colorcube.JPG?psid=1


问:
How to find a folder's size in Python 2.7 ?- an error
I use this code (in Python 2.7.8) in order to find a sub folder size in MB \ GB in one big directory:

```<code># -*- coding: cp1255 -*-
import os
def conv_MB_to_GB(input_megabyte):
        gigabyte = 1.0/1000/1000
        convert_gb = gigabyte * input_megabyte
        return convert_gb
def get_size(start_path = "."):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            total_size += os.path.getsize(fp)
    return  total_size/(1024*1024.0)
rootPath = r"G:\PROJECTS"
os.chdir(rootPath)
all_subdirs = [d for d in os.listdir('.') if os.path.isdir(d)]
for dirs in all_subdirs:
    dir = os.path.join(rootPath, dirs)
    os.chdir(dir)
    current = os.getcwd()
    print current
    if get_size(current) < 1000:
            print "%0.1fMB" % get_size(current)
    if get_size(current) > 1000:
            #print "%0.2fGB" % ((get_size(current))/1000) # this line do the same as the next line
            print "---%0.1fGB---" % (conv_MB_to_GB(get_size(current))*1000)
    print
</code>```

this code run perfectly, but if there is a text file with file name in Hebrew, i got an error (if the name file is english-there's no problem):

```<code>WindowsError: [Error 123] שם הקובץ,: 'G:\\PROJECTS\\mikta7\\gis\\?\xee\xf1\xee\xea \xe8\xf7\xf1\xe8 ?\xe7\xe3\xf9.txt'
</code>```

i also red how to read a file that can be saved as either ansi or unicode in python?

答:
Unfortunately I can't test this as I'm not on a machine with Python installed, but the following change should work:

```<code>for f in filenames:
    fp = os.path.join(dirpath, f.encode('utf-8'))
    total_size += os.path.getsize(fp)
</code>```

The addition is to encode the raw filename in a recognisable format - in this case, utf-8. Note that this is the default parameter for encode so it can theoretically be omitted.

For further references, see:

Python docs - encode

Body:
I use this code (in Python 2.7.8) in order to find a sub folder size in MB \ GB in one big directory:

# -*- coding: cp1255 -*-
import os
def conv_MB_to_GB(input_megabyte):
        gigabyte = 1.0/1000/1000
        convert_gb = gigabyte * input_megabyte
        return convert_gb
def get_size(start_path = "."):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(start_path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            total_size += os.path.getsize(fp)
    return  total_size/(1024*1024.0)
rootPath = r"G:\PROJECTS"
os.chdir(rootPath)
all_subdirs = [d for d in os.listdir('.') if os.path.isdir(d)]
for dirs in all_subdirs:
    dir = os.path.join(rootPath, dirs)
    os.chdir(dir)
    current = os.getcwd()
    print current
    if get_size(current) < 1000:
            print "%0.1fMB" % get_size(current)
    if get_size(current) > 1000:
            #print "%0.2fGB" % ((get_size(current))/1000) # this line do the same as the next line
            print "---%0.1fGB---" % (conv_MB_to_GB(get_size(current))*1000)
    print

this code run perfectly, but if there is a text file with file name in Hebrew, i got an error (if the name file is english-there's no problem):

WindowsError: [Error 123] שם הקובץ,: 'G:\\PROJECTS\\mikta7\\gis\\?\xee\xf1\xee\xea \xe8\xf7\xf1\xe8 ?\xe7\xe3\xf9.txt'

i also red how to read a file that can be saved as either ansi or unicode in python?

Body:
Unfortunately I can't test this as I'm not on a machine with Python installed, but the following change should work:

for f in filenames:
    fp = os.path.join(dirpath, f.encode('utf-8'))
    total_size += os.path.getsize(fp)

The addition is to encode the raw filename in a recognisable format - in this case, utf-8. Note that this is the default parameter for encode so it can theoretically be omitted.

For further references, see:

Python docs - encode


问:
helmignore double-star syntax is not supported in helm 3
I want to ignore specifics files in subchart folder (because some objects, like secrets, are created by all my subchart, so duplicated...). I don't know the depth of these objects. So I want to use this syntax in .helmignore :

charts/**/myfile.yaml
```

<p>But I got this error :</p>

<pre class="lang-sh prettyprint-override"><code>Error: double-star (**) syntax is not supported
</code>```

How can I do that in helm 3 ?

答:
Unfortunately, this feature doesn't supported nether in helm2 nor helm3.

helm2 source code: link

helm3 source code: link

Try to ignore it explicitly:

```<code>$ cat .helmignore
secrets
# or
./secrets/my-secret.yaml
</code>```

Body:
I want to ignore specifics files in subchart folder (because some objects, like secrets, are created by all my subchart, so duplicated...). I don't know the depth of these objects. So I want to use this syntax in .helmignore :

charts/**/myfile.yaml

But I got this error :

Error: double-star (**) syntax is not supported

How can I do that in helm 3 ?

Body:
Unfortunately, this feature doesn't supported nether in helm2 nor helm3.

helm2 source code: link

helm3 source code: link

Try to ignore it explicitly:

$ cat .helmignore
secrets
# or
./secrets/my-secret.yaml


问:
FFMPEG profile-level-id size is invalid
I'm trying to record a RTSP streaming from JVC KY-PZ 100.
So for that i'm using ffmpeg with some parameters like segmentation, hls, ts, m3u8 etc ...
i'm always getting an error The profile-level-id field size is invalid (41) and Error parsing AU headers

This is the output of FFPROBE to debug the RTSP

```<code>ffprobe -loglevel verbose  -i rtsp://jvc:0000@192.168.0.124:554/stream

ffprobe version 4.2.2 Copyright (c) 2007-2019 the FFmpeg developers
  built with Apple LLVM version 10.0.0 (clang-1000.11.45.5)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.2.2 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags='-I/Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk/Contents/Home/include/darwin' --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libsnappy --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
[tcp @ 0x7fa99ee001c0] Starting connection attempt to 192.168.0.124 port 554
[tcp @ 0x7fa99ee001c0] Successfully connected to 192.168.0.124 port 554
[rtsp @ 0x7fa99f807200] SDP:
v=0
o=- 1581949225269357 1 IN IP4 192.168.0.124
s=KY-PZ100
i=KY-PZ100
t=0 0
a=tool:LIVE555 Streaming Media v2013.10.03
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:KY-PZ100
a=x-qt-text-inf:KY-PZ100
m=audio 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:96
a=rtpmap:96 mpeg4-generic/48000/2
a=fmtp:96 streamtype=5;profile-level-id=41;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1190
a=control:track1
m=video 0 RTP/AVP 97
c=IN IP4 0.0.0.0
b=AS:1500
a=rtpmap:97 H264/90000
a=fmtp:97 packetization-mode=1;profile-level-id=4D401E;sprop-parameter-sets=Z01AHqtgUBf8uAqQEBAUAAAPpAADqYOlABksDcoUQDuLFIs=,aM48gA==
a=control:track2

[rtsp @ 0x7fa99f807200] The profile-level-id field size is invalid (41)
[rtsp @ 0x7fa99f807200] setting jitter buffer size to 500
    Last message repeated 1 times
[rtsp @ 0x7fa99f807200] Error parsing AU headers
    Last message repeated 4 times
[h264 @ 0x7fa9a0806600] Reinit context to 640x368, pix_fmt: yuv420p
[rtsp @ 0x7fa99f807200] Error parsing AU headers
    Last message repeated 235 times
[rtsp @ 0x7fa99f807200] max_analyze_duration 5000000 reached at 5005000 microseconds st:1
Input #0, rtsp, from 'rtsp://jvc:0000@192.168.0.124:554/stream':
  Metadata:
    title           : KY-PZ100
    comment         : KY-PZ100
  Duration: N/A, start: 0.066733, bitrate: N/A
    Stream #0:0: Audio: aac, 48000 Hz, stereo, fltp
    Stream #0:1: Video: h264 (Main), 1 reference frame, yuv420p(tv, bt709, progressive, left), 640x360 (640x368) [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc
</code>```

答:
The verification of SDP fmtp integer parameter ranges was fixed in c29d81e73641d0f58e6f058a095e18b99769dac1 but the patch is probably not released yet.

Compile ffmpeg from the latest git sources and retry.

Title: FFMPEG profile-level-id size is invalid

Body:
I'm trying to record a RTSP streaming from JVC KY-PZ 100.
So for that i'm using ffmpeg with some parameters like segmentation, hls, ts, m3u8 etc ...
i'm always getting an error The profile-level-id field size is invalid (41) and Error parsing AU headers

This is the output of FFPROBE to debug the RTSP

ffprobe -loglevel verbose  -i rtsp://jvc:0000@192.168.0.124:554/stream

ffprobe version 4.2.2 Copyright (c) 2007-2019 the FFmpeg developers
  built with Apple LLVM version 10.0.0 (clang-1000.11.45.5)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.2.2 --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags='-I/Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/adoptopenjdk-13.0.1.jdk/Contents/Home/include/darwin' --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libopus --enable-librubberband --enable-libsnappy --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librtmp --enable-libspeex --enable-libsoxr --enable-videotoolbox --disable-libjack --disable-indev=jack
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
[tcp @ 0x7fa99ee001c0] Starting connection attempt to 192.168.0.124 port 554
[tcp @ 0x7fa99ee001c0] Successfully connected to 192.168.0.124 port 554
[rtsp @ 0x7fa99f807200] SDP:
v=0
o=- 1581949225269357 1 IN IP4 192.168.0.124
s=KY-PZ100
i=KY-PZ100
t=0 0
a=tool:LIVE555 Streaming Media v2013.10.03
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:KY-PZ100
a=x-qt-text-inf:KY-PZ100
m=audio 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:96
a=rtpmap:96 mpeg4-generic/48000/2
a=fmtp:96 streamtype=5;profile-level-id=41;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1190
a=control:track1
m=video 0 RTP/AVP 97
c=IN IP4 0.0.0.0
b=AS:1500
a=rtpmap:97 H264/90000
a=fmtp:97 packetization-mode=1;profile-level-id=4D401E;sprop-parameter-sets=Z01AHqtgUBf8uAqQEBAUAAAPpAADqYOlABksDcoUQDuLFIs=,aM48gA==
a=control:track2

[rtsp @ 0x7fa99f807200] The profile-level-id field size is invalid (41)
[rtsp @ 0x7fa99f807200] setting jitter buffer size to 500
    Last message repeated 1 times
[rtsp @ 0x7fa99f807200] Error parsing AU headers
    Last message repeated 4 times
[h264 @ 0x7fa9a0806600] Reinit context to 640x368, pix_fmt: yuv420p
[rtsp @ 0x7fa99f807200] Error parsing AU headers
    Last message repeated 235 times
[rtsp @ 0x7fa99f807200] max_analyze_duration 5000000 reached at 5005000 microseconds st:1
Input #0, rtsp, from 'rtsp://jvc:0000@192.168.0.124:554/stream':
  Metadata:
    title           : KY-PZ100
    comment         : KY-PZ100
  Duration: N/A, start: 0.066733, bitrate: N/A
    Stream #0:0: Audio: aac, 48000 Hz, stereo, fltp
    Stream #0:1: Video: h264 (Main), 1 reference frame, yuv420p(tv, bt709, progressive, left), 640x360 (640x368) [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc


问:
How to concatenate strings in windows batch file for loop?
I'm familiar with Unix shell scripting, but new to windows scripting.

I have a list of strings containing str1, str2, str3...str10. I want to do like this:

```<code>for string in string_list
do
  var = string+"xyz"
  svn co var
end
</code>```

I do found some thread describing how to concatenate string in batch file. But it somehow doesn't work in for loop. So I'm still confusing about the batch syntax.

答:
A very simple example:

```<code>SET a=Hello
SET b=World
SET c=%a% %b%!
echo %c%
</code>```

The result should be:

```<code>Hello World!
</code>```

Body:
I'm familiar with Unix shell scripting, but new to windows scripting.

I have a list of strings containing str1, str2, str3...str10. I want to do like this:

for string in string_list
do
  var = string+"xyz"
  svn co var
end

I do found some thread describing how to concatenate string in batch file. But it somehow doesn't work in for loop. So I'm still confusing about the batch syntax.

Body:
A very simple example:

SET a=Hello
SET b=World
SET c=%a% %b%!
echo %c%

The result should be:

Hello World!


问:
Get parent Width and Height
I've create a custom view based on LinearLayout and I need to calculate the layout width and height according to the parent view but each time I use ((View)this.getParent()).getMeasuredWidth() I got 0 -  I guess that I called this function too early!

Any ideas to how accomplish this functionality?

答:
in Kotlin you can use like this :

```<code>   val height = (parent as View).height
</code>```

Title: Get parent Width and Height

Body:
in Kotlin you can use like this :

   val height = (parent as View).height


问:
Using custom class with getFieldDecorator (React, Ant Design)
Everything is ok if I use Ant Design TreeSelect component in form like this:

```<code><Form.Item>
    {getFieldDecorator('geo_objects_value', {
        rules: [{
            required: true,
            message: 'Warning msg'
        }],
    })(
        <TreeSelect
            treeData={treeGeoObjects}
            treeNodeFilterProp={'title'}
            treeCheckable={true}
            allowClear
            showCheckedStrategy={SHOW_PARENT}
            dropdownStyle={{maxHeight: 500, overflow: 'auto'}}
        />
    )}
</Form.Item>
</code>```

But if I try to use a custom class with the Ant Design Tree component, it will give a warning message: that means the value has not been received.

My custom class:

```<code>class Demo extends React.Component {
    constructor(props) {
        super(props);
        this.treeData = props.treeData;
        this.state = {
            expandedKeys: [],
            autoExpandParent: true,
            value: [],
        };
    }

    onExpand = expandedKeys => {
        this.setState({
            expandedKeys,
            autoExpandParent: false,
        });
    };

    onCheck = value => {
        this.setState({value});
        this.props.value = value;
        console.log('onCheck', this.props.value);
    };

    renderTreeNodes = data =>
        data.map(item => {
            if (item.children) {
                return (
                    <TreeNode title={item.title} key={item.key} dataRef={item}>
                        {this.renderTreeNodes(item.children)}
                    </TreeNode>
                );
            }
            return <TreeNode key={item.key} {...item} />;
        });

    render() {
        return (
            <Tree
                checkable
                onExpand={this.onExpand}
                expandedKeys={this.state.expandedKeys}
                autoExpandParent={this.state.autoExpandParent}
                onCheck={this.onCheck}
                checkedKeys={this.state.value}
            >
                {this.renderTreeNodes(this.treeData)}
            </Tree>
        );
    }
}
</code>```

Using custom class inside the form:

```<code><Form.Item>
    {getFieldDecorator('geo_objects_value', {
        rules: [{
            required: true,
            message: 'Warning msg'
        }],
    })(
        <Demo treeData={treeGeoObjects}/>
    )}
</Form.Item>
</code>```

What am I doing wrong? Why can't getFieldDecorator get the value from my class? Please help!

答:
Create a Component (or PureComponent).

Make sure the controlled value has the same name as the valuePropName.

Create a function that is triggered by onChange. This function will not only update the controlled value, but it will also trigger the controlled onChange handler.

class MyInput extends React.PureComponent {
  constructor(props) {
    super(props);
    const value = props.value || {};
    this.state = {
      // Same name as valuePropName in getFieldDecorator ('value' is default):
      // https://ant.design/components/form/?locale=en-US#getFieldDecorator(id,-options)-parameters
      value,
      // ...
    };
  }

  handleChange = (value) => {
    this.setState({ value });
    const { onChange } = this.props;
    if (onChange) {
      // This will provide the form with changes
      onChange({ ...this.state, ...{ value } });
    }
  }

  render() {
    const { value } = this.state;
    return (
      <Input
        value={value}
        onChange={this.handleChange}
      />
    );
  }
}
```

Body:
Everything is ok if I use Ant Design TreeSelect component in form like this:

<Form.Item>
    {getFieldDecorator('geo_objects_value', {
        rules: [{
            required: true,
            message: 'Warning msg'
        }],
    })(
        <TreeSelect
            treeData={treeGeoObjects}
            treeNodeFilterProp={'title'}
            treeCheckable={true}
            allowClear
            showCheckedStrategy={SHOW_PARENT}
            dropdownStyle={{maxHeight: 500, overflow: 'auto'}}
        />
    )}
</Form.Item>

But if I try to use a custom class with the Ant Design Tree component, it will give a warning message: that means the value has not been received.

My custom class:

class Demo extends React.Component {
    constructor(props) {
        super(props);
        this.treeData = props.treeData;
        this.state = {
            expandedKeys: [],
            autoExpandParent: true,
            value: [],
        };
    }

    onExpand = expandedKeys => {
        this.setState({
            expandedKeys,
            autoExpandParent: false,
        });
    };

    onCheck = value => {
        this.setState({value});
        this.props.value = value;
        console.log('onCheck', this.props.value);
    };

    renderTreeNodes = data =>
        data.map(item => {
            if (item.children) {
                return (
                    <TreeNode title={item.title} key={item.key} dataRef={item}>
                        {this.renderTreeNodes(item.children)}
                    </TreeNode>
                );
            }
            return <TreeNode key={item.key} {...item} />;
        });

    render() {
        return (
            <Tree
                checkable
                onExpand={this.onExpand}
                expandedKeys={this.state.expandedKeys}
                autoExpandParent={this.state.autoExpandParent}
                onCheck={this.onCheck}
                checkedKeys={this.state.value}
            >
                {this.renderTreeNodes(this.treeData)}
            </Tree>
        );
    }
}

Using custom class inside the form:

<Form.Item>
    {getFieldDecorator('geo_objects_value', {
        rules: [{
            required: true,
            message: 'Warning msg'
        }],
    })(
        <Demo treeData={treeGeoObjects}/>
    )}
</Form.Item>

What am I doing wrong? Why can't getFieldDecorator get the value from my class? Please help!


问:
If column contain string from array of strings create new column with
I have a data frame that look like this

```<code>     Col1     Col2
0     22     Apple
1     43     Carrot
2     54     Orange
3     74     Spinach
4     14     Cucumber
</code>```

And I need to add new column with the category "Fruit" , "Vegetable" or "Leaf"
I created a list for each category

```<code>Fru = {'Apple','Orange', 'Grape', 'Blueberry', 'Strawberry'}
Veg = {'Cucumber','Carrot','Broccoli', 'Onion'}
Leaf = {'Lettuce', 'Kale', 'Spinach'}
</code>```

And the result should look like this

```<code>    Col1      Col2     Category
0     22     Apple      Fruit
1     43     Carrot     Vegetable
2     54     Orange     Fruit
3     74     Spinach    Leaf
4     14     Cucumber   Vegetable
</code>```

I tried np.where  and contains yet both functions give: 'in ' requires string as left operand, not set

答:
Another approach you can try with a for loop:

```<code>df = pd.DataFrame({'Col1': [22,43,54,74,14], 'Col2': ['Apple','Carrot','Orange','Spinach','Cucumber']})

Fruit = ['Apple','Orange', 'Grape', 'Blueberry', 'Strawberry']
Vegetable = ['Cucumber','Carrot','Broccoli', 'Onion']
Leaf = ['Lettuce', 'Kale', 'Spinach']

mylist = []
for i in df['Col2']:
    if i in Fruit:
        mylist.append('Fruit')
    elif i in Vegetable:
        mylist.append('Vegetable')
    elif i in Leaf:
        mylist.append('Leaf')

df['Category'] = mylist

print(df)
   Col1      Col2   Category
0    22     Apple      Fruit
1    43    Carrot  Vegetable
2    54    Orange      Fruit
3    74   Spinach       Leaf
4    14  Cucumber  Vegetable
</code>```

Body:
I have a data frame that look like this

     Col1     Col2
0     22     Apple
1     43     Carrot
2     54     Orange
3     74     Spinach
4     14     Cucumber

And I need to add new column with the category "Fruit" , "Vegetable" or "Leaf"
I created a list for each category

Fru = {'Apple','Orange', 'Grape', 'Blueberry', 'Strawberry'}
Veg = {'Cucumber','Carrot','Broccoli', 'Onion'}
Leaf = {'Lettuce', 'Kale', 'Spinach'}

And the result should look like this

    Col1      Col2     Category
0     22     Apple      Fruit
1     43     Carrot     Vegetable
2     54     Orange     Fruit
3     74     Spinach    Leaf
4     14     Cucumber   Vegetable

I tried np.where  and contains yet both functions give: 'in ' requires string as left operand, not set

Body:
Another approach you can try with a for loop:

df = pd.DataFrame({'Col1': [22,43,54,74,14], 'Col2': ['Apple','Carrot','Orange','Spinach','Cucumber']})

Fruit = ['Apple','Orange', 'Grape', 'Blueberry', 'Strawberry']
Vegetable = ['Cucumber','Carrot','Broccoli', 'Onion']
Leaf = ['Lettuce', 'Kale', 'Spinach']

mylist = []
for i in df['Col2']:
    if i in Fruit:
        mylist.append('Fruit')
    elif i in Vegetable:
        mylist.append('Vegetable')
    elif i in Leaf:
        mylist.append('Leaf')

df['Category'] = mylist

print(df)
   Col1      Col2   Category
0    22     Apple      Fruit
1    43    Carrot  Vegetable
2    54    Orange      Fruit
3    74   Spinach       Leaf
4    14  Cucumber  Vegetable


问:
Align Image View without stopping a stackView auto-resizing
I am currently facing an issue where I have a horizontal stack view with a UILabel and a ImageView. I am needing the stackView to dynamically change height depending on how many lines of text there is. I am also wanting the imageView to be aligned with the bottom of the UILabel(even when there is a second line).

I have currently tried:

Adding a UIView and aligning the ImageView in it. This stops the stackView auto-resizing.

Changing the Content Mode to bottom doesn't work either as I am wanting aspect fit.

Thanks for any suggestions!

答:
You should be able to get your desired result pretty easily.

Constrain your Stack View to all 4 sides, using however much top/bottom and left/right "padding" you want.

Give your Image View a Width constraint (I'm guessing you want it around 24), and an Aspect Ratio of 1:1. That will keep it from stretching vertically. Content Mode: Aspect Fit

Set your Stack View properties to:

And... you should be all set.


问:
How to iterate the TValue type property in Blazor

I need to iterate the TValue type property in Blazor.

Component Tag as MYComponent.

```<code><select>
@foreach (var item in this.Value(TValue))
        {
            <option selected value=@item></option>
        }
</select>

@code {
public class MYComponent {
           public TValue Value {get;set;}
           private string[] MyValue = new string[] {"Value1", "Value2"};
}
}
</code>```

答:
If I understand well your question, you can achieve it by using reflexion : </p>

<pre class="lang-cs prettyprint-override"><code>@foreach (var item in GetProperties(TValue))
{
   <option selected value=@item></option>
}
</select>
@code {
    public class MYComponent
    {
        public TValue Value {get;set;}
        private string[] MyValue = new string[] {"Value1", "Value2"};
        public IEnumerable<string> GetProperties()
        {
              return typeof(TValue).GetProperties().Select(p => p.Name);
        }
    }
}
</code>```

Body:
I need to iterate the TValue type property in Blazor.

Component Tag as MYComponent.

<select>
@foreach (var item in this.Value(TValue))
        {
            <option selected value=@item></option>
        }
</select>

@code {
public class MYComponent {
           public TValue Value {get;set;}
           private string[] MyValue = new string[] {"Value1", "Value2"};
}
}

Body:
If I understand well your question, you can achieve it by using reflexion :

@foreach (var item in GetProperties(TValue))
{
   <option selected value=@item></option>
}
</select>
@code {
    public class MYComponent
    {
        public TValue Value {get;set;}
        private string[] MyValue = new string[] {"Value1", "Value2"};
        public IEnumerable<string> GetProperties()
        {
              return typeof(TValue).GetProperties().Select(p => p.Name);
        }
    }
}


问:
H2OGridSearch H2OGBM pyspark: NullPointerException in extractH2OParameters
I'm trying to run a grid search for Gradient Boosting Machine in pyspark with H2O Sparkling Water.

Produced a reproducible example with the famous iris dataset.

```<code>from pysparkling import H2OContext, H2OConf
import pyspark
from pyspark.sql.types import StructType, StructField, FloatType, StringType
from pyspark.conf import SparkConf
from pyspark.sql import SQLContext
conf = SparkConf()
conf.setMaster("local").setAppName("test")
conf.set("spark.sql.shuffle.partitions", 3)
conf.set("spark.default.parallelism", 3)
conf.set("spark.debug.maxToStringFields", 100)
sc = pyspark.SparkContext(conf=conf)
sqlContext = SQLContext(sc)
hc = H2OContext.getOrCreate(sc, H2OConf(sc).set_internal_cluster_mode())
schema = StructType([
    StructField("sepal_length", FloatType(), True),
    StructField("sepal_width", FloatType(), True),
    StructField("petal_length", FloatType(), True),
    StructField("petal_width", FloatType(), True),
    StructField("class", StringType(), True)])
iris_df = sqlContext.read \
        .format('com.databricks.spark.csv') \
        .option('header', 'false') \
        .option('delimiter', ',') \
        .schema(schema) \
        .load('../../../../Downloads/iris.data')
</code>```

If I try to follow this page of H2O docs and just translate to python

```<code>gbm_params = {'learnRate': [0.01, 0.1],
              'ntrees': [100 , 200, 300, 500]}
gbm_grid = H2OGridSearch()\
    .setLabelCol("class") \
    .setHyperParameters(gbm_params)\
    .setAlgo(H2OGBM().setMaxDepth(30))

model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
</code>```

I get an internal NullPointerException, I guess there's something missing in the configuration.

```<code>Py4JJavaError: An error occurred while calling o111.fit.
: java.lang.NullPointerException
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.extractH2OParameters(H2OGridSearch.scala:352)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.fit(H2OGridSearch.scala:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:282)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Unknown Source)
</code>```

If I try to rewrite it in a different way, I get a different error,

```<code>gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         hyperParameters={'learnRate': [0.01, 0.1]},
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
</code>```

This is the output, no matter how do I change the hyperparameters,

```<code>Py4JJavaError: An error occurred while calling o1817.fit.
: java.lang.NoSuchFieldException: learnRate
    at java.lang.Class.getField(Unknown Source)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.findField(H2OGridSearch.scala:170)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.processHyperParams(H2OGridSearch.scala:154)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.fit(H2OGridSearch.scala:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:282)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Unknown Source)
</code>```

The following works, however it is not useful since there is no grid,

```<code>gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         #hyperParameters=gbm_params,
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
model.stages[0].transform(iris_df).head()
</code>```

And finally, just to be sure that learnRate is a parameter of H2OGBM, this also works,

```<code>gbm_model = H2OGBM(labelCol='class',
                   withDetailedPredictionCol=True).setLearnRate(0.01).setMaxDepth(5).setNtrees(100)

model_pipeline = Pipeline().setStages([gbm_model])
model = model_pipeline.fit(iris_df)
model.stages[0].transform(iris_df).head()
</code>```

EDIT: missing imports

```<code>from pyspark.ml.pipeline import Pipeline
from ai.h2o.sparkling.ml.algos import H2OGridSearch
from ai.h2o.sparkling.ml.algos import H2OGBM
</code>```

and sparking water version

```<code>h2o-pysparkling-2-4       3.28.0.1-1               pypi_0    pypi
</code>```

EDIT after comments for Spark/H2O/Java versions

Spark: 2.4.4

H2O: 3.28.0.3

Java: 1.8.0_232

EDIT java -version

```<code>openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-8u242-b08-0ubuntu3~16.04-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)
</code>```

Get the same error if I use learn_rate instead of learnRate.

```<code>gbm_params = {'learnRate': [0.01, 0.1],
              'ntrees': [100 , 200, 300, 500]}
gbm_grid = H2OGridSearch()\
    .setLabelCol("class") \
    .setHyperParameters(gbm_params)\
    .setAlgo(H2OGBM().setMaxDepth(30))

model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
</code>```0

...

```<code>gbm_params = {'learnRate': [0.01, 0.1],
              'ntrees': [100 , 200, 300, 500]}
gbm_grid = H2OGridSearch()\
    .setLabelCol("class") \
    .setHyperParameters(gbm_params)\
    .setAlgo(H2OGBM().setMaxDepth(30))

model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
</code>```1

答:
There's a workaround here I did not notice (probably I should have posted it as a bug in github in the first place).</p>

```<code>gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         hyperParameters={'_learn_rate':[0.01, 0.1], '_ntrees': [100, 200]},
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
model.stages[0].transform(iris_df).head()
</code>```

Body:
I'm trying to run a grid search for Gradient Boosting Machine in pyspark with H2O Sparkling Water.

Produced a reproducible example with the famous iris dataset.

from pysparkling import H2OContext, H2OConf
import pyspark
from pyspark.sql.types import StructType, StructField, FloatType, StringType
from pyspark.conf import SparkConf
from pyspark.sql import SQLContext
conf = SparkConf()
conf.setMaster("local").setAppName("test")
conf.set("spark.sql.shuffle.partitions", 3)
conf.set("spark.default.parallelism", 3)
conf.set("spark.debug.maxToStringFields", 100)
sc = pyspark.SparkContext(conf=conf)
sqlContext = SQLContext(sc)
hc = H2OContext.getOrCreate(sc, H2OConf(sc).set_internal_cluster_mode())
schema = StructType([
    StructField("sepal_length", FloatType(), True),
    StructField("sepal_width", FloatType(), True),
    StructField("petal_length", FloatType(), True),
    StructField("petal_width", FloatType(), True),
    StructField("class", StringType(), True)])
iris_df = sqlContext.read \
        .format('com.databricks.spark.csv') \
        .option('header', 'false') \
        .option('delimiter', ',') \
        .schema(schema) \
        .load('../../../../Downloads/iris.data')

If I try to follow this page of H2O docs and just translate to python

gbm_params = {'learnRate': [0.01, 0.1],
              'ntrees': [100 , 200, 300, 500]}
gbm_grid = H2OGridSearch()\
    .setLabelCol("class") \
    .setHyperParameters(gbm_params)\
    .setAlgo(H2OGBM().setMaxDepth(30))

model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)

I get an internal NullPointerException, I guess there's something missing in the configuration.

Py4JJavaError: An error occurred while calling o111.fit.
: java.lang.NullPointerException
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.extractH2OParameters(H2OGridSearch.scala:352)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.fit(H2OGridSearch.scala:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:282)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Unknown Source)

If I try to rewrite it in a different way, I get a different error,

gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         hyperParameters={'learnRate': [0.01, 0.1]},
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)

This is the output, no matter how do I change the hyperparameters,

Py4JJavaError: An error occurred while calling o1817.fit.
: java.lang.NoSuchFieldException: learnRate
    at java.lang.Class.getField(Unknown Source)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.findField(H2OGridSearch.scala:170)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.processHyperParams(H2OGridSearch.scala:154)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.fit(H2OGridSearch.scala:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:282)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Unknown Source)

The following works, however it is not useful since there is no grid,

gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         #hyperParameters=gbm_params,
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
model.stages[0].transform(iris_df).head()

And finally, just to be sure that learnRate is a parameter of H2OGBM, this also works,

gbm_model = H2OGBM(labelCol='class',
                   withDetailedPredictionCol=True).setLearnRate(0.01).setMaxDepth(5).setNtrees(100)

model_pipeline = Pipeline().setStages([gbm_model])
model = model_pipeline.fit(iris_df)
model.stages[0].transform(iris_df).head()

EDIT: missing imports

from pyspark.ml.pipeline import Pipeline
from ai.h2o.sparkling.ml.algos import H2OGridSearch
from ai.h2o.sparkling.ml.algos import H2OGBM

and sparking water version

h2o-pysparkling-2-4       3.28.0.1-1               pypi_0    pypi

EDIT after comments for Spark/H2O/Java versions

Spark: 2.4.4

H2O: 3.28.0.3

Java: 1.8.0_232

EDIT java -version

openjdk version "1.8.0_242"
OpenJDK Runtime Environment (build 1.8.0_242-8u242-b08-0ubuntu3~16.04-b08)
OpenJDK 64-Bit Server VM (build 25.242-b08, mixed mode)

Get the same error if I use learn_rate instead of learnRate.

gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         hyperParameters={'learn_rate': [0.01, 0.1]},
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)

...

Py4JJavaError: An error occurred while calling o1376.fit.
: java.lang.NoSuchFieldException: learn_rate
    at java.lang.Class.getField(Class.java:1703)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.findField(H2OGridSearch.scala:170)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.processHyperParams(H2OGridSearch.scala:154)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.fit(H2OGridSearch.scala:71)
    at ai.h2o.sparkling.ml.algos.H2OGridSearch.fit(H2OGridSearch.scala:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:282)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Thread.java:748)

Body:
There's a workaround here I did not notice (probably I should have posted it as a bug in github in the first place).

gbm_grid = H2OGridSearch(algo=H2OGBM().setMaxDepth(30),
                         hyperParameters={'_learn_rate':[0.01, 0.1], '_ntrees': [100, 200]},
                         withDetailedPredictionCol=True,
                         labelCol='class',
                         stoppingMetric="AUC")
model_pipeline = Pipeline().setStages([gbm_grid])
model = model_pipeline.fit(iris_df)
model.stages[0].transform(iris_df).head()