问:
Android bluetooth printer app works fine in debug mode but doesn't work in release mode
I am writing an Android app to print text on a bluetooth thermal printer.
Here is the complete code

The app works fine in the debug mode but when I generate a signed APK and install it on the device, it does not respond at all.

I have tried different solution suggested on stackoverflow but non of them worked.

This is my main activity

```<code>import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.lvrenyang.io.IOCallBack;
import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {

    private Handler mHandler; // Our main handler that will receive callback notifications
    // #defines for identifying shared types between calling functions
    private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names

    private static String TAG = "MAIN_ACTIVITY";
    private Activity activity;
    private Button btnConnect;

    private String name = "MTP-II";
    private String mac_address = "02:15:44:31:49:05";

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

        //Get the activity
        this.activity = this;

        //Button from the XML view
        btnConnect = findViewById(R.id.btnConnect);

        //Start the Init Work Service Async task
        new InitWorkService().execute();

        //Set onClickListener for test print button
        btnConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    //Check if name and address are set
                    if (name != "null" && mac_address != "null" && mac_address.contains(":")) {

                        if (!WorkService.workThread.isConnected()) {
                            WorkService.workThread.connectBt(mac_address);
                            //Sleep for 3 seconds
                            try {
                                Thread.sleep(3000);
                            } catch (Exception e) {
                            }
                        }
                        //Check if connected
                        if (WorkService.workThread.isConnected()) {
                            //Collect data in background Thread
                            new PrintData().execute();
                        } else {
                            Toast.makeText(activity, Global.toast_notconnect, Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        Toast.makeText(activity, "Please setup printer first!", Toast.LENGTH_LONG).show();
                    }
                }
                catch(Exception e){
                    Log.e(TAG, e.getMessage(), e.fillInStackTrace());}
            }
        });
    }

    /**
     * Background Async Task
     * */
    private class InitWorkService extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        protected String doInBackground(String... args){
            try{
                WorkService.cb = new IOCallBack() {
                    public void OnOpen() {
                        if (null != mHandler) {
                            Message msg = mHandler.obtainMessage(Global.MSG_IO_ONOPEN);
                            mHandler.sendMessage(msg);
                        }
                    }
                    public void OnClose() {
                        if (null != mHandler) {
                            Message msg = mHandler.obtainMessage(Global.MSG_IO_ONCLOSE);
                            mHandler.sendMessage(msg);
                        }
                    }
                };
            }
            catch(Exception e){
                Log.e(TAG, e.getMessage(), e.fillInStackTrace());
            }
            return null;
        }
        protected void onPostExecute(String file_url){
            try {
                mHandler = new MHandler(MainActivity.this);
                WorkService.addHandler(mHandler);

                if (null == WorkService.workThread) {
                    Intent intent = new Intent(activity, WorkService.class);
                    startService(intent);
                }
            }
            catch (Exception e) {
                Log.e(TAG, e.getMessage(), e.fillInStackTrace());
                Toast.makeText(activity, "Unable to initiate the WorkService!", Toast.LENGTH_LONG).show();
            }
        }
    }

    /**
     * Background Async Task
     * */
    class PrintData extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        protected String doInBackground(String... args){
            try{
                int nTextAlign=1;
                String text = "Test message!\r\n\r\n\r\n";
                String encoding = "UTF-8";
                byte[] hdrBytes = {0x1c, 0x26, 0x1b, 0x39, 0x01};

                Bundle dataAlign = new Bundle();
                Bundle dataTextOut = new Bundle();
                Bundle dataHdr = new Bundle();

                dataHdr.putByteArray(Global.BYTESPARA1, hdrBytes);
                dataHdr.putInt(Global.INTPARA1, 0);
                dataHdr.putInt(Global.INTPARA2, hdrBytes.length);

                dataAlign.putInt(Global.INTPARA1, nTextAlign);

                dataTextOut.putString(Global.STRPARA1, text);
                dataTextOut.putString(Global.STRPARA2, encoding);

                WorkService.workThread.handleCmd(Global.CMD_POS_WRITE,dataHdr);
                WorkService.workThread.handleCmd(Global.CMD_POS_SALIGN,dataAlign);
                WorkService.workThread.handleCmd(Global.CMD_POS_STEXTOUT,dataTextOut);
            }catch(Exception e){
                Log.e(TAG, e.getMessage(), e.fillInStackTrace());
            }
            return null;
        }
        protected void onPostExecute(String file_url){}
    }

    @Override
    protected void onUserLeaveHint()
    {
        Log.d("onUserLeaveHint","Home button pressed");
        super.onUserLeaveHint();
        //Unregister bluetooth receiver
        try{unregisterReceiver(bluetoothReceiver);}catch(Exception e){}
        //Disconnect bt connection
        try{WorkService.workThread.disconnectBt();}catch(Exception e){}
        // remove the handler
        try{WorkService.delHandler(mHandler);}catch(Exception e){}
        mHandler = null;
    }

    /**
     * Broadcast receiver for bluetooth state changes
     */
    private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            final String action = intent.getAction();
            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED))
            {
                final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR);
                switch (state)
                {
                    case BluetoothAdapter.STATE_OFF:
//                        closeConnection();//Close on going connection and disable button
                        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                        break;
                    case BluetoothAdapter.STATE_ON:
                        break;
                }
            }
        }
    };

    private static class MHandler extends Handler {
        WeakReference<MainActivity> mActivity;
        MHandler(MainActivity activity) {
            mActivity = new WeakReference<>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity theActivity = mActivity.get();
            switch (msg.what) {

                case Global.CMD_POS_STEXTOUTRESULT:
                case Global.CMD_POS_WRITERESULT: {
                    int result = msg.arg1;
                    Toast.makeText(
                            theActivity,
                            (result == 1) ? Global.toast_success
                                    : Global.toast_fail, Toast.LENGTH_SHORT).show();
                    Log.v(TAG, "Result: " + result);
                    break;
                }

            }
        }
    }

}
</code>```

答:
One reason for the application not responding is that you stop the main thread for 3 seconds on line 60 in the click listener of the button.
Replace the onCreate() method with the code below

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

    //Get the activity
    this.activity = this;

    //Button from the XML view
    btnConnect = findViewById(R.id.btnConnect);

    //Start the Init Work Service Async task
    new InitWorkService().execute();

    final ExecutorService es = Executors.newFixedThreadPool(1);

    //Set onClickListener for test print button
    btnConnect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            btnConnect.setEnabled(false);
            es.submit(new Runnable() {
                @Override
                public void run() {
                    connect();
                }
            });
        }
    });
}

private void connect() {
    try {
        //Check if name and address are set
        if (name != null && mac_address != null && mac_address.contains(":")) {

            if (!WorkService.workThread.isConnected()) {
                WorkService.workThread.connectBt(mac_address);
                //Sleep for 3 seconds
                try {
                    Thread.sleep(3000);
                } catch (Exception e) {
                }
            }
            //Check if connected
            if (WorkService.workThread.isConnected()) {
                //Collect data in background Thread
                new PrintData().execute();
            } else {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(activity, Global.toast_notconnect, Toast.LENGTH_SHORT).show();
                    }
                });
            }
        } else {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(activity, "Please setup printer first!", Toast.LENGTH_LONG).show();
                }
            });
        }
    } catch (Exception e) {
        Log.e(TAG, e.getMessage(), e.fillInStackTrace());
    }
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            btnConnect.setEnabled(true);
        }
    });
}
</code>```

Now the connection part executes in a new thread and only the UI operations go on the main one.

Please note that this code is not the optimal solution because it does not take into account the activity lifecycle. If the activity is re-created while the thread sleeps, there is still a reference kept to the old activity. But it should be a starting point for you.

Body:
I am writing an Android app to print text on a bluetooth thermal printer.
Here is the complete code

The app works fine in the debug mode but when I generate a signed APK and install it on the device, it does not respond at all.

I have tried different solution suggested on stackoverflow but non of them worked.

This is my main activity

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.lvrenyang.io.IOCallBack;
import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {

    private Handler mHandler; // Our main handler that will receive callback notifications
    // #defines for identifying shared types between calling functions
    private final static int REQUEST_ENABLE_BT = 1; // used to identify adding bluetooth names

    private static String TAG = "MAIN_ACTIVITY";
    private Activity activity;
    private Button btnConnect;

    private String name = "MTP-II";
    private String mac_address = "02:15:44:31:49:05";

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

        //Get the activity
        this.activity = this;

        //Button from the XML view
        btnConnect = findViewById(R.id.btnConnect);

        //Start the Init Work Service Async task
        new InitWorkService().execute();

        //Set onClickListener for test print button
        btnConnect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    //Check if name and address are set
                    if (name != "null" && mac_address != "null" && mac_address.contains(":")) {

                        if (!WorkService.workThread.isConnected()) {
                            WorkService.workThread.connectBt(mac_address);
                            //Sleep for 3 seconds
                            try {
                                Thread.sleep(3000);
                            } catch (Exception e) {
                            }
                        }
                        //Check if connected
                        if (WorkService.workThread.isConnected()) {
                            //Collect data in background Thread
                            new PrintData().execute();
                        } else {
                            Toast.makeText(activity, Global.toast_notconnect, Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        Toast.makeText(activity, "Please setup printer first!", Toast.LENGTH_LONG).show();
                    }
                }
                catch(Exception e){
                    Log.e(TAG, e.getMessage(), e.fillInStackTrace());}
            }
        });
    }

    /**
     * Background Async Task
     * */
    private class InitWorkService extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        protected String doInBackground(String... args){
            try{
                WorkService.cb = new IOCallBack() {
                    public void OnOpen() {
                        if (null != mHandler) {
                            Message msg = mHandler.obtainMessage(Global.MSG_IO_ONOPEN);
                            mHandler.sendMessage(msg);
                        }
                    }
                    public void OnClose() {
                        if (null != mHandler) {
                            Message msg = mHandler.obtainMessage(Global.MSG_IO_ONCLOSE);
                            mHandler.sendMessage(msg);
                        }
                    }
                };
            }
            catch(Exception e){
                Log.e(TAG, e.getMessage(), e.fillInStackTrace());
            }
            return null;
        }
        protected void onPostExecute(String file_url){
            try {
                mHandler = new MHandler(MainActivity.this);
                WorkService.addHandler(mHandler);

                if (null == WorkService.workThread) {
                    Intent intent = new Intent(activity, WorkService.class);
                    startService(intent);
                }
            }
            catch (Exception e) {
                Log.e(TAG, e.getMessage(), e.fillInStackTrace());
                Toast.makeText(activity, "Unable to initiate the WorkService!", Toast.LENGTH_LONG).show();
            }
        }
    }

    /**
     * Background Async Task
     * */
    class PrintData extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        protected String doInBackground(String... args){
            try{
                int nTextAlign=1;
                String text = "Test message!\r\n\r\n\r\n";
                String encoding = "UTF-8";
                byte[] hdrBytes = {0x1c, 0x26, 0x1b, 0x39, 0x01};

                Bundle dataAlign = new Bundle();
                Bundle dataTextOut = new Bundle();
                Bundle dataHdr = new Bundle();

                dataHdr.putByteArray(Global.BYTESPARA1, hdrBytes);
                dataHdr.putInt(Global.INTPARA1, 0);
                dataHdr.putInt(Global.INTPARA2, hdrBytes.length);

                dataAlign.putInt(Global.INTPARA1, nTextAlign);

                dataTextOut.putString(Global.STRPARA1, text);
                dataTextOut.putString(Global.STRPARA2, encoding);

                WorkService.workThread.handleCmd(Global.CMD_POS_WRITE,dataHdr);
                WorkService.workThread.handleCmd(Global.CMD_POS_SALIGN,dataAlign);
                WorkService.workThread.handleCmd(Global.CMD_POS_STEXTOUT,dataTextOut);
            }catch(Exception e){
                Log.e(TAG, e.getMessage(), e.fillInStackTrace());
            }
            return null;
        }
        protected void onPostExecute(String file_url){}
    }

    @Override
    protected void onUserLeaveHint()
    {
        Log.d("onUserLeaveHint","Home button pressed");
        super.onUserLeaveHint();
        //Unregister bluetooth receiver
        try{unregisterReceiver(bluetoothReceiver);}catch(Exception e){}
        //Disconnect bt connection
        try{WorkService.workThread.disconnectBt();}catch(Exception e){}
        // remove the handler
        try{WorkService.delHandler(mHandler);}catch(Exception e){}
        mHandler = null;
    }

    /**
     * Broadcast receiver for bluetooth state changes
     */
    private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            final String action = intent.getAction();
            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED))
            {
                final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR);
                switch (state)
                {
                    case BluetoothAdapter.STATE_OFF:
//                        closeConnection();//Close on going connection and disable button
                        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                        startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                        break;
                    case BluetoothAdapter.STATE_ON:
                        break;
                }
            }
        }
    };

    private static class MHandler extends Handler {
        WeakReference<MainActivity> mActivity;
        MHandler(MainActivity activity) {
            mActivity = new WeakReference<>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity theActivity = mActivity.get();
            switch (msg.what) {

                case Global.CMD_POS_STEXTOUTRESULT:
                case Global.CMD_POS_WRITERESULT: {
                    int result = msg.arg1;
                    Toast.makeText(
                            theActivity,
                            (result == 1) ? Global.toast_success
                                    : Global.toast_fail, Toast.LENGTH_SHORT).show();
                    Log.v(TAG, "Result: " + result);
                    break;
                }

            }
        }
    }

}

Body:
One reason for the application not responding is that you stop the main thread for 3 seconds on line 60 in the click listener of the button.
Replace the onCreate() method with the code below

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

    //Get the activity
    this.activity = this;

    //Button from the XML view
    btnConnect = findViewById(R.id.btnConnect);

    //Start the Init Work Service Async task
    new InitWorkService().execute();

    final ExecutorService es = Executors.newFixedThreadPool(1);

    //Set onClickListener for test print button
    btnConnect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            btnConnect.setEnabled(false);
            es.submit(new Runnable() {
                @Override
                public void run() {
                    connect();
                }
            });
        }
    });
}

private void connect() {
    try {
        //Check if name and address are set
        if (name != null && mac_address != null && mac_address.contains(":")) {

            if (!WorkService.workThread.isConnected()) {
                WorkService.workThread.connectBt(mac_address);
                //Sleep for 3 seconds
                try {
                    Thread.sleep(3000);
                } catch (Exception e) {
                }
            }
            //Check if connected
            if (WorkService.workThread.isConnected()) {
                //Collect data in background Thread
                new PrintData().execute();
            } else {
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(activity, Global.toast_notconnect, Toast.LENGTH_SHORT).show();
                    }
                });
            }
        } else {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(activity, "Please setup printer first!", Toast.LENGTH_LONG).show();
                }
            });
        }
    } catch (Exception e) {
        Log.e(TAG, e.getMessage(), e.fillInStackTrace());
    }
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            btnConnect.setEnabled(true);
        }
    });
}

Now the connection part executes in a new thread and only the UI operations go on the main one.

Please note that this code is not the optimal solution because it does not take into account the activity lifecycle. If the activity is re-created while the thread sleeps, there is still a reference kept to the old activity. But it should be a starting point for you.


来源: stackexchange

问:
Can we have two canvases in an activity ? (OR) Having a canvas outside the onDraw() is not working
```<code>@Override
        protected void onDraw(Canvas canvas) {
        // Draw graphic objects
         .....
             }

         public void displayCalc(){

           //Do some calculation & display results near these graphic objects
            String result = String.valueOf(value);

             //Do some calculation

              //Display Calculated values
             Canvas c =new Canvas();
             Paint paint = new Paint();
             paint.setStyle(Paint.Style.FILL);
             paint.setAntiAlias(true);
             paint.setColor(Color.WHITE);
             c.drawText(result,200,300,paint);
                     }
</code>```

But if i have the same thing in the function onDraw it works fine. I would like to know why or what changes i have to make to get it working

```<code>   @Override
    protected void onDraw(Canvas canvas) {

    // Draw graphic objects
    //Do some calculation & display results near these graphic objects
     .....
     String result = String.valueOf(value);

        //Display Calculated values
         Paint paint = new Paint();
         paint.setStyle(Paint.Style.FILL);
         paint.setAntiAlias(true);
         paint.setColor(Color.WHITE);
         canvas.drawText(result,200,300,paint);
}
</code>```

答:
If you want to have two SurfaceViews, than simply add them to your layout and give them both an own thread (or combine both drawings in one thread).

I don't get it why you want to draw on a separate canvas in your first method sample... Maybe you provide more information for what you try to achieve.

ContentLicense: CC BY-SA 3.0

Body:
@Override
        protected void onDraw(Canvas canvas) {
        // Draw graphic objects
         .....
             }

         public void displayCalc(){

           //Do some calculation & display results near these graphic objects
            String result = String.valueOf(value);

             //Do some calculation

              //Display Calculated values
             Canvas c =new Canvas();
             Paint paint = new Paint();
             paint.setStyle(Paint.Style.FILL);
             paint.setAntiAlias(true);
             paint.setColor(Color.WHITE);
             c.drawText(result,200,300,paint);
                     }

But if i have the same thing in the function onDraw it works fine. I would like to know why or what changes i have to make to get it working

   @Override
    protected void onDraw(Canvas canvas) {

    // Draw graphic objects
    //Do some calculation & display results near these graphic objects
     .....
     String result = String.valueOf(value);

        //Display Calculated values
         Paint paint = new Paint();
         paint.setStyle(Paint.Style.FILL);
         paint.setAntiAlias(true);
         paint.setColor(Color.WHITE);
         canvas.drawText(result,200,300,paint);
}


问:
Optimal way of creating object from two objects
I built this, which is working fine, it takes about 7-9 seconds to run and display.
I'm wondering, is there a faster/optimal way of building this custom object?

As you can see, I want all the drivers information from Win32_PNPsigneddriver but to that, I add two other properties from Win32_PNPentity (configmanagererrorcode and status) based on the DeviceID.

This way, the final object contains all drivers and shows if there is an error for the device using that driver.

```<code>$poste = "COMPUTER1234"

$DriversUp = Get-WmiObject -computername $poste Win32_PNPsigneddriver |
             Where-Object {$_.DeviceName -ne $null}
$Devices = Get-WmiObject -computername $poste Win32_PNPentity

$DriversDevices = foreach ($driver in $DriversUp) {
    $driver |
        Select-Object DeviceClass, Manufacturer, DeviceName,
            FriendlyName, DriverName, InfName,
            @{name='Status';expression={$Devices | Where-Object {$_.DeviceID -eq "$($driver.DeviceID)"} | Select-Object -ExpandProperty status}},
            @{name='ConfigManagerErrorCode';expression={$Devices | Where-Object {$_.DeviceID -eq "$($driver.DeviceID)"} | Select-Object -ExpandProperty ConfigManagerErrorCode}},
            @{name='DriverDate';expression={[DateTime]::ParseExact(($_.DriverDate).Split('.')[0], "yyyyMMddHHmmss", [System.Globalization.CultureInfo]::InvariantCulture)}},
            DriverVersion
}

$DriversDevices |
    Sort-Object DeviceClass |
    Out-GridView -Title "$poste - Drivers utilisés"
</code>```

Like I said everything works fine already. However, I'm curious to know if there's a faster way!

答:
The bottleneck is searching for a device every time using Where-Object.

The following code uses Group-Object to solve the issue.

```<code>$poste = "COMPUTER1234"

$DriversUp = Get-WmiObject -ComputerName $poste Win32_PnPSignedDriver -Filter "DeviceName != NULL"
$Devices = Get-WmiObject -ComputerName $poste Win32_PnPEntity -Property DeviceID,Status,ConfigManagerErrorCode

@($DriversUp; $Devices) | Group-Object DeviceID | Where-Object Count -eq 2 | ForEach-Object {
    $driver, $device = $_.Group
    [pscustomobject]@{
        DeviceClass = $driver.DeviceClass
        Manufacturer = $driver.Manufacturer
        DeviceName = $driver.DeviceName
        FriendlyName = $driver.FriendlyName
        DriverName = $driver.DriverName
        InfName = $driver.InfName
        Status = $device.Status
        ConfigManagerErrorCode = $device.ConfigManagerErrorCode
        DriverDate = [datetime]::ParseExact($driver.DriverDate.Substring(0, 14), "yyyyMMddHHmmss", $null)
        DriverVersion = $driver.DriverVersion
    }
} | Sort-Object DeviceClass | Out-GridView -Title "$poste - Drivers utilisés"
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I built this, which is working fine, it takes about 7-9 seconds to run and display.
I'm wondering, is there a faster/optimal way of building this custom object?

As you can see, I want all the drivers information from Win32_PNPsigneddriver but to that, I add two other properties from Win32_PNPentity (configmanagererrorcode and status) based on the DeviceID.

This way, the final object contains all drivers and shows if there is an error for the device using that driver.

$poste = "COMPUTER1234"

$DriversUp = Get-WmiObject -computername $poste Win32_PNPsigneddriver |
             Where-Object {$_.DeviceName -ne $null}
$Devices = Get-WmiObject -computername $poste Win32_PNPentity

$DriversDevices = foreach ($driver in $DriversUp) {
    $driver |
        Select-Object DeviceClass, Manufacturer, DeviceName,
            FriendlyName, DriverName, InfName,
            @{name='Status';expression={$Devices | Where-Object {$_.DeviceID -eq "$($driver.DeviceID)"} | Select-Object -ExpandProperty status}},
            @{name='ConfigManagerErrorCode';expression={$Devices | Where-Object {$_.DeviceID -eq "$($driver.DeviceID)"} | Select-Object -ExpandProperty ConfigManagerErrorCode}},
            @{name='DriverDate';expression={[DateTime]::ParseExact(($_.DriverDate).Split('.')[0], "yyyyMMddHHmmss", [System.Globalization.CultureInfo]::InvariantCulture)}},
            DriverVersion
}

$DriversDevices |
    Sort-Object DeviceClass |
    Out-GridView -Title "$poste - Drivers utilisés"

Like I said everything works fine already. However, I'm curious to know if there's a faster way!

Body:
The bottleneck is searching for a device every time using Where-Object.

The following code uses Group-Object to solve the issue.

$poste = "COMPUTER1234"

$DriversUp = Get-WmiObject -ComputerName $poste Win32_PnPSignedDriver -Filter "DeviceName != NULL"
$Devices = Get-WmiObject -ComputerName $poste Win32_PnPEntity -Property DeviceID,Status,ConfigManagerErrorCode

@($DriversUp; $Devices) | Group-Object DeviceID | Where-Object Count -eq 2 | ForEach-Object {
    $driver, $device = $_.Group
    [pscustomobject]@{
        DeviceClass = $driver.DeviceClass
        Manufacturer = $driver.Manufacturer
        DeviceName = $driver.DeviceName
        FriendlyName = $driver.FriendlyName
        DriverName = $driver.DriverName
        InfName = $driver.InfName
        Status = $device.Status
        ConfigManagerErrorCode = $device.ConfigManagerErrorCode
        DriverDate = [datetime]::ParseExact($driver.DriverDate.Substring(0, 14), "yyyyMMddHHmmss", $null)
        DriverVersion = $driver.DriverVersion
    }
} | Sort-Object DeviceClass | Out-GridView -Title "$poste - Drivers utilisés"


问:
How to show a database row with my search button?
this is my search.php code. i am trying to search wherein the user will input the subscriber id and it will show the FirstName, LastName and address of the accepted SubscriberID</p>

```<code> <!doctype html>
<html>
<body>
 <?php
 $conn=mysqli_connect("localhost","root","kuyahajji","steve");
 if (isset($POST['submit-SubscriberID']))  {
    $choice = mysqli_real_escape_string($conn,$_POST['$SubscriberID']);
    $sql = "SELECT * FROM property WHERE SubscriberID='$choice'";
    $result = mysqli_query($conn,$sql);
    $queryResult = mysqli_num-rows($result);
    if ($queryResult > 0) {
        while($row = mysqli_fetch_assoc($result))
                {
            echo $result;
    }
    }
        else {
            echo "0 results";
    }
 }
 ?>

</body>
</html>
</code>```

答:
$row is array. To output required key use [] notation:

```<code>echo $row['FirstName'] . $row['LastName'];
</code>```

Also correct name for a function is mysqli_num_rows (all underscores).

Body:
this is my search.php code. i am trying to search wherein the user will input the subscriber id and it will show the FirstName, LastName and address of the accepted SubscriberID

 <!doctype html>

 <?php
 $conn=mysqli_connect("localhost","root","kuyahajji","steve");
 if (isset($POST['submit-SubscriberID']))  {
    $choice = mysqli_real_escape_string($conn,$_POST['$SubscriberID']);
    $sql = "SELECT * FROM property WHERE SubscriberID='$choice'";
    $result = mysqli_query($conn,$sql);
    $queryResult = mysqli_num-rows($result);
    if ($queryResult > 0) {
        while($row = mysqli_fetch_assoc($result))
                {
            echo $result;
    }
    }
        else {
            echo "0 results";
    }
 }
 ?>

Body:
$row is array. To output required key use [] notation:

echo $row['FirstName'] . $row['LastName'];

Also correct name for a function is mysqli_num_rows (all underscores).


问:
On Pandas, how to drop multiple rows based in a column
I am new to Pandas and I am trying to drop all rows that contain some respective countries (Albania, Uzbekistan, Brazil) from the Column country. However, the way I figured it out to do is one by one, as below:

```<code>indexCountry = df[df['country'] == 'Albania'].index
df.drop(indexCountry, inplace = True)

indexCountry = df[df['country'] == 'Uzbekistan'].index
df.drop(indexCountry, inplace = True)

indexCountry = df[df['country'] == 'Brazil'].index
df.drop(indexCountry, inplace = True)
</code>```

Is there a way to do this in one single code line, instead of having to do one for every country?

答:
Try:</p>

```<code>list_of_countries = ['Albania',  'Uzbekistan', 'Brazil']
indexCountry = df[df['country'].isin(list_of_countries)].index
df.drop(indexCountry, inplace = True)

or just:
list_of_countries = ['Albania',  'Uzbekistan', 'Brazil']
df[~df["country"].isin(list_of_countries)]
</code>```

Body:
I am new to Pandas and I am trying to drop all rows that contain some respective countries (Albania, Uzbekistan, Brazil) from the Column country. However, the way I figured it out to do is one by one, as below:

indexCountry = df[df['country'] == 'Albania'].index
df.drop(indexCountry, inplace = True)

indexCountry = df[df['country'] == 'Uzbekistan'].index
df.drop(indexCountry, inplace = True)

indexCountry = df[df['country'] == 'Brazil'].index
df.drop(indexCountry, inplace = True)

Is there a way to do this in one single code line, instead of having to do one for every country?

Body:
Try:

list_of_countries = ['Albania',  'Uzbekistan', 'Brazil']
indexCountry = df[df['country'].isin(list_of_countries)].index
df.drop(indexCountry, inplace = True)

or just:
list_of_countries = ['Albania',  'Uzbekistan', 'Brazil']
df[~df["country"].isin(list_of_countries)]


问:
is there any better way to do this js code?
I am making these panels to be resized to fit screen height as I click 'this' element. I feel like I hard coded those javascript, and I believe there must be better way. But couldn't really sort it out.

when one panel is clicked, its size is going to get bigger, and rest of pannels gonna get smaller

I would very much appreciate any suggestion of it.

I've tried making this function reusable, but then couldn't really come up with better solution as I am a begginer.

```<code>const panels = document.querySelectorAll('.panel');
        const panelsArr = Array.from(panels);

        panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))

        function getCurrentName(element) {
            const panel1 = document.querySelector('.panel1');
            const panel2 = document.querySelector('.panel2');
            const panel3 = document.querySelector('.panel3');
            const panel4 = document.querySelector('.panel4');

            console.log(this);
            if(this) {

                this.classList.toggle('active');

                if(this === panel1) {

                panel2.classList.toggle('inactive');
                panel3.classList.toggle('inactive');
                panel4.classList.toggle('inactive');
                } else if (this === panel2) {
                panel1.classList.toggle('inactive');
                panel3.classList.toggle('inactive');
                panel4.classList.toggle('inactive');

                } else if (this === panel3) {
                panel1.classList.toggle('inactive');
                panel2.classList.toggle('inactive');
                panel4.classList.toggle('inactive');

                } else if (this === panel4) {
                panel1.classList.toggle('inactive');
                panel2.classList.toggle('inactive');
                panel3.classList.toggle('inactive');
                }

            }

        }
</code>```

.panel {
    background-color: #002712;
    box-shadow: inset 0 0 0 .5rem rgba(255,255,255,0.1);
    min-height: 22.5vh;
    color: #fff;
    text-align: center;
    font-size: 2rem;
    background-size: cover;
    background-position: center;
    line-height: 8rem;
    transition:
    min-height .5s linear,
    font-size .2s linear .5s,
    line-height .2s linear .5s;
}

.panel1 { background-image: url("../images/steake.png"); }
.panel2 { background-image: url("../images/sundayRoast.png"); }
.panel3 { background-image: url("../images/image1(1).png"); }
.panel4 { background-image: url("../images/cannonbury.png"); }

.active {
    min-height: 37vh;
    line-height: 15rem;
    font-size: 2.3rem;
}

.inactive {
    min-height: 15vh;
    font-size: 1.2rem;
}
```

<pre class="lang-html prettyprint-override"><code><main>
            <section class="intro">
                <div class="intro-panels">
                    <section class="panel panel1">
                        <p>most original,</p>
                    </section>
                    <section class="panel panel2">
                        <p>best beer,</p>
                    </section>
                    <section class="panel panel3">
                        <p>grilled food</p>
                    </section>
                    <section class="panel panel4">
                        <p>Islington</p>
                    </section>
                </div>
            </section>
        </main>
</code>```

I expect simplified javascript code to achieve the same goal.

Here's how I've sorted it out by your answer. Thank you for your help guys.

```<code>
const panels = document.querySelectorAll('.panel');
        const panelsArr = Array.from(panels);

        panelsArr.forEach(panel => panel.addEventListener('click', getCurrentName))

        function getCurrentName(element) {
            if(this) {

                panelsArr.forEach(panel => panel.classList.toggle('inactive'));

                this.classList.toggle('inactive');
                this.classList.toggle('active');
            }

        }

</code>```

答:
You can toggle inactive class on all class elements but undo it again on the target element:

```<code>    const panels = document.querySelectorAll('.panel');
    const panelsArr = Array.from(panels);

    panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))

    function getCurrentName(element) {
        console.log(this);
        if(this) {

            // Toggle inactive on all elements
            for (i = 0; i < panels.length; ++i) {
              panels[i].classList.toggle('inactive');
            }

            //But undo for selected element again
            this.classList.toggle('inactive');
            this.classList.toggle('active');
        }

    }
</code>```

Body:
I am making these panels to be resized to fit screen height as I click 'this' element. I feel like I hard coded those javascript, and I believe there must be better way. But couldn't really sort it out.

when one panel is clicked, its size is going to get bigger, and rest of pannels gonna get smaller

I would very much appreciate any suggestion of it.

I've tried making this function reusable, but then couldn't really come up with better solution as I am a begginer.

const panels = document.querySelectorAll('.panel');
        const panelsArr = Array.from(panels);

        panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))

        function getCurrentName(element) {
            const panel1 = document.querySelector('.panel1');
            const panel2 = document.querySelector('.panel2');
            const panel3 = document.querySelector('.panel3');
            const panel4 = document.querySelector('.panel4');

            console.log(this);
            if(this) {

                this.classList.toggle('active');

                if(this === panel1) {

                panel2.classList.toggle('inactive');
                panel3.classList.toggle('inactive');
                panel4.classList.toggle('inactive');
                } else if (this === panel2) {
                panel1.classList.toggle('inactive');
                panel3.classList.toggle('inactive');
                panel4.classList.toggle('inactive');

                } else if (this === panel3) {
                panel1.classList.toggle('inactive');
                panel2.classList.toggle('inactive');
                panel4.classList.toggle('inactive');

                } else if (this === panel4) {
                panel1.classList.toggle('inactive');
                panel2.classList.toggle('inactive');
                panel3.classList.toggle('inactive');
                }

            }

        }

.panel {
    background-color: #002712;
    box-shadow: inset 0 0 0 .5rem rgba(255,255,255,0.1);
    min-height: 22.5vh;
    color: #fff;
    text-align: center;
    font-size: 2rem;
    background-size: cover;
    background-position: center;
    line-height: 8rem;
    transition:
    min-height .5s linear,
    font-size .2s linear .5s,
    line-height .2s linear .5s;
}

.panel1 { background-image: url("../images/steake.png"); }
.panel2 { background-image: url("../images/sundayRoast.png"); }
.panel3 { background-image: url("../images/image1(1).png"); }
.panel4 { background-image: url("../images/cannonbury.png"); }

.active {
    min-height: 37vh;
    line-height: 15rem;
    font-size: 2.3rem;
}

.inactive {
    min-height: 15vh;
    font-size: 1.2rem;
}

most original,

best beer,

grilled food

Islington

I expect simplified javascript code to achieve the same goal.

Here's how I've sorted it out by your answer. Thank you for your help guys.

const panels = document.querySelectorAll('.panel');
        const panelsArr = Array.from(panels);

        panelsArr.forEach(panel => panel.addEventListener('click', getCurrentName))

        function getCurrentName(element) {
            if(this) {

                panelsArr.forEach(panel => panel.classList.toggle('inactive'));

                this.classList.toggle('inactive');
                this.classList.toggle('active');
            }

        }

Body:
You can toggle inactive class on all class elements but undo it again on the target element:

    const panels = document.querySelectorAll('.panel');
    const panelsArr = Array.from(panels);

    panelsArr.forEach(panel => panel.addEventListener('click',getCurrentName))

    function getCurrentName(element) {
        console.log(this);
        if(this) {

            // Toggle inactive on all elements
            for (i = 0; i < panels.length; ++i) {
              panels[i].classList.toggle('inactive');
            }

            //But undo for selected element again
            this.classList.toggle('inactive');
            this.classList.toggle('active');
        }

    }


问:
Is it possible to display flexbox items in two rows instead of one?
What I'm trying to accomplish here is, I want to use two rows to display uncertain amount of items. I will use vertical scroll to show overflowed items. If I use below css then it displays the items in one row. I want to know if it's possible to use 2 rows instead of one or if there is any hack to achieve this using flexbox?

```<code>.items-list {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
}
</code>```

```<code><div class="items-list">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  .......
</div>
</code>```

I've been trying for hours to find a solution, or an answer if its even possible to do this with flexbox. Any help would be very much appreciated.

答:
You can do this using CSS grid:

.items-list {
  display: grid;
  grid-template-rows: 50px 50px; /* 2 rows of 50px */
  grid-auto-flow: column;  /* a column flow */
  grid-auto-columns:100px; /* each column will 100px of width */
  grid-gap: 5px;
  overflow: auto;
}
.item {
  border:2px solid red;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="items-list">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div></code>```

Related question to get another kind of layout: Can I use css-grid to display an unknown number of items, in left-to-right reading order, over two rows?

Body:
What I'm trying to accomplish here is, I want to use two rows to display uncertain amount of items. I will use vertical scroll to show overflowed items. If I use below css then it displays the items in one row. I want to know if it's possible to use 2 rows instead of one or if there is any hack to achieve this using flexbox?

.items-list {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
}

  .......

I've been trying for hours to find a solution, or an answer if its even possible to do this with flexbox. Any help would be very much appreciated.

Body:
You can do this using CSS grid:

.items-list {
  display: grid;
  grid-template-rows: 50px 50px; /* 2 rows of 50px */
  grid-auto-flow: column;  /* a column flow */
  grid-auto-columns:100px; /* each column will 100px of width */
  grid-gap: 5px;
  overflow: auto;
}
.item {
  border:2px solid red;
}

<div class="items-list">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

Related question to get another kind of layout: Can I use css-grid to display an unknown number of items, in left-to-right reading order, over two rows?


答:
You can do a filter like this:

```<code>df = df[~df["country"].isin(["Alabania", "Uzbekistan", "Brazil"])]
</code>```

~ is the negation of what it is followed by.

Title: On Pandas, how to drop multiple rows based in a column

Body:
You can do a filter like this:

df = df[~df["country"].isin(["Alabania", "Uzbekistan", "Brazil"])]

~ is the negation of what it is followed by.


问:
Changing the padding of content in a Flexbox HTML
The issue I'm having is that I'm trying to change the layout between min-width:975px max-width: 1280px. I want to move the image and the text around.

In the picture, you can see the text is too much to the left. I want to move it closer to the image. This is inside of a flexbox. I tried to use padding, but nothing changed.

How would I move the text closer to the image?

/*Header for picture, and description*/
#display {
    padding-top: 2em;
    border: solid .125em black;
    display: flex;
    flex-flow: wrap;
    background-color: white;
    opacity: 0.9;
}

#display > * {
    flex: 1 1 5%;
    padding: 1em;
}

article h1{
    font-size: 2em;
}

article p{
    padding-top: 2em;
}

@media screen and (min-width:975px max-width: 1280px){

    article{

    }
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code> <section id="display">
        <figure id="headshot">
            <img src="images/GM05.png" alt="headshot"/>
        </figure>
        <article>
            <h1>Name Goes Here</h1>
            <p>Cras tristique gravida tellus, id fringilla lorem pellentesque iaculis. Donec vitae risus mauris. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc consectetur purus sed diam iaculis congue. Morbi vitae nisl est. Sed sed justo vitae risus porta commodo vestibulum eget est. Cras eu augue enim. Etiam at commodo tellus, at posuere ligula. Vivamus at dolor eget sem faucibus aliquet sed et diam. Mauris vel leo eget nulla pulvinar suscipit vitae eu sem. Quisque nisi nibh, aliquet sit amet urna non, commodo fringilla tellus. Nullam tincidunt est nec tellus laoreet, id mollis urna pulvinar. Donec ligula ipsum, ultrices in venenatis quis, ultricies ut enim. Vivamus porttitor lobortis dui, id aliquam ipsum imperdiet non.</p>
        </article>
    </section></code>```

答:
Why do you set  flex: 1 1 5%; to the flex-child ?

It is the shorthand for

```<code>flex-grow:1;
flex-shrink:1;
flex-basis:5%;
</code>```

while flex-basis is

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

flex-basis

This defines the default size of an element before the remaining space is distributed. It can be a length (e.g. 20%, 5rem, etc.) or a keyword. The auto keyword means "look at my width or height property" (which was temporarily done by the main-size keyword until deprecated). The content keyword means "size it based on the item's content" - this keyword isn't well supported yet, so it's hard to test and harder to know what its brethren max-content, min-content, and fit-content do.

If you set  flex:1; to article, it should work fine, else, use the values you need (flex: X X X;), read the tutorials to go further.

/*Header for picture, and description*/

#display {
  padding-top: 2em;
  border: solid .125em black;
  display: flex;
  flex-flow: wrap;
  background-color: white;
  opacity: 0.9;
}

#display>* {
  padding: 1em;
}

article {
  flex: 1;
}

article h1 {
  font-size: 2em;
}

article p {
  padding-top: 2em;
}

@media screen and (min-width:975px max-width: 1280px) {
  article {}
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><section id="display">
  <figure id="headshot">
    <img src="images/GM05.png" alt="headshot" />
  </figure>
  <article>
    <h1>Name Goes Here</h1>
    <p>Cras tristique gravida tellus, id fringilla lorem pellentesque iaculis. Donec vitae risus mauris. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc consectetur purus sed diam iaculis congue. Morbi vitae nisl est. Sed sed justo vitae
      risus porta commodo vestibulum eget est. Cras eu augue enim. Etiam at commodo tellus, at posuere ligula. Vivamus at dolor eget sem faucibus aliquet sed et diam. Mauris vel leo eget nulla pulvinar suscipit vitae eu sem. Quisque nisi nibh, aliquet
      sit amet urna non, commodo fringilla tellus. Nullam tincidunt est nec tellus laoreet, id mollis urna pulvinar. Donec ligula ipsum, ultrices in venenatis quis, ultricies ut enim. Vivamus porttitor lobortis dui, id aliquam ipsum imperdiet non.</p>
  </article>
</section></code>```

Body:
The issue I'm having is that I'm trying to change the layout between min-width:975px max-width: 1280px. I want to move the image and the text around.

In the picture, you can see the text is too much to the left. I want to move it closer to the image. This is inside of a flexbox. I tried to use padding, but nothing changed.

How would I move the text closer to the image?

/*Header for picture, and description*/
#display {
    padding-top: 2em;
    border: solid .125em black;
    display: flex;
    flex-flow: wrap;
    background-color: white;
    opacity: 0.9;
}

#display > * {
    flex: 1 1 5%;
    padding: 1em;
}

article h1{
    font-size: 2em;
}

article p{
    padding-top: 2em;
}

@media screen and (min-width:975px max-width: 1280px){

    article{

    }
}

Name Goes Here

Cras tristique gravida tellus, id fringilla lorem pellentesque iaculis. Donec vitae risus mauris. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc consectetur purus sed diam iaculis congue. Morbi vitae nisl est. Sed sed justo vitae risus porta commodo vestibulum eget est. Cras eu augue enim. Etiam at commodo tellus, at posuere ligula. Vivamus at dolor eget sem faucibus aliquet sed et diam. Mauris vel leo eget nulla pulvinar suscipit vitae eu sem. Quisque nisi nibh, aliquet sit amet urna non, commodo fringilla tellus. Nullam tincidunt est nec tellus laoreet, id mollis urna pulvinar. Donec ligula ipsum, ultrices in venenatis quis, ultricies ut enim. Vivamus porttitor lobortis dui, id aliquam ipsum imperdiet non.

Body:
Why do you set  flex: 1 1 5%; to the flex-child ?

It is the shorthand for

flex-grow:1;
flex-shrink:1;
flex-basis:5%;

while flex-basis is

https://css-tricks.com/snippets/css/a-guide-to-flexbox/

flex-basis

This defines the default size of an element before the remaining space is distributed. It can be a length (e.g. 20%, 5rem, etc.) or a keyword. The auto keyword means "look at my width or height property" (which was temporarily done by the main-size keyword until deprecated). The content keyword means "size it based on the item's content" - this keyword isn't well supported yet, so it's hard to test and harder to know what its brethren max-content, min-content, and fit-content do.

If you set  flex:1; to article, it should work fine, else, use the values you need (flex: X X X;), read the tutorials to go further.

/*Header for picture, and description*/

#display {
  padding-top: 2em;
  border: solid .125em black;
  display: flex;
  flex-flow: wrap;
  background-color: white;
  opacity: 0.9;
}

#display>* {
  padding: 1em;
}

article {
  flex: 1;
}

article h1 {
  font-size: 2em;
}

article p {
  padding-top: 2em;
}

@media screen and (min-width:975px max-width: 1280px) {
  article {}
}

<section id="display">
  <figure id="headshot">
    <img src="images/GM05.png" alt="headshot" />
  </figure>
  <article>
    <h1>Name Goes Here</h1>
    <p>Cras tristique gravida tellus, id fringilla lorem pellentesque iaculis. Donec vitae risus mauris. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc consectetur purus sed diam iaculis congue. Morbi vitae nisl est. Sed sed justo vitae
      risus porta commodo vestibulum eget est. Cras eu augue enim. Etiam at commodo tellus, at posuere ligula. Vivamus at dolor eget sem faucibus aliquet sed et diam. Mauris vel leo eget nulla pulvinar suscipit vitae eu sem. Quisque nisi nibh, aliquet
      sit amet urna non, commodo fringilla tellus. Nullam tincidunt est nec tellus laoreet, id mollis urna pulvinar. Donec ligula ipsum, ultrices in venenatis quis, ultricies ut enim. Vivamus porttitor lobortis dui, id aliquam ipsum imperdiet non.</p>
  </article>
</section>


答:
Try something like this. Event delegation

document.addEventListener('click', (e) => {

  if(e.target.matches('.sizable')) {
    document.querySelectorAll('.sizable').forEach(div => {
      div.classList.remove('active');
      div.classList.add('inactive');
    });
    e.target.classList.add('active');
  }

});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.sizable {
  display: inline-block;
  border: 1px solid black;
  margin: 5px;
}

.inactive {
  width: 50px;
  height: 50px;
}

.active {
  width: 150px;
  height: 150px;
}</code>```

Stuff

Stuff

Stuff

Stuff

Stuff

Stuff
```

Title: is there any better way to do this js code?

Body:
Try something like this. Event delegation

document.addEventListener('click', (e) => {

  if(e.target.matches('.sizable')) {
    document.querySelectorAll('.sizable').forEach(div => {
      div.classList.remove('active');
      div.classList.add('inactive');
    });
    e.target.classList.add('active');
  }

});

.sizable {
  display: inline-block;
  border: 1px solid black;
  margin: 5px;
}

.inactive {
  width: 50px;
  height: 50px;
}

.active {
  width: 150px;
  height: 150px;
}

<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>
<div class="sizable">Stuff</div>


问:
Why does multi layer perceprons outperform RNN in CartPole?
Recently, I compared two models for a DQN on CartPole-v0 environment. One of them is a multilayer perceptron with 3 layers and the other is an RNN built up from an LSTM and 1 fully connected layer. I have an experience replay buffer of size 200000 and the training doesn't start until it is filled up.
Although MLP has solved the problem under a reasonable amount of training steps  (this means to achieve a mean reward of 195 for the last 100 episodes), the RNN model could not converge as quickly and its maximum mean reward did not even reach 195 too!

I have already tried to increase batch size, add more neurons to the LSTM'S hidden state, increase the RNN'S sequence length and making the fully connected layer more complex - but every attempt failed as I saw enormous fluctuations in mean reward so the model hardly converged at all. May these are the sings of early overfitting?

class DQN(nn.Module):
    def __init__(self, n_input, output_size, n_hidden, n_layers, dropout=0.3):
        super(DQN, self).__init__()

        self.n_layers = n_layers
        self.n_hidden = n_hidden

        self.lstm = nn.LSTM(input_size=n_input,
            hidden_size=n_hidden,
            num_layers=n_layers,
            dropout=dropout,
            batch_first=True)

        self.dropout= nn.Dropout(dropout)

        self.fully_connected = nn.Linear(n_hidden, output_size)

    def forward(self, x, hidden_parameters):
        batch_size = x.size(0)

        output, hidden_state = self.lstm(x.float(), hidden_parameters)

        seq_length = output.shape[1]

        output1 = output.contiguous().view(-1, self.n_hidden)
        output2 = self.dropout(output1)
        output3 = self.fully_connected(output2)

        new = output3.view(batch_size, seq_length, -1)
        new = new[:, -1]

        return new.float(), hidden_state

    def init_hidden(self, batch_size, device):
        weight = next(self.parameters()).data

        hidden = (weight.new(self.n_layers, batch_size, self.n_hidden).zero_().to(device),
            weight.new(self.n_layers, batch_size, self.n_hidden).zero_().to(device))

        return hidden
```

Contrarily to what I expected, the simpler model gave a much better result than the other; even though RNN is supposed to be better in processing time series data.

Can anybody tell me what's the reason for this?

Also, I have to state that I applied no feature engineering and both DQN's worked with raw data. Could RNN outperform the MLP on using normalized features? (I mean feeding both models with normalized data)

Is there anything you can recommend me to improve training efficiency on RNN's to achieve the best results?

答:
Contrary to what I expected the simpler model gave much better result that the other; even though RNN's supposed to be better in processing time series data.

There is no time series in the cart-pole, the state contains all the information needed for optimal decision. It would be different if, for instance, you would learn from images and you would need to estimate the pole velocity from a series of images.

Also, it is not true that the more complex model should perform better. On the contrary, it is more likely to overfit. For the cart-pole you don't even need a NN, a simple linear approximator with RBFs or random Fourier features would suffice. A RNN + LSTM is for sure an overkill for such a simple problem.

Body:
Recently, I compared two models for a DQN on CartPole-v0 environment. One of them is a multilayer perceptron with 3 layers and the other is an RNN built up from an LSTM and 1 fully connected layer. I have an experience replay buffer of size 200000 and the training doesn't start until it is filled up.
Although MLP has solved the problem under a reasonable amount of training steps  (this means to achieve a mean reward of 195 for the last 100 episodes), the RNN model could not converge as quickly and its maximum mean reward did not even reach 195 too!

I have already tried to increase batch size, add more neurons to the LSTM'S hidden state, increase the RNN'S sequence length and making the fully connected layer more complex - but every attempt failed as I saw enormous fluctuations in mean reward so the model hardly converged at all. May these are the sings of early overfitting?

class DQN(nn.Module):
    def __init__(self, n_input, output_size, n_hidden, n_layers, dropout=0.3):
        super(DQN, self).__init__()

        self.n_layers = n_layers
        self.n_hidden = n_hidden

        self.lstm = nn.LSTM(input_size=n_input,
            hidden_size=n_hidden,
            num_layers=n_layers,
            dropout=dropout,
            batch_first=True)

        self.dropout= nn.Dropout(dropout)

        self.fully_connected = nn.Linear(n_hidden, output_size)

    def forward(self, x, hidden_parameters):
        batch_size = x.size(0)

        output, hidden_state = self.lstm(x.float(), hidden_parameters)

        seq_length = output.shape[1]

        output1 = output.contiguous().view(-1, self.n_hidden)
        output2 = self.dropout(output1)
        output3 = self.fully_connected(output2)

        new = output3.view(batch_size, seq_length, -1)
        new = new[:, -1]

        return new.float(), hidden_state

    def init_hidden(self, batch_size, device):
        weight = next(self.parameters()).data

        hidden = (weight.new(self.n_layers, batch_size, self.n_hidden).zero_().to(device),
            weight.new(self.n_layers, batch_size, self.n_hidden).zero_().to(device))

        return hidden

Contrarily to what I expected, the simpler model gave a much better result than the other; even though RNN is supposed to be better in processing time series data.

Can anybody tell me what's the reason for this?

Also, I have to state that I applied no feature engineering and both DQN's worked with raw data. Could RNN outperform the MLP on using normalized features? (I mean feeding both models with normalized data)

Is there anything you can recommend me to improve training efficiency on RNN's to achieve the best results?


问:
Cannot capture the packet using libpcap
I am kind of new to use libpcap.

I am using this library to capture the packet and the code i wrote to the capture the packet is below.

The interface that I am tapping is always flooded with arp packet so there is always packet coming to the interface.But I cannot able to tap these packet. The interface is UP and running.
I got no error on pcap_open_live function.

The code is in C. And I am running this code on FreeBSD10 machine 32 bit.

```<code>void captutre_packet(char* ifname , int snaplen) {

    char ebuf[PCAP_ERRBUF_SIZE];
    int pflag = 0;/*promiscuous mode*/
    snaplen  = 100;
    pcap_t* pcap =  pcap_open_live(ifname, snaplen, !pflag , 0, ebuf);
    if(pcap!=NULL) {
            printf("pcap_open_live for %s  \n" ,ifname );
    }

    int fd = pcap_get_selectable_fd(pcap);
    pcap_setnonblock(pcap, 1, ebuf);

    fd_set fds;
    struct timeval tv;

    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    tv.tv_sec = 3;
    tv.tv_usec = 0;
    int retval = select(fd + 1, &fds, NULL, NULL, &tv);

    if (retval == -1)
            perror("select()");
        else if (retval) {
            printf("Data is available now.\n");
            printf("calling pcap_dispatch \n");
            pcap_dispatch(pcap , -1 , (pcap_handler) callback , NULL);
        }
        else
            printf("No data within 3 seconds.\n");
 }
    void
    callback(const char *unused, struct pcap_pkthdr *h, uint8_t *packet)
    {
            printf("got some packet \n");
    }
</code>```

I am always getting retval as 0 which is timeout.
I don't know what is happening under the hood I follow the tutorial and they also did exactly the same thing I do not know what i am missing.

I also want to understand how the packet from the ethernet layer once received get copied into this opened bpf socket/device (using pcap_open_live) and how the buffer is copied from kernel space to user space?

And for how long we can tap the packet till the kernel consume or reject the packet?

答:
The pcap_open_live() call provided 0 as the packet buffer timeout value (the fourth argument).  libpcap does not specify what a value of 0 means, because different packet capture mechanisms, on different operating systems, treat that value differently.

On systems using BPF, such as the BSDs and macOS, it means "wait until the packet buffer is completely full before providing the packets.  If the packet buffer is large (it defaults to about 256K, on FreeBSD), and the packets are small (60 bytes for ARP packets), it may take a significant amount of time for the buffer to fill - longer than the timeout you're handing to select().

It's probably best to have a timeout value of between 100 milliseconds and 1 second, so pass an argument of somewhere between 100 and 1000, not 0.

Title: Cannot capture the packet using libpcap

Body:
I am kind of new to use libpcap.

I am using this library to capture the packet and the code i wrote to the capture the packet is below.

The interface that I am tapping is always flooded with arp packet so there is always packet coming to the interface.But I cannot able to tap these packet. The interface is UP and running.
I got no error on pcap_open_live function.

The code is in C. And I am running this code on FreeBSD10 machine 32 bit.

void captutre_packet(char* ifname , int snaplen) {

    char ebuf[PCAP_ERRBUF_SIZE];
    int pflag = 0;/*promiscuous mode*/
    snaplen  = 100;
    pcap_t* pcap =  pcap_open_live(ifname, snaplen, !pflag , 0, ebuf);
    if(pcap!=NULL) {
            printf("pcap_open_live for %s  \n" ,ifname );
    }

    int fd = pcap_get_selectable_fd(pcap);
    pcap_setnonblock(pcap, 1, ebuf);

    fd_set fds;
    struct timeval tv;

    FD_ZERO(&fds);
    FD_SET(fd, &fds);

    tv.tv_sec = 3;
    tv.tv_usec = 0;
    int retval = select(fd + 1, &fds, NULL, NULL, &tv);

    if (retval == -1)
            perror("select()");
        else if (retval) {
            printf("Data is available now.\n");
            printf("calling pcap_dispatch \n");
            pcap_dispatch(pcap , -1 , (pcap_handler) callback , NULL);
        }
        else
            printf("No data within 3 seconds.\n");
 }
    void
    callback(const char *unused, struct pcap_pkthdr *h, uint8_t *packet)
    {
            printf("got some packet \n");
    }

I am always getting retval as 0 which is timeout.
I don't know what is happening under the hood I follow the tutorial and they also did exactly the same thing I do not know what i am missing.

I also want to understand how the packet from the ethernet layer once received get copied into this opened bpf socket/device (using pcap_open_live) and how the buffer is copied from kernel space to user space?

And for how long we can tap the packet till the kernel consume or reject the packet?


问:
angular ng2-charts (stacked bar charts) is not loading from json file
I am trying to load the records from a json (ng2-charts stacked bar chart) file but the data is not loading into the charts. I am able to see the response with console.log but not able assign the json array to chart array. Please suggest me what should I do?

My component file.

```<code>import { Component, OnInit } from "@angular/core";
import { ChartOptions, ChartType, ChartDataSets } from "chart.js";
import * as pluginDataLabels from "chartjs-plugin-datalabels";
import { Label } from "ng2-charts";
import { BarChartService } from "../service/bar-chart.service";

@Component({
  selector: "app-second-bar-chart",
  templateUrl: "./second-bar-chart.component.html",
  styleUrls: ["./second-bar-chart.component.css"]
})
export class SecondBarChartComponent implements OnInit {
  public barChartData: ChartDataSets[];
  public parentChartData: ChartDataSets[];
  public myLabelsArray: Label[];
  public barChartLabels: Label[];
  constructor(private barchartservice: BarChartService) {}

  ngOnInit() {
    // WITH API CALL AND OBSERVABLE
    this.barchartservice.getBarChartData().subscribe(res => {
      console.log(res);
      this.parentChartData = res;
    });
  }
}
</code>```

my service file:

```<code>import { Injectable } from "@angular/core";
import { ChartOptions, ChartType, ChartDataSets } from "chart.js";
import * as pluginDataLabels from "chartjs-plugin-datalabels";
import { Label } from "ng2-charts";
import { HttpClient } from "@angular/common/http";
import { BarChart } from "../model/bar-chart";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";

@Injectable({
  providedIn: "root"
})
export class BarChartService {
  public barChartData: ChartDataSets[];
  public parentChartData: ChartDataSets[];
  public myLabelsArray: Label[];
  public barChartLabels: Label[];

  private _url: string = "../../assets/dummy-chart/bar-chart-two.json";

  constructor(private http: HttpClient) {}

 getBarChartData(): Observable<any> {
    return this.http.get<any>(this._url);
  }
}
</code>```

my json file:

```<code>[
  { "data": [14, 81], "label": "Male", "stack": "1" },
  { "data": [25, 72], "label": "Female", "stack": "1" }
]
</code>```

Data should be loaded from the json file and reflect in the chart.Please help me.

答:
Hey Biplob welcome to stack overflow,

So in your issue , the json object does'nt have the right structure . I am using something similar in my app.

Initially to have a proper structure create an interface which defines this structure like :

```<code>export interface IChartDataConfiguration {
    type:string;
    options:any;
    data: any;
    labels: any[];
    legend: boolean;
}
</code>```

Then define a property in the component' class

```<code>barChartData: IChartDataConfiguration;
</code>```

Try use a json object with this structure

```<code>{
        "type": "bar",
        "options": {
            "responsive": true,
            "scales": { "xAxes": [{}], "yAxes": [{}] },
            "plugins": {
              "datalabels": {
                "anchor": "end",
                "align": "end"
              }
            }
          },
          "data": [
            { "data": [65, 59, 80, 81, 56, 55, 40], "label": "Series A" },
            { "data": [28, 48, 40, 19, 86, 27, 90], "label": "Series B" }
          ],

          "labels":["2006", "2007", "2008", "2009", "2010", "2011", "2012"],
          "legend": true
    }
</code>```

So get the json with this structure and then assign it in a member of your component class and then in the template:

```<code>            <canvas baseChart
                  height="60%"
                  [datasets]="yourComponentProperty"
                  [labels]="barChartData.labels"
                  [options]="barChartData.options"
                  [legend]="barChartData.legend"
                  [chartType]="barChartData.type">
                </canvas>
</code>```

Hope that helps.

Body:
I am trying to load the records from a json (ng2-charts stacked bar chart) file but the data is not loading into the charts. I am able to see the response with console.log but not able assign the json array to chart array. Please suggest me what should I do?

My component file.

import { Component, OnInit } from "@angular/core";
import { ChartOptions, ChartType, ChartDataSets } from "chart.js";
import * as pluginDataLabels from "chartjs-plugin-datalabels";
import { Label } from "ng2-charts";
import { BarChartService } from "../service/bar-chart.service";

@Component({
  selector: "app-second-bar-chart",
  templateUrl: "./second-bar-chart.component.html",
  styleUrls: ["./second-bar-chart.component.css"]
})
export class SecondBarChartComponent implements OnInit {
  public barChartData: ChartDataSets[];
  public parentChartData: ChartDataSets[];
  public myLabelsArray: Label[];
  public barChartLabels: Label[];
  constructor(private barchartservice: BarChartService) {}

  ngOnInit() {
    // WITH API CALL AND OBSERVABLE
    this.barchartservice.getBarChartData().subscribe(res => {
      console.log(res);
      this.parentChartData = res;
    });
  }
}

my service file:

import { Injectable } from "@angular/core";
import { ChartOptions, ChartType, ChartDataSets } from "chart.js";
import * as pluginDataLabels from "chartjs-plugin-datalabels";
import { Label } from "ng2-charts";
import { HttpClient } from "@angular/common/http";
import { BarChart } from "../model/bar-chart";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";

@Injectable({
  providedIn: "root"
})
export class BarChartService {
  public barChartData: ChartDataSets[];
  public parentChartData: ChartDataSets[];
  public myLabelsArray: Label[];
  public barChartLabels: Label[];

  private _url: string = "../../assets/dummy-chart/bar-chart-two.json";

  constructor(private http: HttpClient) {}

 getBarChartData(): Observable<any> {
    return this.http.get<any>(this._url);
  }
}

my json file:

[
  { "data": [14, 81], "label": "Male", "stack": "1" },
  { "data": [25, 72], "label": "Female", "stack": "1" }
]

Data should be loaded from the json file and reflect in the chart.Please help me.

Body:
Hey Biplob welcome to stack overflow,

So in your issue , the json object does'nt have the right structure . I am using something similar in my app.

Initially to have a proper structure create an interface which defines this structure like :

export interface IChartDataConfiguration {
    type:string;
    options:any;
    data: any;
    labels: any[];
    legend: boolean;
}

Then define a property in the component' class

barChartData: IChartDataConfiguration;

Try use a json object with this structure

{
        "type": "bar",
        "options": {
            "responsive": true,
            "scales": { "xAxes": [{}], "yAxes": [{}] },
            "plugins": {
              "datalabels": {
                "anchor": "end",
                "align": "end"
              }
            }
          },
          "data": [
            { "data": [65, 59, 80, 81, 56, 55, 40], "label": "Series A" },
            { "data": [28, 48, 40, 19, 86, 27, 90], "label": "Series B" }
          ],

          "labels":["2006", "2007", "2008", "2009", "2010", "2011", "2012"],
          "legend": true
    }

So get the json with this structure and then assign it in a member of your component class and then in the template:

            <canvas baseChart
                  height="60%"
                  [datasets]="yourComponentProperty"
                  [labels]="barChartData.labels"
                  [options]="barChartData.options"
                  [legend]="barChartData.legend"
                  [chartType]="barChartData.type">
                </canvas>

Hope that helps.


问:
OpenGL - skeletal animation - bone rotates around origin
I am following a tutorial series about skeletal animation on Youtube (https://www.youtube.com/watch?v=f3Cr8Yx3GGA) and have ran into a problem – everything works fine, except when I rotate one of the bones (or "joints"), they get rotated around the scene origin, meaning they do not stay in place but are translated. The following image illustrates the problem:

How can I make it so that the translation doesn't happen? I have been going over the tutorial series multiple times now, but cannot identify which step would prevent this from happening.

The code is very large, split into around a dozen files, and I don't know which section might be causing the issue, so I do not think there's much point in posting it all here (it should be similar to the code in the tutorial, even though I am using C++ while he's working in Java. The tutorial code can be found here: https://github.com/TheThinMatrix/OpenGL-Animation). If you could give me even general advice on how this issue is normally solved in skeletal animation, it should hopefully be enough for me to at least identify the part that's wrong and try moving from there.

答:
You just need to pay attention to what you are rotating around.

A way to fix this: Rotate it first and then translate it. Rotate the object while it is at the origin and then translate the object to where you want it.

Repeatedly do this when things change throughout your program. Start the object at the origin, do the desired rotation, and then translate out to it's final resting position.


问:
Changing characters in a data frame to numeric with if-function
For example, i have this dataframe and i wanna change characters into numbers:

```<code>x<-c("a","b","c","a","a","a","c","b","b","a","c","a","b","b","c")
y<-rnorm(15)
z<-rnorm(15)
data<-data.frame(x,y,z)
</code>```

I know this way:

```<code>data$x<-factor(data$x,levels = c("a","b","c"),labels = c(1,2,3))
</code>```

but if i have more characters it will be take a lot. I wanna learn how can i change it with if-function.

答:
We can just use

```<code>as.numeric(data$x)
#[1] 1 2 3 1 1 1 3 2 2 1 3 1 2 2 3
</code>```

If it needs to be encoded in the occurence of unique elements

```<code>as.numeric(factor(data$x, levels = unique(data$x)))
#[1] 1 2 3 1 1 1 3 2 2 1 3 1 2 2 3
</code>```

If we are okay to use packages, .GRP from data.table can be helpful

```<code>library(data.table)
setDT(data)[, x1 := .GRP , x]
</code>```

Body:
For example, i have this dataframe and i wanna change characters into numbers:

x<-c("a","b","c","a","a","a","c","b","b","a","c","a","b","b","c")
y<-rnorm(15)
z<-rnorm(15)
data<-data.frame(x,y,z)

I know this way:

data$x<-factor(data$x,levels = c("a","b","c"),labels = c(1,2,3))

but if i have more characters it will be take a lot. I wanna learn how can i change it with if-function.

Body:
We can just use

as.numeric(data$x)
#[1] 1 2 3 1 1 1 3 2 2 1 3 1 2 2 3

If it needs to be encoded in the occurence of unique elements

as.numeric(factor(data$x, levels = unique(data$x)))
#[1] 1 2 3 1 1 1 3 2 2 1 3 1 2 2 3

If we are okay to use packages, .GRP from data.table can be helpful

library(data.table)
setDT(data)[, x1 := .GRP , x]


Title: Changing characters in a data frame to numeric with if-function

Body:
This works without relying on factors:

library(dplyr)
data %>%
  mutate(x = group_indices(.,x))

# A tibble: 15 x 3
       x       y      z
   <int>   <dbl>  <dbl>
 1     1  1.61    0.865
 2     2 -0.424  -0.939
 3     3 -0.773  -0.558
 4     1  0.108   0.336
 5     1 -0.219   1.82


问:
Scale and crop an image in python PIL without exceeding the image dimensions
I am cropping an image using python PIL. Say my image is as such:

This is the simple code snippet I use for cropping:

```<code>from PIL import Image
im = Image.open(image)
cropped_image = im.crop((topLeft_x, topLeft_y, bottomRight_x, bottomRight_y))
cropped_image.save("Out.jpg")
</code>```

The result of this is:

I want to scale out this cropped image keeping the aspect ratio (proportionate width and height) same by say 20% to look something like this without exceeding the image dimensions.

How should I scale out the crop such that the aspect ratio is maintained while not exceeding the image boundary/ dimensions?

答:
You should calculate the center of your crop and use it there on.
As an example:

```<code>crop_width = right - left
crop_height = bottom - top
crop_center_x = int(left + crop_width/2)
crop_center_y = (top + crop_height/2)
</code>```

In this way you will obtain the (x,y) point which corresponds to the center of your crop w.r.t your original image.
In that case, you will know that the maximum width for your crop would be the minimum between the center value and the outer bounds of the original image minus the center itself:

```<code>im = Image.open("brad.jpg")
l = 200
t = 200
r = 300
b = 300
cropped = im.crop((l, t, r, b))
</code>```

Which gives you:

If you want to "enlarge" it to the maximum starting from the same center, then you will have:

```<code>max_width = min(crop_center_x, im.size[0]-crop_center_x)
max_height = min(crop_center_y, im.size[1]-crop_center_y)
new_l = crop_center_x - max_width
new_t = crop_center_x - max_height
new_r = crop_center_x + max_width
new_b = crop_center_x + max_height
new_crop = im.crop((new_l, new_t, new_r, new_b))
</code>```

which gives as a result, having the same center:

Edit

If you want to keep the aspect ratio you should retrieve it (the ratio) before and apply the crop only if the resulting size would still fit the original image. As an example, if you want to enlarge it by 20%:

```<code>ratio = crop_height/crop_width
scale = 20/100
new_width = int(crop_width + (crop_width*scale))

# Here we are using the previously calculated value for max_width to
# determine if the new one would be too large.
# Note that the width that we calculated here (new_width) refers to both
# sides of the crop, while the max_width calculated previously refers to
# one side only; same for height. Sorry for the confusion.
if max_width < new_width/2:
    new_width = int(2*max_width)

new_height = int(new_width*ratio)

# Do the same for the height, update width if necessary
if max_height < new_height/2:
    new_height = int(2*max_height)
    new_width = int(new_height/ratio)

adjusted_scale = (new_width - crop_width)/crop_width

if adjusted_scale != scale:
    print("Scale adjusted to: {:.2f}".format(adjusted_scale))

new_l = int(crop_center_x - new_width/2)
new_r = int(crop_center_x + new_width/2)
new_t = int(crop_center_y - new_height/2)
new_b = int(crop_center_y + new_height/2)
</code>```

Once you have the width and height values the process to get the crop is the same as above.

Body:
I am cropping an image using python PIL. Say my image is as such:

This is the simple code snippet I use for cropping:

from PIL import Image
im = Image.open(image)
cropped_image = im.crop((topLeft_x, topLeft_y, bottomRight_x, bottomRight_y))
cropped_image.save("Out.jpg")

The result of this is:

I want to scale out this cropped image keeping the aspect ratio (proportionate width and height) same by say 20% to look something like this without exceeding the image dimensions.

How should I scale out the crop such that the aspect ratio is maintained while not exceeding the image boundary/ dimensions?

Body:
You should calculate the center of your crop and use it there on.
As an example:

crop_width = right - left
crop_height = bottom - top
crop_center_x = int(left + crop_width/2)
crop_center_y = (top + crop_height/2)

In this way you will obtain the (x,y) point which corresponds to the center of your crop w.r.t your original image.
In that case, you will know that the maximum width for your crop would be the minimum between the center value and the outer bounds of the original image minus the center itself:

im = Image.open("brad.jpg")
l = 200
t = 200
r = 300
b = 300
cropped = im.crop((l, t, r, b))

Which gives you:

If you want to "enlarge" it to the maximum starting from the same center, then you will have:

max_width = min(crop_center_x, im.size[0]-crop_center_x)
max_height = min(crop_center_y, im.size[1]-crop_center_y)
new_l = crop_center_x - max_width
new_t = crop_center_x - max_height
new_r = crop_center_x + max_width
new_b = crop_center_x + max_height
new_crop = im.crop((new_l, new_t, new_r, new_b))

which gives as a result, having the same center:

Edit

If you want to keep the aspect ratio you should retrieve it (the ratio) before and apply the crop only if the resulting size would still fit the original image. As an example, if you want to enlarge it by 20%:

ratio = crop_height/crop_width
scale = 20/100
new_width = int(crop_width + (crop_width*scale))

# Here we are using the previously calculated value for max_width to
# determine if the new one would be too large.
# Note that the width that we calculated here (new_width) refers to both
# sides of the crop, while the max_width calculated previously refers to
# one side only; same for height. Sorry for the confusion.
if max_width < new_width/2:
    new_width = int(2*max_width)

new_height = int(new_width*ratio)

# Do the same for the height, update width if necessary
if max_height < new_height/2:
    new_height = int(2*max_height)
    new_width = int(new_height/ratio)

adjusted_scale = (new_width - crop_width)/crop_width

if adjusted_scale != scale:
    print("Scale adjusted to: {:.2f}".format(adjusted_scale))

new_l = int(crop_center_x - new_width/2)
new_r = int(crop_center_x + new_width/2)
new_t = int(crop_center_y - new_height/2)
new_b = int(crop_center_y + new_height/2)

Once you have the width and height values the process to get the crop is the same as above.


问:
WPF ProgressBar doesn't update?
I am trying to update my progressbar by using data bindings. The XAML file contains the progressbar:

```<code><ProgressBar Height="23" Name="progressBar" VerticalAlignment="Bottom" Margin="207,444,0,0" Minimum="0" Maximum="{Binding ProgressBarMax}" Value="{Binding ProgressBarValue}" />
</code>```

My relevant C# class contains the getter & setter:

```<code>    private int progressBarMax;
    public int ProgressBarMax
    {
        get
        {
            if (this.progressBarMax == 0)
                this.progressBarMax = 1;
            return this.progressBarMax;
        }
        set
        {
            this.progressBarMax = value;
        }
    }

    private int progressBarValue;
    public int ProgressBarValue
    {
        get
        {
            return progressBarValue;
        }
        set
        {
            progressBarValue = value;
        }
    }
</code>```

In my "update" method the maximum is being set. For example like this.progressBarMax = 100;. In a loop the progressbar value is getting the value += 1. To see the updates I used Application.DoEvents(), later I will implement threads. The data binding has to be correct, because I have other components that work fine.

So why doesn't my progressbar update?

Thank you for your help.

答: I found the mistake in my code. Unfortunately I changed my private members, not the public properties. So when using this.ProgressBarValue += 1; instead of this.progressBarValue += 1; everything works fine.

Title: WPF ProgressBar doesn't update?

Body:
I am trying to update my progressbar by using data bindings. The XAML file contains the progressbar:

<ProgressBar Height="23" Name="progressBar" VerticalAlignment="Bottom" Margin="207,444,0,0" Minimum="0" Maximum="{Binding ProgressBarMax}" Value="{Binding ProgressBarValue}" />

My relevant C# class contains the getter & setter:

    private int progressBarMax;
    public int ProgressBarMax
    {
        get
        {
            if (this.progressBarMax == 0)
                this.progressBarMax = 1;
            return this.progressBarMax;
        }
        set
        {
            this.progressBarMax = value;
        }
    }

    private int progressBarValue;
    public int ProgressBarValue
    {
        get
        {
            return progressBarValue;
        }
        set
        {
            progressBarValue = value;
        }
    }

In my "update" method the maximum is being set. For example like this.progressBarMax = 100;. In a loop the progressbar value is getting the value += 1. To see the updates I used Application.DoEvents(), later I will implement threads. The data binding has to be correct, because I have other components that work fine.

So why doesn't my progressbar update?

Thank you for your help.


问:
Heroku giving 'Picked up JAVA_TOOL_OPTIONS', and setting JMX to 'true' is not stopping it
The way my program works, which is a java runtime for discord, it displays the console output from a java program. The issue is that right now, the program picks up the 'Picked up' message, then picks up nothing else. I'd like to get rid of this message. How would I do that?</p>

答:
Heroku sets JAVA_TOOL_OPTIONS for you dyno. You can read about it here

It seems you can't really remove the message. Here is a question with more information about that.

But the message is sent to stderr. Maybe ignore that?