问:
Apply select2 on dynamically loaded external html component
When loading a page, it loads another html page inside it and the html page contains select, which I want to apply select2 on it.

The very basic page contains

```<code><select class="selectAddItem" id="selectAddItem" name="selectAddItem" style="width: 150px;" class="required">
  <option value="">--- Please Select---</option>
  <option value="1">Movie</option>
  <option value="2">Actor or Actress</option>
</select>
<div class="well" id="well"></div>
</code>```

and when I select an item, it loads an external html page inside by

```<code>$(document).on('change','#selectAddItem',function(){
  if(this.value==1) {
    $("#well").load("/showAddMovie");
  } else {
    $("#well").load("/showAddActor");
  }
  $.getScript("../static/js/select2.min.js");
  $.getScript("../static/js/additem.js");
  $(".js-example-basic-multiple").select2({
      width: "80%",
      tags: true
  });;
});
</code>```

The showAddMovie will load html page containing select and I want to apply select 2 on the loaded page. The external html contains something like below.

```<code><select class="js-example-basic-multiple" multiple="multiple">
  <option value="AL">Alabama</option>
  <option value="Am">Amalapuram</option>
  <option value="An">Anakapalli</option>
  <option value="Ak">Akkayapalem</option>
  <option value="WY">Wyoming</option>
</select>
</code>```

However, select2 is not applied in my code. Any idea? Thanks.

答:
This call is an ajax call $("#well").load("/showAddMovie");

You need to specify callback function in the second parameter so that once the data is loaded then you do further processing inside the callback function.
$("#well").load("/showAddMovie", function(responseTxt, statusTxt, xhr){
        if(statusTxt == "success")
            console.log("loaded successfully!");
        if(statusTxt == "error")
            console.log("Error: " + xhr.status + ": " + xhr.statusText);
    });

Also as suggested by MrCode that $.getScript is also async call, you may want to use $.when to combine async calls and do processing once all calls are resolved.

Body:
When loading a page, it loads another html page inside it and the html page contains select, which I want to apply select2 on it.

The very basic page contains

<select class="selectAddItem" id="selectAddItem" name="selectAddItem" style="width: 150px;" class="required">
  <option value="">--- Please Select---</option>
  <option value="1">Movie</option>
  <option value="2">Actor or Actress</option>
</select>

and when I select an item, it loads an external html page inside by

$(document).on('change','#selectAddItem',function(){
  if(this.value==1) {
    $("#well").load("/showAddMovie");
  } else {
    $("#well").load("/showAddActor");
  }
  $.getScript("../static/js/select2.min.js");
  $.getScript("../static/js/additem.js");
  $(".js-example-basic-multiple").select2({
      width: "80%",
      tags: true
  });;
});

The showAddMovie will load html page containing select and I want to apply select 2 on the loaded page. The external html contains something like below.

<select class="js-example-basic-multiple" multiple="multiple">
  <option value="AL">Alabama</option>
  <option value="Am">Amalapuram</option>
  <option value="An">Anakapalli</option>
  <option value="Ak">Akkayapalem</option>
  <option value="WY">Wyoming</option>
</select>

However, select2 is not applied in my code. Any idea? Thanks.


来源: stackexchange

问:
Can't draw on double buffered form
In my form class I have overridden the OnPaint method

```<code>protected override void OnPaint(PaintEventArgs e)
{
    using (Graphics g = e.Graphics)
    {
        g.DrawImage(player.Sprite, new Rectangle(player.X, player.Y, 20, 20));
    }
    base.OnPaint(e);
}
</code>```

I have a timer, that does this.Invalidate() on Tick, and the image is flickering. I've set this.DoubleBuffered = true in form constructor, and now my form does not even show anything, and if I resize it, it behaves like this:

What is that double-buffer thing that I am missing?

答:
```<code>using (Graphics g = e.Graphics)
</code>```

The using keyword is the bug in this code.  In essence it killed the double-buffer and the normal painting cycle cannot continue.  Where "normal" is the content of the buffer getting blitted to the screen after your OnPaint() method completes.  This screws up both the rendering of the background, which is why you see the back of the monitor, and the foreground, the image you drew.

Golden rule for using (or calling Dispose) is that you should only ever do that when you created the object.  If you didn't, like you did not in this case, then you cannot assume that you "own" the object and you have to rely on the caller of your code to take care of it.  Which it does, no need to help.

Fix:

```<code>e.Graphics.DrawImage(player.Sprite, new Rectangle(player.X, player.Y, 20, 20));
base.OnPaint(e);
</code>```

ContentLicense: CC BY-SA 3.0

Title: Can't draw on double buffered form

Body:
In my form class I have overridden the OnPaint method

protected override void OnPaint(PaintEventArgs e)
{
    using (Graphics g = e.Graphics)
    {
        g.DrawImage(player.Sprite, new Rectangle(player.X, player.Y, 20, 20));
    }
    base.OnPaint(e);
}

I have a timer, that does this.Invalidate() on Tick, and the image is flickering. I've set this.DoubleBuffered = true in form constructor, and now my form does not even show anything, and if I resize it, it behaves like this:

What is that double-buffer thing that I am missing?

Body:
using (Graphics g = e.Graphics)

The using keyword is the bug in this code.  In essence it killed the double-buffer and the normal painting cycle cannot continue.  Where "normal" is the content of the buffer getting blitted to the screen after your OnPaint() method completes.  This screws up both the rendering of the background, which is why you see the back of the monitor, and the foreground, the image you drew.

Golden rule for using (or calling Dispose) is that you should only ever do that when you created the object.  If you didn't, like you did not in this case, then you cannot assume that you "own" the object and you have to rely on the caller of your code to take care of it.  Which it does, no need to help.

Fix:

e.Graphics.DrawImage(player.Sprite, new Rectangle(player.X, player.Y, 20, 20));
base.OnPaint(e);


问:
Eclipse - how to auto-close quotation mark
I thought this was the default behavior, but my Java editor refuses to auto complete quotation marks, even though it will auto-complete parentheses and brackets.

For example, when I type

```
<code>
list.add("
</code>
```

it refuses to auto-complete.

Is there a place to set this in Eclipse preferences?  It seems like there are about 7,000 sub menus, but I couldn't find it anywhere.

答:
Hmm, auto-completion is the default behavior, at least as of Helios version, so maybe yours got disabled by accident? I found the setting in Window > Preferences > Java > Editor > Typing. Near the top I have an "Automatically close" fieldset that includes "Strings". Hopefully that clears up the issue.

Just to be very explicit: When I type

```<code>list.add("
</code>```

what I see is

```<code>list.add("")
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I thought this was the default behavior, but my Java editor refuses to auto complete quotation marks, even though it will auto-complete parentheses and brackets.

For example, when I type

list.add("

it refuses to auto-complete.

Is there a place to set this in Eclipse preferences?  It seems like there are about 7,000 sub menus, but I couldn't find it anywhere.

Body:
Hmm, auto-completion is the default behavior, at least as of Helios version, so maybe yours got disabled by accident? I found the setting in Window > Preferences > Java > Editor > Typing. Near the top I have an "Automatically close" fieldset that includes "Strings". Hopefully that clears up the issue.

Just to be very explicit: When I type

list.add("

what I see is

list.add("")


问:
how to find and click elements have a specific class and doesn't have a specific class?
in fact,  I wanna find elements that have a specific class and doesn't have a specific class, for example, I mean this is code.

in this code, we have toggle-like and has-like but I wanna find all of the elements that have toggle-like but doesn't have has-like

please if you can write javascript and jquery code.

```<code> <button class="widget-button toggle-like has-like fade-out no-text" aria-label="شما این نوشته را پسندیده‌اید" title="شما این نوشته را پسندیده‌اید" disabled="true">
    <i class="fa fa-heart" aria-hidden="true"></i>
</button>
</code>```

=================================

```<code>var sad = document.querySelectorAll("button:not([.has-like])");
    for (var i = 0; i < happy.length; i++) {
        sad[i].click();
    }
</code>```

答: The dot before the class name is missing. When you put the dot '.', that way the Jquery knows you are referring to a class name.</p>

Body:
in fact,  I wanna find elements that have a specific class and doesn't have a specific class, for example, I mean this is code.

in this code, we have toggle-like and has-like but I wanna find all of the elements that have toggle-like but doesn't have has-like

please if you can write javascript and jquery code.

 <button class="widget-button toggle-like has-like fade-out no-text" aria-label="شما این نوشته را پسندیده‌اید" title="شما این نوشته را پسندیده‌اید" disabled="true">

</button>

=================================

var sad = document.querySelectorAll("button:not([.has-like])");
    for (var i = 0; i < happy.length; i++) {
        sad[i].click();
    }


问:
Smooth frequency change
I'm trying to continuously play a sound, whichs frequency should be changed smoothley. For example, my AudioTrack is currently playing on a frequency of 100 Hz, and the new frequency is 1000 Hz. Then I don't want the frequency to jump, but to smoothley adapt to the changes. My current code looks like this:

```<code>int buffSize = AudioTrack.getMinBufferSize(sampleRate,
                                           AudioFormat.CHANNEL_OUT_MONO,
                                           AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                                       AudioFormat.CHANNEL_OUT_MONO,
                                       AudioFormat.ENCODING_PCM_16BIT, buffSize,
                                       AudioTrack.MODE_STREAM);
short samples[] = new short[buffSize];
int amp = 10000;
double twopi = 8. * Math.atan(1.);
double phase = 0.0;
audioTrack.play();
while (playing)
{
    double newFrequency = getFrequency();
    for (int i = 0; i < buffSize; i++)
    {
        samples[i] = (short) (amp * Math.sin(phase));
        phase += twopi * newFrequency / sampleRate;
    }
    audioTrack.write(samples, 0, buffSize);
}
audioTrack.stop();
audioTrack.release();
</code>```

This, of course, is run in the background. My sampleRate is automatically set to the lowest possible value:

```<code>private int getMinSampleRate()
{
    for (int i = 1; i < 100000; i++)
        if (AudioTrack.getMinBufferSize(i, AudioFormat.CHANNEL_OUT_MONO,
                                        AudioFormat.ENCODING_PCM_16BIT) > 0)
            return i;

    return -1;
}
</code>```

答:
You can use a low-pass filter to smooth the transition. Here's another example.

```<code>double currentFrequency = getFrequency();
double smoothing  = 10;   // calculate based on your sample rate and desired time delta for the change
while (playing)
{
    double newFrequency = getFrequency();
    for (int i = 0; i < buffSize; i++)
    {
        // because you are filling the buffer, deltaTime will be a constant: the time between samples
        currentFrequency += deltaTime * ( newFrequency - currentFrequency ) / smoothing;
        samples[i] = (short) (amp * Math.sin(phase));
        phase += twopi * currentFrequency / sampleRate;
    }
    audioTrack.write(samples, 0, buffSize);
}
</code>```

Keep a historical record of the frequency and slowly change it towards you new value using incremental steps, based on the delta.  For large deltas, the value will change faster at the beginning and then slower near the end.  IIRC, this is called a first-order filter because you aren't controlling the acceleration of the change.  A second order filter will smooth the acceleration.

There are lots of different techniques, check out the filters at Wikipedia.

Title: Smooth frequency change

Body:
I'm trying to continuously play a sound, whichs frequency should be changed smoothley. For example, my AudioTrack is currently playing on a frequency of 100 Hz, and the new frequency is 1000 Hz. Then I don't want the frequency to jump, but to smoothley adapt to the changes. My current code looks like this:

int buffSize = AudioTrack.getMinBufferSize(sampleRate,
                                           AudioFormat.CHANNEL_OUT_MONO,
                                           AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
                                       AudioFormat.CHANNEL_OUT_MONO,
                                       AudioFormat.ENCODING_PCM_16BIT, buffSize,
                                       AudioTrack.MODE_STREAM);
short samples[] = new short[buffSize];
int amp = 10000;
double twopi = 8. * Math.atan(1.);
double phase = 0.0;
audioTrack.play();
while (playing)
{
    double newFrequency = getFrequency();
    for (int i = 0; i < buffSize; i++)
    {
        samples[i] = (short) (amp * Math.sin(phase));
        phase += twopi * newFrequency / sampleRate;
    }
    audioTrack.write(samples, 0, buffSize);
}
audioTrack.stop();
audioTrack.release();

This, of course, is run in the background. My sampleRate is automatically set to the lowest possible value:

private int getMinSampleRate()
{
    for (int i = 1; i < 100000; i++)
        if (AudioTrack.getMinBufferSize(i, AudioFormat.CHANNEL_OUT_MONO,
                                        AudioFormat.ENCODING_PCM_16BIT) > 0)
            return i;

    return -1;
}

Body:
You can use a low-pass filter to smooth the transition. Here's another example.

double currentFrequency = getFrequency();
double smoothing  = 10;   // calculate based on your sample rate and desired time delta for the change
while (playing)
{
    double newFrequency = getFrequency();
    for (int i = 0; i < buffSize; i++)
    {
        // because you are filling the buffer, deltaTime will be a constant: the time between samples
        currentFrequency += deltaTime * ( newFrequency - currentFrequency ) / smoothing;
        samples[i] = (short) (amp * Math.sin(phase));
        phase += twopi * currentFrequency / sampleRate;
    }
    audioTrack.write(samples, 0, buffSize);
}

Keep a historical record of the frequency and slowly change it towards you new value using incremental steps, based on the delta.  For large deltas, the value will change faster at the beginning and then slower near the end.  IIRC, this is called a first-order filter because you aren't controlling the acceleration of the change.  A second order filter will smooth the acceleration.

There are lots of different techniques, check out the filters at Wikipedia.


问:
Full group by query similar to mysql
Sample mysql query:

```<code>select error_number, query, count(*) as cnt from mytable group by error_number;
</code>```

This query works in mysql even if both the columns (error_number and query) are not part of aggregation. It shows a random record for "query" column in such cases.

This does not seem to be possible in Kibana. I have to group by error_number AND query. I want to group by only error_number and still see a random "query" column from that group.

Is it possible in Kibana? if yes, how?

答:
If the max value query for each error number counts as being random, then you can try the following query:</p>

```<code>select
    error_number,
    max(query) as query,
    count(*) as cnt
from mytable
group by error_number;
</code>```

Title: Full group by query similar to mysql

Body:
Sample mysql query:

select error_number, query, count(*) as cnt from mytable group by error_number;

This query works in mysql even if both the columns (error_number and query) are not part of aggregation. It shows a random record for "query" column in such cases.

This does not seem to be possible in Kibana. I have to group by error_number AND query. I want to group by only error_number and still see a random "query" column from that group.

Is it possible in Kibana? if yes, how?

Body:
If the max value query for each error number counts as being random, then you can try the following query:

select
    error_number,
    max(query) as query,
    count(*) as cnt
from mytable
group by error_number;


问:
bash: find all regex in file and put into array
I have a template config file with PlaceHolders, and i want to find all those PlaceHolders and put inside an array.

The curent state:

I can find all the PlaceHolders in file only if there is no more than one PlaceHolder in a line.

For example, this is my template file:

```<code>upstream portal {
   server {{UNICORN_SERVICE_NAME}}:{{UNICORN_SERVICE_PORT}};
}

server {
  listen *:80 default_server;
  server_name {{APP_HOST}};
  server_tokens off;
  root /dev/null;

  # Increase this if you want to upload large attachments
  # Or if you want to accept large git objects over http
  client_max_body_size {{NGINX_MAX_UPLOAD_SIZE}};

  location {{GITLAB_RELATIVE_URL_ROOT}}/ {
    root /var/lib/nginx/portal;
    # serve static files from defined root folder;.
    # @gitlab is a named location for the upstream fallback, see below
  }
  }
</code>```

this is the code i use to find the PlaceHolders:

```<code>matches_bloc=$(awk 'match($0, /(\{\{)([^{]*)(\}\})/) {
                    print substr($0, RSTART, RLENGTH)
                }' ${currFile})

            # convert 'matches_bloc' into array
            matches=()
            echo "Matches:"
            while read -r line; do
                matches+=("$line")
                echo "  - ${line}"
            done <<< "$matches_bloc"
</code>```

in this example the matches result will be:

Matches:

    - {{UNICORN_SERVICE_NAME}}

    - {{APP_HOST}}

    - {{NGINX_MAX_UPLOAD_SIZE}}

    - {{GITLAB_RELATIVE_URL_ROOT}}

You can notice that there are 5 PlaceHolders in the file and only 4 matches.

The missing match is: {{UNICORN_SERVICE_PORT}}, because there is already another match in the same line.

My question is:

How can i find all the matches in the file regardless of the line?

答:
Find all variables in a template file and put them in an array.

With GNU grep:

```<code>array=( $(grep -Po '{{.*?}}' file) )
declare -p array
</code>```

Output:

```
declare -a array='([0]="{{UNICORN_SERVICE_NAME}}" [1]="{{UNICORN_SERVICE_PORT}}" [2]="{{APP_HOST}}" [3]="{{NGINX_MAX_UPLOAD_SIZE}}" [4]="{{GITLAB_RELATIVE_URL_ROOT}}")'
```

-P: Interpret {{.*?}} as a Perl regular expression.

-o: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

* The preceding expression can match zero or more times. With ? the * tries to match as few as possible (non-greedy).

See: The Stack Overflow Regular Expressions FAQ

Body:
I have a template config file with PlaceHolders, and i want to find all those PlaceHolders and put inside an array.

The curent state:

I can find all the PlaceHolders in file only if there is no more than one PlaceHolder in a line.

For example, this is my template file:

upstream portal {
   server {{UNICORN_SERVICE_NAME}}:{{UNICORN_SERVICE_PORT}};
}

server {
  listen *:80 default_server;
  server_name {{APP_HOST}};
  server_tokens off;
  root /dev/null;

  # Increase this if you want to upload large attachments
  # Or if you want to accept large git objects over http
  client_max_body_size {{NGINX_MAX_UPLOAD_SIZE}};

  location {{GITLAB_RELATIVE_URL_ROOT}}/ {
    root /var/lib/nginx/portal;
    # serve static files from defined root folder;.
    # @gitlab is a named location for the upstream fallback, see below
  }
  }

this is the code i use to find the PlaceHolders:

matches_bloc=$(awk 'match($0, /(\{\{)([^{]*)(\}\})/) {
                    print substr($0, RSTART, RLENGTH)
                }' ${currFile})

            # convert 'matches_bloc' into array
            matches=()
            echo "Matches:"
            while read -r line; do
                matches+=("$line")
                echo "  - ${line}"
            done <<< "$matches_bloc"

in this example the matches result will be:

Matches:

    - {{UNICORN_SERVICE_NAME}}

    - {{APP_HOST}}

    - {{NGINX_MAX_UPLOAD_SIZE}}

    - {{GITLAB_RELATIVE_URL_ROOT}}

You can notice that there are 5 PlaceHolders in the file and only 4 matches.

The missing match is: {{UNICORN_SERVICE_PORT}}, because there is already another match in the same line.

My question is:

How can i find all the matches in the file regardless of the line?

Body:
Find all variables in a template file and put them in an array.

With GNU grep:

array=( $(grep -Po '{{.*?}}' file) )
declare -p array

Output:

declare -a array='([0]="{{UNICORN_SERVICE_NAME}}" [1]="{{UNICORN_SERVICE_PORT}}" [2]="{{APP_HOST}}" [3]="{{NGINX_MAX_UPLOAD_SIZE}}" [4]="{{GITLAB_RELATIVE_URL_ROOT}}")'

-P: Interpret {{.*?}} as a Perl regular expression.

-o: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

* The preceding expression can match zero or more times. With ? the * tries to match as few as possible (non-greedy).

See: The Stack Overflow Regular Expressions FAQ


问:
Same Origin Policy for jQuery vs Browser (with OData)
I am building an AJAX application to query an OData endpoint. I've been doing some testing with the Netflix OData feed and found something I don't get:

When I make an .ajax() request to a url (e.g. http://odata.netflix.com/v1/Catalog/Titles) I get the error: "Origin null is not allowed by Access-Control-Allow-Origin". However when I put the same url into my browser the request goes through and I get a response.

What is the fundamental difference here that I'm not getting? How is the browser bypassing the Same Origin Policy?

答:
I also used JSONP for Netflix's OData.  It seems to work fine for my application.  I have posted the code and explaination under my blog http://bit.ly/95HXLM

Some sample fragment below as well:

```<code>49.        // Make JSONP call to Netflix
50.     $.ajax({
51.            dataType: "jsonp",
52.            url: query,
53.            jsonpCallback: "callback",
54.            success: callback
55.            });
56.        });
57.
58.    function callback(result) {
59.        // unwrap result
60.        var movies = result.d.results;
61.
62.        $("#movieTemplateContainer").empty();
63.        $("#movieTemplate").tmpl(movies).appendTo("#movieTemplateContainer");
64.    }
</code>```

Body:
I also used JSONP for Netflix's OData.  It seems to work fine for my application.  I have posted the code and explaination under my blog http://bit.ly/95HXLM

Some sample fragment below as well:

49.        // Make JSONP call to Netflix
50.     $.ajax({
51.            dataType: "jsonp",
52.            url: query,
53.            jsonpCallback: "callback",
54.            success: callback
55.            });
56.        });
57.
58.    function callback(result) {
59.        // unwrap result
60.        var movies = result.d.results;
61.
62.        $("#movieTemplateContainer").empty();
63.        $("#movieTemplate").tmpl(movies).appendTo("#movieTemplateContainer");
64.    }


问:
Laravel select field cannot be null
I'm trying to store a form into my database but this is the error i get:

```<code>Integrity constraint violation: 1048 Column 'rent_product' cannot be null
</code>```

Why is this?

I'm trying to do this in an array because i have an option to show more select fields (to add more products to rent).

This is the HTML:

```<code><div class="col-lg-10">
 <label for="sel1">Selecteer product:</label>
   <select class="form-control" id="sel1" style="height: 40px;">
     @foreach ($pr as $prr)
      <option name="product_name[]" value="{{$prr->product_name}}">{{$prr->product_name}}</option>
     @endforeach
   </select>
</div>
</code>```

Function:

```<code>public function create_order($id) {

    $customer = Customer::find($id);

    $customer->rent_product = Request::get('product_name');
    $customer->rent_product_count = Request::get('product_count');
    $customer->update();

}
</code>```

Thanks in advance.

答:
Change $customer->update(); to $customer->save();. The update method expects you to pass the attributes array to update. So you're making an update without any values.

```<code>$customer = Customer::find($id);
$customer->rent_product = Request::get('product_name');
$customer->rent_product_count = Request::get('product_count');
$customer->save();

// This is what you need to do if you want to use `update`

$customer->update([
    'rent_product' => Request::get('product_name'),
    'rent_product_count' => Request::get('product_count')
]);

// Or you can do this to update in a single query

Customer::where('id', $id)->update([
    'rent_product' => Request::get('product_name'),
    'rent_product_count' => Request::get('product_count')
]);
</code>```

Title: Laravel select field cannot be null

Body:
I'm trying to store a form into my database but this is the error i get:

Integrity constraint violation: 1048 Column 'rent_product' cannot be null

Why is this?

I'm trying to do this in an array because i have an option to show more select fields (to add more products to rent).

This is the HTML:

 Selecteer product:
   <select class="form-control" id="sel1" style="height: 40px;">
     @foreach ($pr as $prr)
      <option name="product_name[]" value="{{$prr->product_name}}">{{$prr->product_name}}</option>
     @endforeach
   </select>

Function:

public function create_order($id) {

    $customer = Customer::find($id);

    $customer->rent_product = Request::get('product_name');
    $customer->rent_product_count = Request::get('product_count');
    $customer->update();

}

Thanks in advance.

Body:
Change $customer->update(); to $customer->save();. The update method expects you to pass the attributes array to update. So you're making an update without any values.

$customer = Customer::find($id);
$customer->rent_product = Request::get('product_name');
$customer->rent_product_count = Request::get('product_count');
$customer->save();

// This is what you need to do if you want to use `update`

$customer->update([
    'rent_product' => Request::get('product_name'),
    'rent_product_count' => Request::get('product_count')
]);

// Or you can do this to update in a single query

Customer::where('id', $id)->update([
    'rent_product' => Request::get('product_name'),
    'rent_product_count' => Request::get('product_count')
]);


问:
How can I prevent Email Header Injection in my contact form?
I am a newbie on PHP but manage to create a working contact form. But then I got aware of Email Header Injection. How can I prevent this in best possible way? Don't want my form to be used to spam people.

This is my code:

```<code><?php
if ($_POST["email"]<>'') {
    $ToEmail = 'FixedEmail@domain.com';
    $EmailSubject = 'Email Subject';
    $mailheader = 'From: donotreply@domain.com' . "\r\n" .
        'Reply-To:' .$_POST["email"]. "\r\n" .
        'MIME-Version: 1.0'."\r\n".
        'Content-Type: text/html; charset=utf-8'."\r\n".
        'X-Mailer: PHP/' . phpversion();
    $MESSAGE_BODY .= "<b>Navn:</b> ".$_POST["name"]."<br />";
    $MESSAGE_BODY .= "<b>Telefon:</b> ".$_POST["telephone"]."<br />";
    $MESSAGE_BODY .= "<b>Email:</b> ".$_POST["email"]."<br /><br />";
    $MESSAGE_BODY .= "".nl2br($_POST["message"])."<br />";
    mail($ToEmail, $EmailSubject, $MESSAGE_BODY, $mailheader) or die ("Failure");
</code>```

?>

答:
Just Put the validation for email field as shown below:

```<code>$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);

if ($email === FALSE) {
    echo 'Invalid email';
    exit(1);
}
</code>```

It validates your Email format which will not allow any kind of injected headers.

Body:
I am a newbie on PHP but manage to create a working contact form. But then I got aware of Email Header Injection. How can I prevent this in best possible way? Don't want my form to be used to spam people.

This is my code:

<?php
if ($_POST["email"]<>'') {
    $ToEmail = 'FixedEmail@domain.com';
    $EmailSubject = 'Email Subject';
    $mailheader = 'From: donotreply@domain.com' . "\r\n" .
        'Reply-To:' .$_POST["email"]. "\r\n" .
        'MIME-Version: 1.0'."\r\n".
        'Content-Type: text/html; charset=utf-8'."\r\n".
        'X-Mailer: PHP/' . phpversion();
    $MESSAGE_BODY .= "Navn: ".$_POST["name"]."
";
    $MESSAGE_BODY .= "Telefon: ".$_POST["telephone"]."
";
    $MESSAGE_BODY .= "Email: ".$_POST["email"]."

";
    $MESSAGE_BODY .= "".nl2br($_POST["message"])."
";
    mail($ToEmail, $EmailSubject, $MESSAGE_BODY, $mailheader) or die ("Failure");

?>

Body:
Just Put the validation for email field as shown below:

$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);

if ($email === FALSE) {
    echo 'Invalid email';
    exit(1);
}

It validates your Email format which will not allow any kind of injected headers.


问:
Concatenating strings or using multiple echo parameters: which is faster?
Suppose I have two PHP statements:

```<code>echo "foo"."bar"

echo "foo", "bar"
</code>```

Notice the different ways of concatenating the strings - using a . or a ,.

I realise the actual differences between the two methods, that using , gives multiple parameters to the keyword echo, whereas using . actually joins the strings together before echoing.

But my question is, which way is faster?

答:
Aotoki's answer is untrue.  The double quoted strings can contain a variable.  The commas and dots have nothing to do with variables versus literal strings.

When using echo (a "language construct") multiple parameters can be declared.  When doing so, you can concatenate with dots or commas.  There is a slight difference in their behavior because of "precedence"; this is an issue that explained in the php manual (see earlier link to manual).

Many benchmark tests have been run over the years on this topic, and everyone that I have ever seen has stated that comma concatenation is faster than dot concatenation.  For this reason, I never use dots to concatenate with echo.

Here are some links that offer some actual benchmark results:

https://stackoverflow.com/a/17437821/2943403

https://www.electrictoolbox.com/php-echo-commas-vs-concatenation/

https://www.fusionswift.com/2010/05/php-concatenation-benchmark-comma-vs-period/

All this said, this topic is about micro-optimization.  If you have a project that truly need to shave time because it is impacting users, chances are there is a bigger fish to fry than echo concatenation.  In virtually all instances, your end user is not going to have the slightest clue if you used commas or dots to echo your content.

Body:
Suppose I have two PHP statements:

echo "foo"."bar"

echo "foo", "bar"

Notice the different ways of concatenating the strings - using a . or a ,.

I realise the actual differences between the two methods, that using , gives multiple parameters to the keyword echo, whereas using . actually joins the strings together before echoing.

But my question is, which way is faster?


问:
How to toggle transform transition upon click?
https://codepen.io/pen/MoWLrZ

When you click the first time, it will show the animation of the two overlays. But on second click it, the two overlays just goes back on one swoop.

JQUERY

```<code>$(document).ready(function() {
  $('#clickThis').click(function(e){
    e.preventDefault();
    $('.overlay').toggleClass('extend');
  });
});
</code>```

答:
Considering that you only have two overlay containers grey and white.
You might need to replace their transition-delay property if you want two swoops on the second click.

```<code>$(document).ready(function() {
    $('#clickThis').click(function(e) {
        e.preventDefault();
        if ($('.overlay.grey').hasClass('extend') === true) {
            $('.overlay.grey').css('transition-delay', '0.3s');
            $('.overlay.white').css('transition-delay', '0.1s');
        } else {
            $('.overlay.grey').css('transition-delay', '0.1s');
            $('.overlay.white').css('transition-delay', '0.3s');
        }
        $('.overlay').toggleClass('extend');
    });
});
</code>```

This is because by the time you've click the #clickThis element, The white container is the current container that last show up because of the given delay you have given on your css (e.g 0.3s).

Thus, on the second click, The grey container was already taking affect but its hidden behind the white container (Look at the z-index property)

Hope this helps for your case

Body:
https://codepen.io/pen/MoWLrZ

When you click the first time, it will show the animation of the two overlays. But on second click it, the two overlays just goes back on one swoop.

JQUERY

$(document).ready(function() {
  $('#clickThis').click(function(e){
    e.preventDefault();
    $('.overlay').toggleClass('extend');
  });
});

Body:
Considering that you only have two overlay containers grey and white.
You might need to replace their transition-delay property if you want two swoops on the second click.

$(document).ready(function() {
    $('#clickThis').click(function(e) {
        e.preventDefault();
        if ($('.overlay.grey').hasClass('extend') === true) {
            $('.overlay.grey').css('transition-delay', '0.3s');
            $('.overlay.white').css('transition-delay', '0.1s');
        } else {
            $('.overlay.grey').css('transition-delay', '0.1s');
            $('.overlay.white').css('transition-delay', '0.3s');
        }
        $('.overlay').toggleClass('extend');
    });
});

This is because by the time you've click the #clickThis element, The white container is the current container that last show up because of the given delay you have given on your css (e.g 0.3s).

Thus, on the second click, The grey container was already taking affect but its hidden behind the white container (Look at the z-index property)

Hope this helps for your case


问:
Geometry DataType in H2 w/ Spring JPA
Context:
I've been trying to get Geometry Datatypes working with H2 before I eventually move to PostgreSQL. My code compiles but when I attempt to retrieve the User model it fails because of Geometry location. I get a value too long for column "LOCATION BINARY(255): 'X'aced005...."

application.properties

```<code>spring.datasource.url=jdbc:h2:file:./members.db
server.port = 8090
</code>```

gradle.build, the main dependencies for this are the vividsolutions and some of the hibernate ones.

```<code>buildscript {
    ext {
        springBootVersion = '1.5.3.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()

}

dependencies {
    testCompile('org.springframework.boot:spring-boot-starter-test')
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile (group: 'com.vividsolutions', name: 'jts', version: '1.13')
    compile (group: 'org.orbisgis', name: 'h2gis', version: '1.3.1')
    compile (group: 'org.hibernate', name: 'hibernate-core', version: '5.2.10.Final')
    compile (group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final')
    compile (group: 'org.hibernate', name: 'hibernate-spatial', version: '5.2.10.Final')
    runtime('com.h2database:h2')
    //  runtime('org.postgresql:postgresql')
}
</code>```

Entity: If I don't provide getters/setters for location the application runs but that's because it's not actually trying to access that data. I've tried using other annotations to define Geometry for location,         @Type(type="org.hibernate.spatial.GeometryType")
 Hibernate spatial docs. That annotation won't even compile because it doesn't recognize hibernate.spatial despite having the dependency in gradle.

```<code>package com.alex_donley.event_mapper.Entities;

import com.vividsolutions.jts.geom.Geometry;

import javax.persistence.*;

/**
 * Created by Indycorps on 5/11/2017.
 */
@Entity
public class User {

    @Id
    @GeneratedValue
    private long id;

    private String firstName;
    private String lastName;
    @Column(columnDefinition="Geometry")
    private Geometry location;

    public User(String firstName, String lastName, Geometry location) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.location = location;
    }

    public User(){}

    public long getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    //Create getters and setters for location to actually output stuff

    public Geometry getLocation() {
        return location;
    }

    public void setLocation(Geometry location) {
        this.location = location;
    }
}
</code>```

答:
You're referring to outdated documentation. The correct documentation for your version is here.

Hibernate Spatial doesn't support H2, but it does support GeoDB which is based on H2. You might have more luck with that database.

Title: Geometry DataType in H2 w/ Spring JPA

Body:
Context:
I've been trying to get Geometry Datatypes working with H2 before I eventually move to PostgreSQL. My code compiles but when I attempt to retrieve the User model it fails because of Geometry location. I get a value too long for column "LOCATION BINARY(255): 'X'aced005...."

application.properties

spring.datasource.url=jdbc:h2:file:./members.db
server.port = 8090

gradle.build, the main dependencies for this are the vividsolutions and some of the hibernate ones.

buildscript {
    ext {
        springBootVersion = '1.5.3.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
    mavenCentral()

}

dependencies {
    testCompile('org.springframework.boot:spring-boot-starter-test')
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile (group: 'com.vividsolutions', name: 'jts', version: '1.13')
    compile (group: 'org.orbisgis', name: 'h2gis', version: '1.3.1')
    compile (group: 'org.hibernate', name: 'hibernate-core', version: '5.2.10.Final')
    compile (group: 'org.hibernate', name: 'hibernate-entitymanager', version: '5.2.10.Final')
    compile (group: 'org.hibernate', name: 'hibernate-spatial', version: '5.2.10.Final')
    runtime('com.h2database:h2')
    //  runtime('org.postgresql:postgresql')
}

Entity: If I don't provide getters/setters for location the application runs but that's because it's not actually trying to access that data. I've tried using other annotations to define Geometry for location,         @Type(type="org.hibernate.spatial.GeometryType")
 Hibernate spatial docs. That annotation won't even compile because it doesn't recognize hibernate.spatial despite having the dependency in gradle.

package com.alex_donley.event_mapper.Entities;

import com.vividsolutions.jts.geom.Geometry;

import javax.persistence.*;

/**
 * Created by Indycorps on 5/11/2017.
 */
@Entity
public class User {

    @Id
    @GeneratedValue
    private long id;

    private String firstName;
    private String lastName;
    @Column(columnDefinition="Geometry")
    private Geometry location;

    public User(String firstName, String lastName, Geometry location) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.location = location;
    }

    public User(){}

    public long getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    //Create getters and setters for location to actually output stuff

    public Geometry getLocation() {
        return location;
    }

    public void setLocation(Geometry location) {
        this.location = location;
    }
}


问:
Chrome Extension change url in the same popup
I am trying to write a chrome extension, and in it i need to open a new link for the Spotify web API authorisation. However, window.open() opens it in a new tab and my extension popup closes. Is there a way to open an url over the default_popup or at least keep it from closing automatically?

Thanks

答:
Thanks to w0xx0m i got it to work. Turns out, i needed to use the Chrome  identity API chrome.identity.launchWebAuthFlow.

In my case, i tried to authorize with Spotify on behalf of the user, and get the return url which contained the access token.

```<code>     chrome.identity.launchWebAuthFlow({
        url : THE_AUTHORIZATION_URL,
       //If interactive is set to false, the logon screen won't show up
        interactive : true},

        function(data){
            //the 'data' contains the return URL
            .......
        });
   });`
</code>```

Body:
Thanks to w0xx0m i got it to work. Turns out, i needed to use the Chrome  identity API chrome.identity.launchWebAuthFlow.

In my case, i tried to authorize with Spotify on behalf of the user, and get the return url which contained the access token.

     chrome.identity.launchWebAuthFlow({
        url : THE_AUTHORIZATION_URL,
       //If interactive is set to false, the logon screen won't show up
        interactive : true},

        function(data){
            //the 'data' contains the return URL
            .......
        });
   });`


问:
Angular DomSanitizer - SecurityContext.NONE
Official Angular Security Guide speaks about 4 security contexts: HTML, Url, Style and Resource Url.

Each one is responsible for sanitizing corresponding type of resource.

In addition, there are 5 methods (per resource type) in DomSanitizer service

```<code> - bypassSecurityTrustHtml
 - bypassSecurityTrustScript
 - bypassSecurityTrustStyle
 - bypassSecurityTrustUrl
 - bypassSecurityTrustResourceUrl
</code>```

However, I didn't find any mention of SecurityContext.NONE in official documentation. And it's does exist in the code.

I would assume that it aggregates all the resource types, meaning the resource being sanitized can be HTML, which contains styling and scripts.

Is that the case? Any official source?

答:
Apparently, if we use domSanitizer.sanitize with SecurityContext.NONE, it won't perform any sanitation and will return the value as is.

Thus, this will allow HTML with embedded URLs, styling and scripts.

Therefore it is highly recommended not to use this in your code.

ContentLicense: CC BY-SA 4.0

Body:
Official Angular Security Guide speaks about 4 security contexts: HTML, Url, Style and Resource Url.

Each one is responsible for sanitizing corresponding type of resource.

In addition, there are 5 methods (per resource type) in DomSanitizer service

 - bypassSecurityTrustHtml
 - bypassSecurityTrustScript
 - bypassSecurityTrustStyle
 - bypassSecurityTrustUrl
 - bypassSecurityTrustResourceUrl

However, I didn't find any mention of SecurityContext.NONE in official documentation. And it's does exist in the code.

I would assume that it aggregates all the resource types, meaning the resource being sanitized can be HTML, which contains styling and scripts.

Is that the case? Any official source?


问:
How to replace only one digit in text in python?
I have a file with pairs of numbers as following:

```<code>0,21
0,52
0,464
100,478
1,101
1,729
1,730
</code>```

And I want to replace the single "0"s with "2000". The expected output should be:

```<code>2000,21
2000,52
2000,464
100,478
1,101
1,729
1,730
</code>```

However, with my code, it changes all 0s to 2000s and I end up with this output:

```<code>2000,21
2000,52
2000,464
120002000,478
1,120001
1,729
1,732000
</code>```

My code is:

```<code>textToSearch = "0"
textToReplace = "2000"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')
</code>```

Plus : I never know how many 0s will be on the left side of the comma, therefore I cannot limit the number of 0s to be changed. The file is randomly generated, as sometimes I have twelve 0s and sometimes only one.
I have tried this:

```<code>textToSearch = "0,"
textToReplace = "2000,"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')
</code>```

However,this time it is not working for numbers such as "100" or "200", as it is making them "102000" and "202000" respectively.

How can I fix it?

答:
You should try using "regular expressions" import re module as below.

```<code>import re

fileToSearch = "example.csv"

    with open(fileToSearch) as file:
        for line in file:
            line = line.strip("\n")
            match = re.search("^0", line)
            if match:
                list1 = line.split(",")
                list1[0] = 2000
                line = str(list1[0]) + "," + str(list1[1])
            print(line)
</code>```

This seems to produce the result you want.

Body:
I have a file with pairs of numbers as following:

0,21
0,52
0,464
100,478
1,101
1,729
1,730

And I want to replace the single "0"s with "2000". The expected output should be:

2000,21
2000,52
2000,464
100,478
1,101
1,729
1,730

However, with my code, it changes all 0s to 2000s and I end up with this output:

2000,21
2000,52
2000,464
120002000,478
1,120001
1,729
1,732000

My code is:

textToSearch = "0"
textToReplace = "2000"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')

Plus : I never know how many 0s will be on the left side of the comma, therefore I cannot limit the number of 0s to be changed. The file is randomly generated, as sometimes I have twelve 0s and sometimes only one.
I have tried this:

textToSearch = "0,"
textToReplace = "2000,"
fileToSearch = "example.csv"
with fileinput.FileInput(fileToSearch, inplace=True, backup='.bak') as file:
    for line in file:
        print(line.replace(textToSearch, textToReplace), end='')

However,this time it is not working for numbers such as "100" or "200", as it is making them "102000" and "202000" respectively.

How can I fix it?

Body:
You should try using "regular expressions" import re module as below.

import re

fileToSearch = "example.csv"

    with open(fileToSearch) as file:
        for line in file:
            line = line.strip("\n")
            match = re.search("^0", line)
            if match:
                list1 = line.split(",")
                list1[0] = 2000
                line = str(list1[0]) + "," + str(list1[1])
            print(line)

This seems to produce the result you want.


问:
Can't handle with the movement bug in simple Java.swing game
I have a problem with moving in the game I am creating, everything works exactly as I would like except one thing, the board is redrawn according to the timer delay and when I do more than one move before board redraws, then there is a chance that my snake will fall into itself each other. I can not handle this and I do not know how to avoid it, I was thinking about setting a delay between push buttons but it is impossible because the game is for two players. I'm trying to fix this issue where the snake backtracks into itself, but haven't found a solution yet. Any help would be appreciated.

Several photos representing the problem:

Normal gameplay:

When i spam the buttons:

Movement method:

```<code>    private void move()
{

    for (int z = dots; z > 0; z--)
    {
        p1x[z] = p1x[(z - 1)];
        p1y[z] = p1y[(z - 1)];
        p2x[z] = p2x[(z - 1)];
        p2y[z] = p2y[(z - 1)];
    }

    if (p1LeftDirection)
    {
        p1x[0] -= DOT_SIZE;
    }

    if (p1RightDirection)
    {
        p1x[0] += DOT_SIZE;
    }

    if (p1UpDirection)
    {
        p1y[0] -= DOT_SIZE;
    }

    if (p1DownDirection)
    {
        p1y[0] += DOT_SIZE;
    }

    if (p2LeftDirection)
    {
        p2x[0] -= DOT_SIZE;
    }

    if (p2RightDirection)
    {
        p2x[0] += DOT_SIZE;
    }

    if (p2UpDirection)
    {
        p2y[0] -= DOT_SIZE;
    }

    if (p2DownDirection)
    {
        p2y[0] += DOT_SIZE;
    }
    dots++;
}
</code>```

Drawing method:

```<code>private void doDrawing(Graphics g)
{
    if (inGame)
    {
        for (int z = 0; z < dots; z++)
        {
            if (z == 0)
            {
                g.drawImage(p1Head, p1x[z], p1y[z], this);
                g.drawImage(p2Head, p2x[z], p2y[z], this);
            }
            else
            {
                g.drawImage(p1Body, p1x[z], p1y[z], this);
                g.drawImage(p2Body, p2x[z], p2y[z], this);
            }
        }

        for (int i = 0; i < B_WIDTH; i += 25)
        {
            g.drawImage(brick, 0, i, this);
            g.drawImage(brick, i, 0, this);
        }
        for (int i = 0; i < B_WIDTH; i += 25)
        {
            g.drawImage(brick, B_WIDTH - DOT_SIZE, i, this);
            g.drawImage(brick, i, B_HEIGHT - DOT_SIZE, this);
        }

        Toolkit.getDefaultToolkit().sync();
    }
    else
    {
        gameOver(g);
    }
}
</code>```

And my KeyAdapter:

```<code>public class KeyboardSettings extends KeyAdapter
{

    @Override
    public void keyPressed(KeyEvent e)
    {
        int key = e.getKeyCode();

        if ((key == KeyEvent.VK_LEFT) && (!p1RightDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1leftmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1LeftDirection = true;
            p1UpDirection = false;
            p1DownDirection = false;
        }

        if ((key == KeyEvent.VK_RIGHT) && (!p1LeftDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1rightmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1RightDirection = true;
            p1UpDirection = false;
            p1DownDirection = false;
        }

        if ((key == KeyEvent.VK_UP) && (!p1DownDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1upmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1UpDirection = true;
            p1RightDirection = false;
            p1LeftDirection = false;
        }

        if ((key == KeyEvent.VK_DOWN) && (!p1UpDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1downmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1DownDirection = true;
            p1RightDirection = false;
            p1LeftDirection = false;
        }

        if ((key == KeyEvent.VK_A) && (!p2RightDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2leftmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2LeftDirection = true;
            p2UpDirection = false;
            p2DownDirection = false;
        }

        if ((key == KeyEvent.VK_D) && (!p2LeftDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2rightmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2RightDirection = true;
            p2UpDirection = false;
            p2DownDirection = false;
        }

        if ((key == KeyEvent.VK_W) && (!p2DownDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2upmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2UpDirection = true;
            p2RightDirection = false;
            p2LeftDirection = false;
        }

        if ((key == KeyEvent.VK_S) && (!p2UpDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2downmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2DownDirection = true;
            p2RightDirection = false;
            p2LeftDirection = false;
        }
    }
}
</code>```

答:
I had the exact same problem. I tried different in-built methods but they didn't work for me. But this is how I would bypass the problem with my method:

```<code>private void move()
{

for (int z = dots; z > 0; z--)
{
    p1x[z] = p1x[(z - 1)];
    p1y[z] = p1y[(z - 1)];
    p2x[z] = p2x[(z - 1)];
    p2y[z] = p2y[(z - 1)];
}

if (p1LeftDirection)
{
    p1x[0] -= DOT_SIZE;
    if(p1x[0] == p1x[2])
    {
        p1x[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1x[0] == p1x[1])
    {
        p1x[0] += DOT_SIZE;
        rotateCorr();
    }
}

if (p1RightDirection)
{
    p1x[0] += DOT_SIZE;
    if(p1x[0] == p1x[2])
    {
        p1x[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1x[0] == p1x[1])
    {
        p1x[0] -= DOT_SIZE;
        rotateCorr();
    }
}

if (p1UpDirection)
{
    p1y[0] -= DOT_SIZE;
    if(p1y[0] == p1y[2])
    {
        p1y[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1y[0] == p1y[1])
    {
        p1y[0] += DOT_SIZE;
        rotateCorr();

    }
}

if (p1DownDirection)
{
    p1y[0] += DOT_SIZE;
    if(p1y[0] == p1y[2])
    {
        p1y[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1y[0] == p1y[1])
    {
        p1y[0] -= DOT_SIZE;
        rotateCorr();
    }
}

if (p2LeftDirection)
{
    p2x[0] -= DOT_SIZE;
    if(p2x[0] == p2x[2])
    {
        p2x[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2x[0] == p2x[1])
    {
        p2x[0] += DOT_SIZE;
        rotateCorr();
    }
}

if (p2RightDirection)
{
    p2x[0] += DOT_SIZE;
    if(p2x[0] == p2x[2])
    {
        p2x[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2x[0] == p2x[1])
    {
        p2x[0] -= DOT_SIZE;
        rotateCorr();
    }
}

if (p2UpDirection)
{
    p2y[0] -= DOT_SIZE;
    if(p2y[0] == p2y[2])
    {
        p2y[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2y[0] == p2y[1])
    {
        p2y[0] += DOT_SIZE;
        rotateCorr();
    }
}

if (p2DownDirection)
{
    p2y[0] += DOT_SIZE;
    if(p2y[0] == p2y[2])
    {
        p2y[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2y[0] == p2y[1])
    {
        p2y[0] -= DOT_SIZE;
        rotateCorr();
    }
}
dots++;
}
</code>```

I know exactly the glitch you faced, so this should work for you.

Basically, if multiple buttons are pressed, the snake backtracks along itself, because first it registers that the key is valid, but then moves to execute the invalid key. So, even though logically it makes NO FRIKKIN SENSE, the snake backtracks.

This code simply tells it that if the snake backtracks (if the head coincides with the first or second part of the body), then the snake head should go back to its initial location, and resume its initial direction.

Additional Code:

To rotate the head correctly:

```<code>private void rotateCorr()
{
    if(p1x[0] = p1x[1] - DOT_SIZE)
    {
          // Your code to rotate p1 head to face the left
    }
    if(p1x[0] = p1x[1] + DOT_SIZE)
    {
          // Your code to rotate p1 head to face the right
    }
    if(p1y[0] = p1y[1] - DOT_SIZE)
    {
          // Your code to rotate p1 head to face the top
    }
    if(p1y[0] = p1y[1] + DOT_SIZE)
    {
          // Your code to rotate p1 head to face the bottom
    }

    // Now, for p2 snake:

    if(p2x[0] = p2x[1] - DOT_SIZE)
    {
          // Your code to rotate p2 head to face the left
    }
    if(p2x[0] = p2x[1] + DOT_SIZE)
    {
          // Your code to rotate p2 head to face the right
    }
    if(p2y[0] = p2y[1] - DOT_SIZE)
    {
          // Your code to rotate p2 head to face the top
    }
    if(p2y[0] = p2y[1] + DOT_SIZE)
    {
          // Your code to rotate p2 head to face the bottom
    }
}
</code>```

If the head is above the second part, it is rotated to face the top, etc.

Body:
I have a problem with moving in the game I am creating, everything works exactly as I would like except one thing, the board is redrawn according to the timer delay and when I do more than one move before board redraws, then there is a chance that my snake will fall into itself each other. I can not handle this and I do not know how to avoid it, I was thinking about setting a delay between push buttons but it is impossible because the game is for two players. I'm trying to fix this issue where the snake backtracks into itself, but haven't found a solution yet. Any help would be appreciated.

Several photos representing the problem:

Normal gameplay:

When i spam the buttons:

Movement method:

    private void move()
{

    for (int z = dots; z > 0; z--)
    {
        p1x[z] = p1x[(z - 1)];
        p1y[z] = p1y[(z - 1)];
        p2x[z] = p2x[(z - 1)];
        p2y[z] = p2y[(z - 1)];
    }

    if (p1LeftDirection)
    {
        p1x[0] -= DOT_SIZE;
    }

    if (p1RightDirection)
    {
        p1x[0] += DOT_SIZE;
    }

    if (p1UpDirection)
    {
        p1y[0] -= DOT_SIZE;
    }

    if (p1DownDirection)
    {
        p1y[0] += DOT_SIZE;
    }

    if (p2LeftDirection)
    {
        p2x[0] -= DOT_SIZE;
    }

    if (p2RightDirection)
    {
        p2x[0] += DOT_SIZE;
    }

    if (p2UpDirection)
    {
        p2y[0] -= DOT_SIZE;
    }

    if (p2DownDirection)
    {
        p2y[0] += DOT_SIZE;
    }
    dots++;
}

Drawing method:

private void doDrawing(Graphics g)
{
    if (inGame)
    {
        for (int z = 0; z < dots; z++)
        {
            if (z == 0)
            {
                g.drawImage(p1Head, p1x[z], p1y[z], this);
                g.drawImage(p2Head, p2x[z], p2y[z], this);
            }
            else
            {
                g.drawImage(p1Body, p1x[z], p1y[z], this);
                g.drawImage(p2Body, p2x[z], p2y[z], this);
            }
        }

        for (int i = 0; i < B_WIDTH; i += 25)
        {
            g.drawImage(brick, 0, i, this);
            g.drawImage(brick, i, 0, this);
        }
        for (int i = 0; i < B_WIDTH; i += 25)
        {
            g.drawImage(brick, B_WIDTH - DOT_SIZE, i, this);
            g.drawImage(brick, i, B_HEIGHT - DOT_SIZE, this);
        }

        Toolkit.getDefaultToolkit().sync();
    }
    else
    {
        gameOver(g);
    }
}

And my KeyAdapter:

public class KeyboardSettings extends KeyAdapter
{

    @Override
    public void keyPressed(KeyEvent e)
    {
        int key = e.getKeyCode();

        if ((key == KeyEvent.VK_LEFT) && (!p1RightDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1leftmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1LeftDirection = true;
            p1UpDirection = false;
            p1DownDirection = false;
        }

        if ((key == KeyEvent.VK_RIGHT) && (!p1LeftDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1rightmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1RightDirection = true;
            p1UpDirection = false;
            p1DownDirection = false;
        }

        if ((key == KeyEvent.VK_UP) && (!p1DownDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1upmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1UpDirection = true;
            p1RightDirection = false;
            p1LeftDirection = false;
        }

        if ((key == KeyEvent.VK_DOWN) && (!p1UpDirection))
        {
            ImageIcon p1HeadLoader = new ImageIcon("src/main/resources/images/p1downmouth.png");
            p1Head = p1HeadLoader.getImage();
            p1DownDirection = true;
            p1RightDirection = false;
            p1LeftDirection = false;
        }

        if ((key == KeyEvent.VK_A) && (!p2RightDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2leftmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2LeftDirection = true;
            p2UpDirection = false;
            p2DownDirection = false;
        }

        if ((key == KeyEvent.VK_D) && (!p2LeftDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2rightmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2RightDirection = true;
            p2UpDirection = false;
            p2DownDirection = false;
        }

        if ((key == KeyEvent.VK_W) && (!p2DownDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2upmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2UpDirection = true;
            p2RightDirection = false;
            p2LeftDirection = false;
        }

        if ((key == KeyEvent.VK_S) && (!p2UpDirection))
        {
            ImageIcon p2HeadLoader = new ImageIcon("src/main/resources/images/p2downmouth.png");
            p2Head = p2HeadLoader.getImage();
            p2DownDirection = true;
            p2RightDirection = false;
            p2LeftDirection = false;
        }
    }
}

Body:
I had the exact same problem. I tried different in-built methods but they didn't work for me. But this is how I would bypass the problem with my method:

private void move()
{

for (int z = dots; z > 0; z--)
{
    p1x[z] = p1x[(z - 1)];
    p1y[z] = p1y[(z - 1)];
    p2x[z] = p2x[(z - 1)];
    p2y[z] = p2y[(z - 1)];
}

if (p1LeftDirection)
{
    p1x[0] -= DOT_SIZE;
    if(p1x[0] == p1x[2])
    {
        p1x[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1x[0] == p1x[1])
    {
        p1x[0] += DOT_SIZE;
        rotateCorr();
    }
}

if (p1RightDirection)
{
    p1x[0] += DOT_SIZE;
    if(p1x[0] == p1x[2])
    {
        p1x[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1x[0] == p1x[1])
    {
        p1x[0] -= DOT_SIZE;
        rotateCorr();
    }
}

if (p1UpDirection)
{
    p1y[0] -= DOT_SIZE;
    if(p1y[0] == p1y[2])
    {
        p1y[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1y[0] == p1y[1])
    {
        p1y[0] += DOT_SIZE;
        rotateCorr();

    }
}

if (p1DownDirection)
{
    p1y[0] += DOT_SIZE;
    if(p1y[0] == p1y[2])
    {
        p1y[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p1y[0] == p1y[1])
    {
        p1y[0] -= DOT_SIZE;
        rotateCorr();
    }
}

if (p2LeftDirection)
{
    p2x[0] -= DOT_SIZE;
    if(p2x[0] == p2x[2])
    {
        p2x[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2x[0] == p2x[1])
    {
        p2x[0] += DOT_SIZE;
        rotateCorr();
    }
}

if (p2RightDirection)
{
    p2x[0] += DOT_SIZE;
    if(p2x[0] == p2x[2])
    {
        p2x[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2x[0] == p2x[1])
    {
        p2x[0] -= DOT_SIZE;
        rotateCorr();
    }
}

if (p2UpDirection)
{
    p2y[0] -= DOT_SIZE;
    if(p2y[0] == p2y[2])
    {
        p2y[0] += 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2y[0] == p2y[1])
    {
        p2y[0] += DOT_SIZE;
        rotateCorr();
    }
}

if (p2DownDirection)
{
    p2y[0] += DOT_SIZE;
    if(p2y[0] == p2y[2])
    {
        p2y[0] -= 2*DOT_SIZE;
        rotateCorr();
    }
    else if(p2y[0] == p2y[1])
    {
        p2y[0] -= DOT_SIZE;
        rotateCorr();
    }
}
dots++;
}

I know exactly the glitch you faced, so this should work for you.

Basically, if multiple buttons are pressed, the snake backtracks along itself, because first it registers that the key is valid, but then moves to execute the invalid key. So, even though logically it makes NO FRIKKIN SENSE, the snake backtracks.

This code simply tells it that if the snake backtracks (if the head coincides with the first or second part of the body), then the snake head should go back to its initial location, and resume its initial direction.

Additional Code:

To rotate the head correctly:

private void rotateCorr()
{
    if(p1x[0] = p1x[1] - DOT_SIZE)
    {
          // Your code to rotate p1 head to face the left
    }
    if(p1x[0] = p1x[1] + DOT_SIZE)
    {
          // Your code to rotate p1 head to face the right
    }
    if(p1y[0] = p1y[1] - DOT_SIZE)
    {
          // Your code to rotate p1 head to face the top
    }
    if(p1y[0] = p1y[1] + DOT_SIZE)
    {
          // Your code to rotate p1 head to face the bottom
    }

    // Now, for p2 snake:

    if(p2x[0] = p2x[1] - DOT_SIZE)
    {
          // Your code to rotate p2 head to face the left
    }
    if(p2x[0] = p2x[1] + DOT_SIZE)
    {
          // Your code to rotate p2 head to face the right
    }
    if(p2y[0] = p2y[1] - DOT_SIZE)
    {
          // Your code to rotate p2 head to face the top
    }
    if(p2y[0] = p2y[1] + DOT_SIZE)
    {
          // Your code to rotate p2 head to face the bottom
    }
}

If the head is above the second part, it is rotated to face the top, etc.


问:
Converting Multiple Sprite Images into One
In an app I'm testing out, I'm using a gradient image as a background (590kb in size). I have the ability of breaking this image into 0.5 pixel vertical strips (19kb) and having this image repeat itself (1334 times) to create the same larger background image. I have 20 different background images total so the app will be 11.8mb vs 380kb in storage usage.

I don't like the idea of having 1334 sprites, but I do like the idea of using less storage. So, is there a way of flatting the 1334 images into one sprite? Not sure if this make sense, but any push in the right direction would be appreciated.

答:
You don't have to use image at all if you want to have a gradient. Take a look at this:

```<code> let context = CIContext()
        if let filter = CIFilter(name: "CILinearGradient")
        {
            filter.setDefaults()

            let startColor = CIColor(color: .gray)
            let endColor = CIColor(color: .purple)
            let startVector = CIVector(x: frame.width, y: 0)
            let endVector = CIVector(x: frame.width, y: frame.height)

            filter.setValue(startVector, forKey: "inputPoint0")
            filter.setValue(endVector, forKey: "inputPoint1")
            filter.setValue(startColor, forKey: "inputColor0")
            filter.setValue(endColor, forKey: "inputColor1")

            if let outputImage = filter.outputImage {

                if let  croppedImage = context.createCGImage(outputImage, from: CGRect(origin: CGPoint.zero, size: frame.size)){

                    let background  = SKSpriteNode(texture: SKTexture(cgImage: croppedImage))

                    addChild(background)
                    background.zPosition = -20

                }

            }

        }
</code>```

Repeating an image horizontally or vertically to achieve the same effect is possible. That would require creating texture from a container node using something like this. Still, IMO, you may want skip that and do gradient programatically. And certainly I would stay away of having many nodes which act as a background. That would be silly :)

Body:
You don't have to use image at all if you want to have a gradient. Take a look at this:

 let context = CIContext()
        if let filter = CIFilter(name: "CILinearGradient")
        {
            filter.setDefaults()

            let startColor = CIColor(color: .gray)
            let endColor = CIColor(color: .purple)
            let startVector = CIVector(x: frame.width, y: 0)
            let endVector = CIVector(x: frame.width, y: frame.height)

            filter.setValue(startVector, forKey: "inputPoint0")
            filter.setValue(endVector, forKey: "inputPoint1")
            filter.setValue(startColor, forKey: "inputColor0")
            filter.setValue(endColor, forKey: "inputColor1")

            if let outputImage = filter.outputImage {

                if let  croppedImage = context.createCGImage(outputImage, from: CGRect(origin: CGPoint.zero, size: frame.size)){

                    let background  = SKSpriteNode(texture: SKTexture(cgImage: croppedImage))

                    addChild(background)
                    background.zPosition = -20

                }

            }

        }

Repeating an image horizontally or vertically to achieve the same effect is possible. That would require creating texture from a container node using something like this. Still, IMO, you may want skip that and do gradient programatically. And certainly I would stay away of having many nodes which act as a background. That would be silly :)


问:
ActionBar: Up icon and Overflow menu icons not appearing, but working
The ActionBar on my app, which is a toolbar, does not show the icons for the UP button, nor the overflow menu, just a white bar. However, these still work- if you touch where they are supposed to be. They simply are not appearing.

I've compared the theme, xml, and manifests to an older app of mine which did not share the same problems, and found no differences. So I am completely lost.

Styles xml

```<code><style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme_NoActionBar" parent= "AppTheme">
        <!-- Customize your theme here. -->

        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>

    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</code>```

Activity_main.xml

```<code><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xu.servicequalityrater.CameraActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" >

        <TextView android:textSize="20dp" android:textColor="@color/black" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Veritas" />

    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_main" />

</android.support.design.widget.CoordinatorLayout>
</code>```

Manifest excerpt

```<code> <activity
            android:name=".CameraActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme_NoActionBar" />
</code>```

Any advice by members who have faced similar issues is extremely welcome!

答:
As you are using Theme.AppCompat.Light.DarkActionBar, your toolbar back icon and overflow icon showing as white color and I guess you have used colorPrimary as white.

Change colorPrimary to other color OR you can use Theme.AppCompat.Light, it will show back and overflow icon as black.

Here is the fully working code

Style.xml:

```<code><resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">@color/colorPrimary</item> <!-- WHITE -->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar" >
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>
</code>```

AndroidManifest.xml:

```<code><activity android:name=".MainActivity"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
</code>```

activity_main.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />
</LinearLayout>
</code>```

MainActivity.java:

```<code>public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }
}
</code>```

OUTPUT:

Hope this will help~

Body:
As you are using Theme.AppCompat.Light.DarkActionBar, your toolbar back icon and overflow icon showing as white color and I guess you have used colorPrimary as white.

Change colorPrimary to other color OR you can use Theme.AppCompat.Light, it will show back and overflow icon as black.

Here is the fully working code

Style.xml:

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">@color/colorPrimary</item> <!-- WHITE -->
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar" >
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>

AndroidManifest.xml:

<activity android:name=".MainActivity"
    android:theme="@style/AppTheme.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />
</LinearLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }
}

OUTPUT:

Hope this will help~


问:
com.datastax.driver.core.OperationTimedOutException
I created the following test class using Cassandra.

```<code>private static String server_ip = "127.0.0.1";
private static String keyspace = "hr";

private static Cluster cluster = null;
private static Session session = null;

public static void main (String [] args)
{
    if(cluster!=null) return;

    cluster = Cluster.builder().addContactPoints(server_ip).withPort(9042).build();

    final Metadata metadata = cluster.getMetadata();
    String msg = String.format("Connected to cluster: %s", metadata.getClusterName());
    System.out.println(msg);

    System.out.println("List of hosts");
    for (final Host host : metadata.getAllHosts())
    {
        msg = String.format("Datacenter: %s; Host: %s; Rack: %s",
        host.getDatacenter(),
        host.getAddress(),
        host.getRack());
        System.out.println(msg);
    }
    session = cluster.connect(keyspace);
}
</code>```

(Cluster.java:407)
    at samples.SampleB.main(SampleB.java:28)

After googling, I try all the proposing solution without success. Could you please help me solving this issue?. Thanks a lot.

答:
you should verify those dependencies:

<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-core</artifactId>
  <version>3.1.0</version>
</dependency>

<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-mapping</artifactId>
  <version>3.1.0</version>
</dependency>```

HTH

Body:
I created the following test class using Cassandra.

private static String server_ip = "127.0.0.1";
private static String keyspace = "hr";

private static Cluster cluster = null;
private static Session session = null;

public static void main (String [] args)
{
    if(cluster!=null) return;

    cluster = Cluster.builder().addContactPoints(server_ip).withPort(9042).build();

    final Metadata metadata = cluster.getMetadata();
    String msg = String.format("Connected to cluster: %s", metadata.getClusterName());
    System.out.println(msg);

    System.out.println("List of hosts");
    for (final Host host : metadata.getAllHosts())
    {
        msg = String.format("Datacenter: %s; Host: %s; Rack: %s",
        host.getDatacenter(),
        host.getAddress(),
        host.getRack());
        System.out.println(msg);
    }
    session = cluster.connect(keyspace);
}

(Cluster.java:407)
    at samples.SampleB.main(SampleB.java:28)

After googling, I try all the proposing solution without success. Could you please help me solving this issue?. Thanks a lot.

Body:
you should verify those dependencies:

<!-- Apache Cassandra Datastax's CQL driver. -->

<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-core</artifactId>
  <version>3.1.0</version>
</dependency>

<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-mapping</artifactId>
  <version>3.1.0</version>
</dependency>

HTH


问:
How to implement a ContentObserver for call logs
I'd like to know if there is a way to know if the content provider of callings has changed. I mean, if I make a call, or I answer a call, it returns a "flag" that a new log has been added to the call log, or the place where Android store informations about callings.

Because, when I make a call, Android stores the number, the contact name (if exists), the hour of the calling, the duration, ..., all in the content provider. So is there a way to capture this "flag" that says the content provider of callings is bigger, I mean, that a new data has been inserted on the content provider CallLog.Calls.

So, I still have a lot of doubts related to this issue. I don't know where to register the content observer. My intention is, when something changes in the CallLog content provider, the insert method of the code will be used.

I mean, the code won't do anything unless new data has been added to the CallLog content provider. If some data has been added to the CallLog content provider, then the code will query the new data, and then will insert. I wanna do this, because without a content observer the application was inserting data in the database that was already inserted every time I run the application, got it?

So here is my code. If someone could tell me where to put registerContentObserver() and everything else that is needed.

```<code>public class RatedCalls extends ListActivity {

    private SQLiteDatabase db;
    private CallDataHelper dh = null;
    StringBuilder sb = new StringBuilder();
    OpenHelper openHelper = new OpenHelper(RatedCalls.this);

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Cursor cursor = getContentResolver().query(
                android.provider.CallLog.Calls.CONTENT_URI, null, null, null,
                android.provider.CallLog.Calls.DATE + " DESC ");

        dh = new CallDataHelper(this);
        db = openHelper.getWritableDatabase();

        startManagingCursor(cursor);
        int numberColumnId = cursor.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
        int durationId = cursor.getColumnIndex(android.provider.CallLog.Calls.DURATION);
        int contactNameId = cursor.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);
        int dateId = cursor.getColumnIndex(android.provider.CallLog.Calls.DATE);
        int numTypeId = cursor.getColumnIndex(android.provider.CallLog.Calls.CACHED_NUMBER_TYPE);

        Date dt = new Date();
        int hours = dt.getHours();
        int minutes = dt.getMinutes();
        int seconds = dt.getSeconds();
        String currTime = hours + ":" + minutes + ":" + seconds;

        ArrayList<String> callList = new ArrayList<String>();
        if (cursor.moveToFirst()) {
            do {
                String contactNumber = cursor.getString(numberColumnId);
                String contactName = cursor.getString(contactNameId);
                String duration = cursor.getString(durationId);
                String callDate = DateFormat.getDateInstance().format(dateId);
                String numType = cursor.getString(numTypeId);

                ContentValues values = new ContentValues();
                values.put("contact_id", 1);
                values.put("contact_name", contactName);
                values.put("number_type", numType);
                values.put("contact_number", contactNumber);
                values.put("duration", duration);
                values.put("date", callDate);
                values.put("current_time", currTime);
                values.put("cont", 1);

                this.db.insert(CallDataHelper.TABLE_NAME, null, values);

                Toast.makeText(getBaseContext(), "Inserted!", Toast.LENGTH_LONG);
                callList.add("Contact Number: " + contactNumber
                        + "\nContact Name: " + contactName + "\nDuration: "
                        + duration + "\nDate: " + callDate);

            } while (cursor.moveToNext());
        }
        setListAdapter(new ArrayAdapter<String>(this, R.layout.listitem, callList));

        ListView lv = getListView();
        lv.setTextFilterEnabled(true);
        lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(getApplicationContext(), ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}
</code>```

答:
Here is the answer. Dont forget to register the content observer with this method:

```<code>registerContentObserver (Uri uri, boolean notifyForDescendents, ContentObserver observer)
</code>```

And then you can create it like this.

```<code>public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.getApplicationContext()
    .getContentResolver()
    .registerContentObserver(
            android.provider.CallLog.Calls.CONTENT_URI, true,
            new MyContentObserver(handler));
}

class MyContentObserver extends ContentObserver {
    public MyContentObserver(Handler h) {
        super(h);
    }

    @Override
    public boolean deliverSelfNotifications() {
        return true;
    }

    @Override
    public void onChange(boolean selfChange) {
        Log.d(LOG_TAG, "MyContentObserver.onChange("+selfChange+")");
        super.onChange(selfChange);

        // here you call the method to fill the list
    }
}
</code>```

Body:
I'd like to know if there is a way to know if the content provider of callings has changed. I mean, if I make a call, or I answer a call, it returns a "flag" that a new log has been added to the call log, or the place where Android store informations about callings.

Because, when I make a call, Android stores the number, the contact name (if exists), the hour of the calling, the duration, ..., all in the content provider. So is there a way to capture this "flag" that says the content provider of callings is bigger, I mean, that a new data has been inserted on the content provider CallLog.Calls.

So, I still have a lot of doubts related to this issue. I don't know where to register the content observer. My intention is, when something changes in the CallLog content provider, the insert method of the code will be used.

I mean, the code won't do anything unless new data has been added to the CallLog content provider. If some data has been added to the CallLog content provider, then the code will query the new data, and then will insert. I wanna do this, because without a content observer the application was inserting data in the database that was already inserted every time I run the application, got it?

So here is my code. If someone could tell me where to put registerContentObserver() and everything else that is needed.

public class RatedCalls extends ListActivity {

    private SQLiteDatabase db;
    private CallDataHelper dh = null;
    StringBuilder sb = new StringBuilder();
    OpenHelper openHelper = new OpenHelper(RatedCalls.this);

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Cursor cursor = getContentResolver().query(
                android.provider.CallLog.Calls.CONTENT_URI, null, null, null,
                android.provider.CallLog.Calls.DATE + " DESC ");

        dh = new CallDataHelper(this);
        db = openHelper.getWritableDatabase();

        startManagingCursor(cursor);
        int numberColumnId = cursor.getColumnIndex(android.provider.CallLog.Calls.NUMBER);
        int durationId = cursor.getColumnIndex(android.provider.CallLog.Calls.DURATION);
        int contactNameId = cursor.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME);
        int dateId = cursor.getColumnIndex(android.provider.CallLog.Calls.DATE);
        int numTypeId = cursor.getColumnIndex(android.provider.CallLog.Calls.CACHED_NUMBER_TYPE);

        Date dt = new Date();
        int hours = dt.getHours();
        int minutes = dt.getMinutes();
        int seconds = dt.getSeconds();
        String currTime = hours + ":" + minutes + ":" + seconds;

        ArrayList<String> callList = new ArrayList<String>();
        if (cursor.moveToFirst()) {
            do {
                String contactNumber = cursor.getString(numberColumnId);
                String contactName = cursor.getString(contactNameId);
                String duration = cursor.getString(durationId);
                String callDate = DateFormat.getDateInstance().format(dateId);
                String numType = cursor.getString(numTypeId);

                ContentValues values = new ContentValues();
                values.put("contact_id", 1);
                values.put("contact_name", contactName);
                values.put("number_type", numType);
                values.put("contact_number", contactNumber);
                values.put("duration", duration);
                values.put("date", callDate);
                values.put("current_time", currTime);
                values.put("cont", 1);

                this.db.insert(CallDataHelper.TABLE_NAME, null, values);

                Toast.makeText(getBaseContext(), "Inserted!", Toast.LENGTH_LONG);
                callList.add("Contact Number: " + contactNumber
                        + "\nContact Name: " + contactName + "\nDuration: "
                        + duration + "\nDate: " + callDate);

            } while (cursor.moveToNext());
        }
        setListAdapter(new ArrayAdapter<String>(this, R.layout.listitem, callList));

        ListView lv = getListView();
        lv.setTextFilterEnabled(true);
        lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(getApplicationContext(), ((TextView) view).getText(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

Body:
Here is the answer. Dont forget to register the content observer with this method:

registerContentObserver (Uri uri, boolean notifyForDescendents, ContentObserver observer)

And then you can create it like this.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.getApplicationContext()
    .getContentResolver()
    .registerContentObserver(
            android.provider.CallLog.Calls.CONTENT_URI, true,
            new MyContentObserver(handler));
}

class MyContentObserver extends ContentObserver {
    public MyContentObserver(Handler h) {
        super(h);
    }

    @Override
    public boolean deliverSelfNotifications() {
        return true;
    }

    @Override
    public void onChange(boolean selfChange) {
        Log.d(LOG_TAG, "MyContentObserver.onChange("+selfChange+")");
        super.onChange(selfChange);

        // here you call the method to fill the list
    }
}


问:
How can I know tracking is lost using KCF tracker
I am using KCF tracker to track a region selected by hand (mouse).
Once it is selected, the tracker is able to do it but the tracker fails to stop tracking after the target has moved outside the image.

Is there any way to know that the target region is lost or out of the image region.

答: You can now use Tracker::update to detect whether the object is lost. This feature was just recently added (see https://github.com/opencv/opencv_contrib/pull/1123) and should land in the next release after 3.2.0.


问:
Insert negative value into one sqlite column based on subtracting other values
I am having trouble writing a query that sets the value of a column called improvement to the difference between the integer values stored in  columns whose names are stored in the variables latest and prev_list.

My current query (with python string concatenation) is:

'UPDATE players SET improvement=(' + latest + '-' + prev_list + ') WHERE ' + latest + ' IS NOT NULL AND ' + prev_list + 'IS NOT NULL AND ' + prev_list + ' != 0 '

Now, if I change the query so that the values are added (+) instead of subtracted (-) inside of the parentheses the query works as expected, however when attempting to subtract them none of the improvement values are changes from the column default.

What am I doing wrong?

EDIT: As per a now-deleted comment - I tried adding brackets around the variable names, to no effect.

答:
I believe you should change your query like below per my understanding </p>

```<code>UPDATE players
SET improvement = latest - prev_list
WHERE latest IS NOT NULL
AND ( prev_list IS NOT NULL AND prev_list <> 0 )
</code>```

Body:
I believe you should change your query like below per my understanding

UPDATE players
SET improvement = latest - prev_list
WHERE latest IS NOT NULL
AND ( prev_list IS NOT NULL AND prev_list <> 0 )


问:
Why does the blue tooth low energy scanner need to be restarted again?
I noticed that in a couple implementations of the ble scanner that the scanning is stopped and started again after a given time period, like every 20 seconds.

Here for example here is a scanner class firing up the scanner in a separate thread. You can see in the start() method that the thread is put to sleep for a period of time, and the scanner is then stopped and restarted:

```<code>public class BleScanner extends Thread {

    private final BluetoothAdapter bluetoothAdapter;
    private final BluetoothAdapter.LeScanCallback mLeScanCallback;

    private volatile boolean isScanning = false;

    public BleScanner(BluetoothAdapter adapter, BluetoothAdapter.LeScanCallback callback) {

        bluetoothAdapter = adapter;
        mLeScanCallback = callback;
    }

    public boolean isScanning() {
        return isScanning;
    }

    public void startScanning() {
        synchronized (this) {
            isScanning = true;
            start();
        }
    }

    public void stopScanning() {
        synchronized (this) {
            isScanning = false;
            bluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

    @Override
    public void run() {

        try {

            // Thread goes into an infinite loop
            while (true) {

                synchronized (this) {

                    // If there is not currently a scan in progress, start one
                    if (!isScanning) break;
                    bluetoothAdapter.startLeScan(mLeScanCallback);
                }

                sleep(Constants.SCAN_PERIOD); // Thread sleeps before stopping the scan

                // stop scan
                synchronized (this) {
                    bluetoothAdapter.stopLeScan(mLeScanCallback);
                }

                // restart scan on next iteration of infinite while loop
            }

        } catch (InterruptedException ignore) {

        } finally { // Just in case there is an error, the scan will be stopped

            bluetoothAdapter.stopLeScan(mLeScanCallback);

            // The finally block always executes when the try block exits. This ensures that the
            // finally block is executed even if an unexpected exception occurs.
        }
    }
}
</code>```

Are there any benefits to stopping and restarting the scanner? Why not just let the scan continue perpetually?

答: There are advantages. On some devices, you would only see an advertisement from a device once per scan. On some you would see all advertisements. Also, restarting the scan cleans up some low-level stuff and is generally better than keeping the scanner active all the time.</p>

Body:
I noticed that in a couple implementations of the ble scanner that the scanning is stopped and started again after a given time period, like every 20 seconds.

Here for example here is a scanner class firing up the scanner in a separate thread. You can see in the start() method that the thread is put to sleep for a period of time, and the scanner is then stopped and restarted:

public class BleScanner extends Thread {

    private final BluetoothAdapter bluetoothAdapter;
    private final BluetoothAdapter.LeScanCallback mLeScanCallback;

    private volatile boolean isScanning = false;

    public BleScanner(BluetoothAdapter adapter, BluetoothAdapter.LeScanCallback callback) {

        bluetoothAdapter = adapter;
        mLeScanCallback = callback;
    }

    public boolean isScanning() {
        return isScanning;
    }

    public void startScanning() {
        synchronized (this) {
            isScanning = true;
            start();
        }
    }

    public void stopScanning() {
        synchronized (this) {
            isScanning = false;
            bluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

    @Override
    public void run() {

        try {

            // Thread goes into an infinite loop
            while (true) {

                synchronized (this) {

                    // If there is not currently a scan in progress, start one
                    if (!isScanning) break;
                    bluetoothAdapter.startLeScan(mLeScanCallback);
                }

                sleep(Constants.SCAN_PERIOD); // Thread sleeps before stopping the scan

                // stop scan
                synchronized (this) {
                    bluetoothAdapter.stopLeScan(mLeScanCallback);
                }

                // restart scan on next iteration of infinite while loop
            }

        } catch (InterruptedException ignore) {

        } finally { // Just in case there is an error, the scan will be stopped

            bluetoothAdapter.stopLeScan(mLeScanCallback);

            // The finally block always executes when the try block exits. This ensures that the
            // finally block is executed even if an unexpected exception occurs.
        }
    }
}

Are there any benefits to stopping and restarting the scanner? Why not just let the scan continue perpetually?