问:
Caliburn.Micro - Calling method guard when updating field of item in BindableCollection
I have a property BindableCollection<Cat> { get; private set; } with a number of Cat objects that is bound to an ItemsControl in my WPF XAML.

I then have the following code that is attached to a button inside this ItemsControl.

XAML snippet

```<code><Button Content="Pat Cat" cal:Message.Attach="PatCat($dataContext)" />
</code>```

In the ViewModel...

```<code>BindableCollection<Cat> { get; private set; }

public bool CanPatCat(Cat cat)
{
   return cat.Pattable && cat.Alive;
}

public void PatCat(Cat cat)
{
    // pat the cat
    cat.Alive = false;
}
</code>```

Given this is a method guard and not a property, how do I notify the UI so that the CanPat method is evaluated for each Cat in the BindableCollection given the guard method will now return false once the Cat has been pat?

答:
While for properties a specific and sophisticated UI awareness mechanism exists (I am talking about Binding), for methods the situation is completely different.
Using events in this context in my humble opinion is not suitable, so I thought a solution which is based on extending Caliburn Micro framework.

First of all we need to create a specific ActionMessage which is meant for re-executing the guard method after its invocation. I called it RefreshableActionMessage.

```<code>public class RefreshableActionMessage : ActionMessage
{
    private bool refreshAfterInvoke = true;

    public bool RefreshAfterInvoke
    {
        get { return refreshAfterInvoke; }
        set { refreshAfterInvoke = value; }
    }
}
</code>```

Now we have to use it in our "guarded" button (yes, we need to use the verbose syntax):

```<code><Button Content="Pat Cat">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:RefreshableActionMessage MethodName="PatCat">
                <cal:Parameter Value="{Binding}" />
            </local:RefreshableActionMessage>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>
</code>```

Just the code which is responsible to re-execute the guard method is missing, but we can add it in the Configure method in the Bootstrapper class:

```<code>protected override void Configure()
{
    ActionMessage.InvokeAction = delegate(ActionExecutionContext context)
    {
        RefreshableActionMessage refreshableActionMessage;

        object[] parameters = MessageBinder.DetermineParameters(context, context.Method.GetParameters());
        object obj = context.Method.Invoke(context.Target, parameters);
        Task task = obj as Task;
        if (task != null)
        {
            obj = task.AsResult();
        }
        IResult result = obj as IResult;
        if (result != null)
        {
            obj = new IResult[]
            {
                result
            };
        }
        IEnumerable<IResult> enumerable = obj as IEnumerable<IResult>;
        if (enumerable != null)
        {
            obj = enumerable.GetEnumerator();
        }
        IEnumerator<IResult> enumerator = obj as IEnumerator<IResult>;
        if (enumerator != null)
        {
            Coroutine.BeginExecute(enumerator, new CoroutineExecutionContext
            {
                Source = context.Source,
                View = context.View,
                Target = context.Target
            }, null);
        }

        refreshableActionMessage = context.Message as RefreshableActionMessage;
        if (refreshableActionMessage != null && refreshableActionMessage.RefreshAfterInvoke)
        {
            refreshableActionMessage.UpdateAvailability();
        }
    };
}
</code>```

As you can see, if the custom ActionMessage requires a refresh, it is performed by calling the UpdateAvailability method.

I hope this solution can help you.

Body:
I have a property BindableCollection<Cat> { get; private set; } with a number of Cat objects that is bound to an ItemsControl in my WPF XAML.

I then have the following code that is attached to a button inside this ItemsControl.

XAML snippet

<Button Content="Pat Cat" cal:Message.Attach="PatCat($dataContext)" />

In the ViewModel...

BindableCollection<Cat> { get; private set; }

public bool CanPatCat(Cat cat)
{
   return cat.Pattable && cat.Alive;
}

public void PatCat(Cat cat)
{
    // pat the cat
    cat.Alive = false;
}

Given this is a method guard and not a property, how do I notify the UI so that the CanPat method is evaluated for each Cat in the BindableCollection given the guard method will now return false once the Cat has been pat?

Body:
While for properties a specific and sophisticated UI awareness mechanism exists (I am talking about Binding), for methods the situation is completely different.
Using events in this context in my humble opinion is not suitable, so I thought a solution which is based on extending Caliburn Micro framework.

First of all we need to create a specific ActionMessage which is meant for re-executing the guard method after its invocation. I called it RefreshableActionMessage.

public class RefreshableActionMessage : ActionMessage
{
    private bool refreshAfterInvoke = true;

    public bool RefreshAfterInvoke
    {
        get { return refreshAfterInvoke; }
        set { refreshAfterInvoke = value; }
    }
}

Now we have to use it in our "guarded" button (yes, we need to use the verbose syntax):

<Button Content="Pat Cat">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:RefreshableActionMessage MethodName="PatCat">
                <cal:Parameter Value="{Binding}" />
            </local:RefreshableActionMessage>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

Just the code which is responsible to re-execute the guard method is missing, but we can add it in the Configure method in the Bootstrapper class:

protected override void Configure()
{
    ActionMessage.InvokeAction = delegate(ActionExecutionContext context)
    {
        RefreshableActionMessage refreshableActionMessage;

        object[] parameters = MessageBinder.DetermineParameters(context, context.Method.GetParameters());
        object obj = context.Method.Invoke(context.Target, parameters);
        Task task = obj as Task;
        if (task != null)
        {
            obj = task.AsResult();
        }
        IResult result = obj as IResult;
        if (result != null)
        {
            obj = new IResult[]
            {
                result
            };
        }
        IEnumerable<IResult> enumerable = obj as IEnumerable<IResult>;
        if (enumerable != null)
        {
            obj = enumerable.GetEnumerator();
        }
        IEnumerator<IResult> enumerator = obj as IEnumerator<IResult>;
        if (enumerator != null)
        {
            Coroutine.BeginExecute(enumerator, new CoroutineExecutionContext
            {
                Source = context.Source,
                View = context.View,
                Target = context.Target
            }, null);
        }

        refreshableActionMessage = context.Message as RefreshableActionMessage;
        if (refreshableActionMessage != null && refreshableActionMessage.RefreshAfterInvoke)
        {
            refreshableActionMessage.UpdateAvailability();
        }
    };
}

As you can see, if the custom ActionMessage requires a refresh, it is performed by calling the UpdateAvailability method.

I hope this solution can help you.


来源: stackexchange

问:
cellclick event doesn't work when rendering html table
I have a grid panel and I'm using renderer for certain column.., I also use cellclick for handling click.

In renderer config, I return html table to place the value of a cell (I have some values in a cell).

The problem is, when I click the cell that has renderer returning html table, the cellclick event doesn't work otherwise it works.

How could this happen?

Here is my code :

```<code>    // Variable For HTML Code
    var renderFerrous = '<table style="text-align: left; width: 140px;" border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse">'+
                            '<tbody>'+
                            '<tr>'+
                                '<td style="text-align: center; width: 50px;">Rating</td>'+
                                '<td style="text-align: center; width: 50px;">Colour</td>'+
                                '<td style="text-align: center; width: 50px;">Ferrous</td>'+
                            '</tr>'+
                            '<tr>'+
                                '<td style="text-align: center; width: 50px;">val1</td>'+
                                '<td style="text-align: center; width: 50px;">val2</td>'+
                                '<td style="text-align: center; width: 50px;">val3</td>'+
                            '</tr>'+
                        ' </tbody>'+
                        '</table>';

ewhid.cpt.grid = Ext.extend(Ext.grid.GridPanel, {
    constructor: function (config) {
        config = config || {};
        config.id = config.id || 'cpt_grid';
        config.height = config.height || 300;
        config.width = config.width || 900;
        config.border = config.border || true;
        config.frame = config.frame || true;
        config.deferredRender = true;
        config.stripeRows = true;
        config.loadMask = true;
        config.ds = this.store_grid;
        config.ds = new newhid.cpt.store();
        config.sm = new Ext.grid.RowSelectionModel({
            singleSelect: true,
            listeners: {
                rowselect: function (smObj, rowIndex, record) {
                    selRecordStore = record;
                    record1 = record;
                }
            }
        }),

        // MY CELLCLICK HANDLER
        config.listeners = {
            cellclick: function(grid, rowIndex, colIndex, e) {
                colIndex1 = colIndex;
                el = e.getTarget();
                record = grid.getStore().getAt(rowIndex).data;
                record2 = grid.getStore().getAt(rowIndex);

                var fieldName = grid.getColumnModel().getDataIndex(colIndex); // Get field name
                var data = record2.get(fieldName); // get data in a cell

                console.log(fieldName);
                console.log(record2.get(fieldName));

                if (grid.manage_cell != undefined && grid.manage_cell.isVisible()) {
                    grid.manage_cell.hide();
                    grid.manage_cell.destroy(this.items);
                    return false;
                }
                if(colIndex == 8 || colIndex == 9){
                    if(record.idrecordingtype == 0 || !record.idrecordingtype){
                        grid.manage_cell = new manage_cell({
                            items: new newhid.cpt.formValue({
                                record : record2.get(fieldName)
                            })
                        });
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }

                    else if(record.idrecordingtype == 3){
                        grid.manage_cell = new manage_cell({
                            // items: new newhid.cpt.formIso()
                            items: new newhid.cpt.formIso2()
                        });
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }
                    else if(record.idrecordingtype == 4){
                        grid.manage_cell = new manage_cell({
                            items:  new newhid.cpt.formFerrous()
                        });
                        var val = record2.get(fieldName);
                        var trim = val.replace(/\s*\/\s*/g,"/");
                        var val2 = trim.split("/");

                        Ext.getCmp('id_rating').setValue(val2[0]);
                        Ext.getCmp('colour').setValue(val2[1]);
                        Ext.getCmp('id_ferrous').items.get(0).setValue(val2[2]);

                        var val = record2.get(fieldName);
                        var val2 = str.split("/");

                        var idrating = Ext.getCmp('id_rating');
                        idrating.store.removeAll();
                        idrating.store.load({
                            params: {
                                'idrating_type' : record.idrating_type,
                                'idsite': Ext.getCmp('site_id').getValue(),
                                'idfleet': Ext.getCmp('fleet_id').getValue()
                            }
                        })

                        var colour = Ext.getCmp('colour');
                        colour.store.removeAll();
                        colour.store.load()

                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }

                    else if(record.idrecordingtype == 5){
                        grid.manage_cell = new manage_cell({
                            items: new newhid.cpt.formFluid()
                        });

                        var val = record2.get(fieldName);
                        var trim = val.replace(/\s*\/\s*/g,"/");
                        var val2 = trim.split("/");
                        console.log(trim);
                        Ext.getCmp('id_qty').setValue(val2[1]);
                        Ext.getCmp('id_unit_value').setValue(val2[2]);
                        Ext.getCmp('id_fluid').items.get(0).setValue(val2[0]);

                        var idunit = Ext.getCmp('id_unit_value');
                        idunit.store.removeAll();
                        idunit.store.load({
                            params: {
                                'idunit': record.idunit
                            }
                        })
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }

                }
                else if(colIndex == 10){
                    if(record.idrecordingtype == 0 || !record.idrecordingtype){
                        // console.log(formunit.items.items);
                        grid.manage_cell = new manage_cell({
                            items: new newhid.cpt.formUnit()
                        });
                        var valCmbUnit = record2.get(fieldName);
                        var idunit = Ext.getCmp('id_unit_value');
                        idunit.store.removeAll();
                        idunit.store.load({
                            params: {
                                'idunit': record.idunit
                            }
                        });
                        (valCmbUnit ? Ext.getCmp('id_unit_value').setValue(valCmbUnit): false);
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }
                    else if(record.idrecordingtype == 4){
                        return false;
                    }
                    else if(record.idrecordingtype == 5){
                        return false;
                    }
                }
            }
        }

        // Group Grid
      config.columns = [
        {
            header: 'Ord.',
            width: 40,
            align: 'center',
            sortable: true,
            dataIndex: 'orders',
            menuDisabled: true
        },
        {
            header: "Sub.",
            width: 40,
            align: 'center',
            sortable: true,
            dataIndex: 'suborder'

        },
        {
            header: "CC",
            width: 50,
            align: 'center',
            sortable: true,
            dataIndex: 'idcomponent'

        },
        {
            header: "Mod",
            width: 50,
            align: 'center',
            sortable: true,
            dataIndex: 'idmodifier'

        },
        {
            header: "Condition",
            width: 80,
            align: 'center',
            sortable: true,
            dataIndex: 'conditions'
        },
        {
            header: "Rec.Parameter",
            width: 100,
            align: 'center',
            sortable: true,
            dataIndex: 'idrecordparameter',

        },
        {
            header: "Spesification",
            width: 100,
            align: 'center',
            sortable: true,
            dataIndex: 'specification',

        },
        {
            header: "M",
            width: 40,
            align: 'center',
            sortable: true,
            dataIndex: 'mandatory',

        },
        {
            header: "Actual Reading",
            width: 220,
            align: 'center',
            sortable: true,
            dataIndex: 'act_reading',
            renderer: function(val, meta, rec){

                if(val == ""){
                    meta.attr = 'style="color: red; cursor:pointer;"';
                    return 'Manage';
                }
                else{
                    return "<center>"+renderFerrous+"</center>";
                }
            }

        },
        {
            header: "Adjusted Reading",
            width: 220,
            align: 'center',
            sortable: true,
            dataIndex: 'adj_reading',
            renderer: function(val, meta, rec){
                if(val == ""){
                    meta.attr = 'style="color: red; cursor:pointer;"';
                    return 'Manage';
                }
                else{
                    return val;
                }
            }

        },
        {
            header: "Unit",
            width: 80,
            align: 'center',
            sortable: true,
            dataIndex: 'unit',
            renderer: function(val, meta, rec){
                if(rec.data.idrecordingtype == 4 || rec.data.idrecordingtype == 5 || rec.data.idrecordingtype == 3){
                    str = '';
                    return str;
                }
                else if(val == ""){
                    meta.attr = 'style="color: red; cursor:pointer;"';
                    return 'Manage';
                }
                else{
                    return val;
                }
            }

        },
        {
            header: "Coment",
            width: 80,
            align: 'center',
            sortable: true,
            dataIndex: 'comments'
        },
        {
            header : 'idcpt_template',
            hidden: true,
            dataIndex: 'idcpt_template'
        },
        {
            header: 'idrecordingtype',
            hidden: true,
            dataIndex: 'idrecordingtype'
        },
        {
            header: 'idunit',
            hidden: true,
            dataIndex: 'idunit'
        },
        {
            header: 'idrating_type',
            hidden: true,
            dataIndex: 'idrating_type'
        }
    ];
        newhid.cpt.grid.superclass.constructor.call(this, config);
    }
});
</code>```

Can somebody help me please?

Thanks in Advance..

答:
As I recall, Ext makes some assumptions when determining which cell is clicked. One assumption it makes is that the only tables in a grid are rendered by the grid. In other words, by using a table in your renderer, you are confusing the code that generates the click event. Luckily, you can get the same effect without a table.

Try something like this for your template:

```<code>  <div>
    <span>Rating</span>
    <span>Color</span>
    <span>Ferrous</span>
  </div>
  <div>
    <span>val1</span>
    <span>val2</span>
    <span>val3</span>
  </div>
</code>```

Add this css to your page

```<code>  .table-ish {
    width: 156px;

    border: 1px solid black;
    overflow: auto;

  }

  .table-ish div span {
    float: left;
    width: 50px;
    text-align: center;
    border: 1px solid black;
  }
</code>```

Change your column definition to inclode:

```<code>css: 'table-ish',
</code>```

Caveat: I don't have Ext working on this computer, so some of this is conjecture, but you've been waiting for a while now so I figured I'd at least post this.

ContentLicense: CC BY-SA 2.5

Body:
I have a grid panel and I'm using renderer for certain column.., I also use cellclick for handling click.

In renderer config, I return html table to place the value of a cell (I have some values in a cell).

The problem is, when I click the cell that has renderer returning html table, the cellclick event doesn't work otherwise it works.

How could this happen?

Here is my code :

    // Variable For HTML Code
    var renderFerrous = '
'+
                            '
'+
                            '
'+
                                'Rating	'+
                                'Colour	'+
                                'Ferrous	'+
                            '
'+
                            '
'+
                                'val1	'+
                                'val2	'+
                                'val3	'+
                            '
'+
                        '
'+
                        '
';

ewhid.cpt.grid = Ext.extend(Ext.grid.GridPanel, {
    constructor: function (config) {
        config = config || {};
        config.id = config.id || 'cpt_grid';
        config.height = config.height || 300;
        config.width = config.width || 900;
        config.border = config.border || true;
        config.frame = config.frame || true;
        config.deferredRender = true;
        config.stripeRows = true;
        config.loadMask = true;
        config.ds = this.store_grid;
        config.ds = new newhid.cpt.store();
        config.sm = new Ext.grid.RowSelectionModel({
            singleSelect: true,
            listeners: {
                rowselect: function (smObj, rowIndex, record) {
                    selRecordStore = record;
                    record1 = record;
                }
            }
        }),

        // MY CELLCLICK HANDLER
        config.listeners = {
            cellclick: function(grid, rowIndex, colIndex, e) {
                colIndex1 = colIndex;
                el = e.getTarget();
                record = grid.getStore().getAt(rowIndex).data;
                record2 = grid.getStore().getAt(rowIndex);

                var fieldName = grid.getColumnModel().getDataIndex(colIndex); // Get field name
                var data = record2.get(fieldName); // get data in a cell

                console.log(fieldName);
                console.log(record2.get(fieldName));

                if (grid.manage_cell != undefined && grid.manage_cell.isVisible()) {
                    grid.manage_cell.hide();
                    grid.manage_cell.destroy(this.items);
                    return false;
                }
                if(colIndex == 8 || colIndex == 9){
                    if(record.idrecordingtype == 0 || !record.idrecordingtype){
                        grid.manage_cell = new manage_cell({
                            items: new newhid.cpt.formValue({
                                record : record2.get(fieldName)
                            })
                        });
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }

                    else if(record.idrecordingtype == 3){
                        grid.manage_cell = new manage_cell({
                            // items: new newhid.cpt.formIso()
                            items: new newhid.cpt.formIso2()
                        });
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }
                    else if(record.idrecordingtype == 4){
                        grid.manage_cell = new manage_cell({
                            items:  new newhid.cpt.formFerrous()
                        });
                        var val = record2.get(fieldName);
                        var trim = val.replace(/\s*\/\s*/g,"/");
                        var val2 = trim.split("/");

                        Ext.getCmp('id_rating').setValue(val2[0]);
                        Ext.getCmp('colour').setValue(val2[1]);
                        Ext.getCmp('id_ferrous').items.get(0).setValue(val2[2]);

                        var val = record2.get(fieldName);
                        var val2 = str.split("/");

                        var idrating = Ext.getCmp('id_rating');
                        idrating.store.removeAll();
                        idrating.store.load({
                            params: {
                                'idrating_type' : record.idrating_type,
                                'idsite': Ext.getCmp('site_id').getValue(),
                                'idfleet': Ext.getCmp('fleet_id').getValue()
                            }
                        })

                        var colour = Ext.getCmp('colour');
                        colour.store.removeAll();
                        colour.store.load()

                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }

                    else if(record.idrecordingtype == 5){
                        grid.manage_cell = new manage_cell({
                            items: new newhid.cpt.formFluid()
                        });

                        var val = record2.get(fieldName);
                        var trim = val.replace(/\s*\/\s*/g,"/");
                        var val2 = trim.split("/");
                        console.log(trim);
                        Ext.getCmp('id_qty').setValue(val2[1]);
                        Ext.getCmp('id_unit_value').setValue(val2[2]);
                        Ext.getCmp('id_fluid').items.get(0).setValue(val2[0]);

                        var idunit = Ext.getCmp('id_unit_value');
                        idunit.store.removeAll();
                        idunit.store.load({
                            params: {
                                'idunit': record.idunit
                            }
                        })
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }

                }
                else if(colIndex == 10){
                    if(record.idrecordingtype == 0 || !record.idrecordingtype){
                        // console.log(formunit.items.items);
                        grid.manage_cell = new manage_cell({
                            items: new newhid.cpt.formUnit()
                        });
                        var valCmbUnit = record2.get(fieldName);
                        var idunit = Ext.getCmp('id_unit_value');
                        idunit.store.removeAll();
                        idunit.store.load({
                            params: {
                                'idunit': record.idunit
                            }
                        });
                        (valCmbUnit ? Ext.getCmp('id_unit_value').setValue(valCmbUnit): false);
                        grid.manage_cell.show();
                        grid.manage_cell.getEl().alignTo(el, 'bl');
                    }
                    else if(record.idrecordingtype == 4){
                        return false;
                    }
                    else if(record.idrecordingtype == 5){
                        return false;
                    }
                }
            }
        }

        // Group Grid
      config.columns = [
        {
            header: 'Ord.',
            width: 40,
            align: 'center',
            sortable: true,
            dataIndex: 'orders',
            menuDisabled: true
        },
        {
            header: "Sub.",
            width: 40,
            align: 'center',
            sortable: true,
            dataIndex: 'suborder'

        },
        {
            header: "CC",
            width: 50,
            align: 'center',
            sortable: true,
            dataIndex: 'idcomponent'

        },
        {
            header: "Mod",
            width: 50,
            align: 'center',
            sortable: true,
            dataIndex: 'idmodifier'

        },
        {
            header: "Condition",
            width: 80,
            align: 'center',
            sortable: true,
            dataIndex: 'conditions'
        },
        {
            header: "Rec.Parameter",
            width: 100,
            align: 'center',
            sortable: true,
            dataIndex: 'idrecordparameter',

        },
        {
            header: "Spesification",
            width: 100,
            align: 'center',
            sortable: true,
            dataIndex: 'specification',

        },
        {
            header: "M",
            width: 40,
            align: 'center',
            sortable: true,
            dataIndex: 'mandatory',

        },
        {
            header: "Actual Reading",
            width: 220,
            align: 'center',
            sortable: true,
            dataIndex: 'act_reading',
            renderer: function(val, meta, rec){

                if(val == ""){
                    meta.attr = 'style="color: red; cursor:pointer;"';
                    return 'Manage';
                }
                else{
                    return ""+renderFerrous+"";
                }
            }

        },
        {
            header: "Adjusted Reading",
            width: 220,
            align: 'center',
            sortable: true,
            dataIndex: 'adj_reading',
            renderer: function(val, meta, rec){
                if(val == ""){
                    meta.attr = 'style="color: red; cursor:pointer;"';
                    return 'Manage';
                }
                else{
                    return val;
                }
            }

        },
        {
            header: "Unit",
            width: 80,
            align: 'center',
            sortable: true,
            dataIndex: 'unit',
            renderer: function(val, meta, rec){
                if(rec.data.idrecordingtype == 4 || rec.data.idrecordingtype == 5 || rec.data.idrecordingtype == 3){
                    str = '';
                    return str;
                }
                else if(val == ""){
                    meta.attr = 'style="color: red; cursor:pointer;"';
                    return 'Manage';
                }
                else{
                    return val;
                }
            }

        },
        {
            header: "Coment",
            width: 80,
            align: 'center',
            sortable: true,
            dataIndex: 'comments'
        },
        {
            header : 'idcpt_template',
            hidden: true,
            dataIndex: 'idcpt_template'
        },
        {
            header: 'idrecordingtype',
            hidden: true,
            dataIndex: 'idrecordingtype'
        },
        {
            header: 'idunit',
            hidden: true,
            dataIndex: 'idunit'
        },
        {
            header: 'idrating_type',
            hidden: true,
            dataIndex: 'idrating_type'
        }
    ];
        newhid.cpt.grid.superclass.constructor.call(this, config);
    }
});

Can somebody help me please?

Thanks in Advance..

Body:
As I recall, Ext makes some assumptions when determining which cell is clicked. One assumption it makes is that the only tables in a grid are rendered by the grid. In other words, by using a table in your renderer, you are confusing the code that generates the click event. Luckily, you can get the same effect without a table.

Try something like this for your template:

  <div>
    <span>Rating</span>
    <span>Color</span>
    <span>Ferrous</span>
  </div>
  <div>
    <span>val1</span>
    <span>val2</span>
    <span>val3</span>
  </div>

Add this css to your page

  .table-ish {
    width: 156px;

    border: 1px solid black;
    overflow: auto;

  }

  .table-ish div span {
    float: left;
    width: 50px;
    text-align: center;
    border: 1px solid black;
  }

Change your column definition to inclode:

css: 'table-ish',

Caveat: I don't have Ext working on this computer, so some of this is conjecture, but you've been waiting for a while now so I figured I'd at least post this.


问:
How to make a function call only once in Swift 3.1?
I have a class that looks a little like:

```<code>final class Token {

..........

public enum Result {

    case Success()
    case Failure(Error)

}

private var successClosure : (() -> Void)?
private var failureClosure : ((Error) -> Void)?

public func completed(withResult result: Token.Result) {

    switch result {
       case .Success: successClosure?()
       case .Failure(let error): failureClosure?(error)
    }

}

..........

}
</code>```

I would like to enforce the ability to call completed(withResult:) only once.

Is there a method of converting the above completed(withResult:) method to one that is compatible with Swift 3.1?

答:
You can declare a boolean variable which changes to false when the function was called once.

```<code>fileprivate var firstCompletionTime = true

public func completed(withResult result: Token.Result) {
    guard firstCompletionTime else {
        return
    }

    switch result {
       case .Success: successClosure?()
       case .Failure(let error): failureClosure?(error)
    }

    firstCompletionTime = false
}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have a class that looks a little like:

final class Token {

..........

public enum Result {

    case Success()
    case Failure(Error)

}

private var successClosure : (() -> Void)?
private var failureClosure : ((Error) -> Void)?

public func completed(withResult result: Token.Result) {

    switch result {
       case .Success: successClosure?()
       case .Failure(let error): failureClosure?(error)
    }

}

..........

}

I would like to enforce the ability to call completed(withResult:) only once.

Is there a method of converting the above completed(withResult:) method to one that is compatible with Swift 3.1?

Body:
You can declare a boolean variable which changes to false when the function was called once.

fileprivate var firstCompletionTime = true

public func completed(withResult result: Token.Result) {
    guard firstCompletionTime else {
        return
    }

    switch result {
       case .Success: successClosure?()
       case .Failure(let error): failureClosure?(error)
    }

    firstCompletionTime = false
}


答:
```<code>def valid(v):
    try:
        value = int(v)
        return 10000000 <= value <= 99999999
    except:
        return False

output = [x for x in list if valid(x)]
</code>```

Explanation:

Filter all values in the list using the valid function as your criteria.

Title: Extract 8-digit numbers from a list of strings

Body:
I have a list of strings which may contain letters, symbols, digits, etc, as below:

list = ['\n', '', '0', '38059', '', '', '?_', '71229366', '', '1', '38059', '', '', '?_', '87640804', '', '2', '38059', '', '', '?_', '71758011', '', '', ':?', ';__', '71229366287640804271758011287169822']

How do I filter out all other strings, except numbers less than 10000000 and greater than 99999999?

Expected Output:

list = ['71229366', '87640804', '71758011']

Body:
def valid(v):
    try:
        value = int(v)
        return 10000000 <= value <= 99999999
    except:
        return False

output = [x for x in list if valid(x)]

Explanation:

Filter all values in the list using the valid function as your criteria.


Body:
data = ['\n', '', '0', '38059', '', '', '?_', '71229366', '', '1', '38059',
        '', '', '?_', '87640804', '', '2', '38059', '', '', '?_', '71758011',
        '', '', ':?', ';__', '71229366287640804271758011287169822']

res = []
for e in data:
    try:
        number = int(e)
    except ValueError:
        continue
    if 10000000  < number < 99999999:
        res.append(str(number))

print(res)

print(res)

Output:

 ['71229366', '87640804', '71758011']


问:
Changing the overall color of different panels using another jFrame
So i am working on a software and I have reached a particular point where in the settings window (separate jFrame from the main), I should be able to change the color of two different panels using a ComboBox(called Color_cb1).
I have used a switch statement to get the selected index and change colors in the other form like so:[the screenshot of the entire code is given here -> Screenshot:

But it just doesn't seem to change anything! Can someone help out here?

答:
I see your problem, it's here:

```<code>Chatroom c = new Chatroom();
</code>```

You then call methods to try to change the state of this object, c.xxx.someMethod(); and your methods in fact work, they do change the state of c, but please understand that your changing the wrong object. Your Chatroom object, c, is not the same as the Chatroom that is actually displayed, and changing the state of c will have no magical effect on the displayed object. To visualize, imagine that your wife has a car, and it needs gas. Your above solution is similar to your buying a new car of the exact same make, model and year, then filling it with gas, and expecting that now your wife's car has gas. Doesn't work. Instead you need to get a hold of your wife's car, fill it with gas, and now things are good.

One possible solution is to make the state fields static, and this is a bad solution since it causes the class to lose OOP benefits, to make it tougher to debug, to increase potential complexity and increase the risk of bugs.

A better solution is to pass a reference to the visualized Chatroom object into this class, and call your methods on it. Pass the reference in via a constructor or setter parameter, and you'll be able to use it.

For an example of a MCVE that shows use of a JDialog as well as passing a reference of one object into another via a constructor parameter, note the program below. In this program, I have two JPanels, a MainPanel and a DialogPanel, one the main JPanel for the application, the other the JPanel that his held by the JDialog, and when I create the JDialog, I pass the main panel into like so:

```<code>class MainPanel extends JPanel {
    // ....

    // create the dialog, passing the main panel into it:
    private DialogPanel dialogPanel = new DialogPanel(this);
</code>```

Then within the DialogPanel's constructor, I set a field with the parameter:

```<code>@SuppressWarnings("serial")
class DialogPanel extends JPanel {
    private MainPanel mainPanel;
    // ....

    public DialogPanel(MainPanel mainPanel) {
        this.mainPanel = mainPanel;
</code>```

and then use this mainPanel field within an ActionListener held by the dialog panel:

```<code>public void actionPerformed(ActionEvent e) {
    ColorPair colorPair = (ColorPair) colorCombo.getSelectedItem();
    mainPanel.setCenterBackground(colorPair.getColor());
    mainPanel.setSideBackground(colorPair.getDarkColor());
}
</code>```

Also, since you're working with Color pairs, I created an enum called ColorPair that ties the two colors together with a String:

```<code>public enum ColorPair {
    BLUE("Blue", new Color(52, 73, 94), new Color(44, 62, 80)),
    GREEN("Green", new Color(46, 204, 113), new Color(39, 174, 96)),
    TURQ("Turquoise", new Color(26, 188, 156), new Color(22, 160, 133)),
    GREY("Grey", new Color(149, 165, 166), new Color(127, 140, 141));

    private ColorPair(String text, Color color1, Color color2) {
        this.text = text;
        this.color = color1;
        this.darkColor = color2;
    }

    private String text;
    private Color color;
    private Color darkColor;

    public String getText() {
        return text;
    }
    public Color getColor() {
        return color;
    }
    public Color getDarkColor() {
        return darkColor;
    }
}
</code>```

Why do this? Well it helps us create a nifty effect where we render the two colors plus the text in the JComboBox that lets us select colors by using a custom ListCellRenderer class:

```<code>public class ColorPairRenderer implements ListCellRenderer<ColorPair> {
    private static final int IMG_W = 100;
    private static final int IMG_H = 20;
    private JLabel label = new JLabel();
    private Map<ColorPair, Icon> iconMap = new EnumMap<>(ColorPair.class);

    public ColorPairRenderer() {
        label.setOpaque(true);
        label.setHorizontalTextPosition(SwingConstants.TRAILING);
        label.setVerticalTextPosition(SwingConstants.CENTER);
        for (ColorPair colorPair : ColorPair.values()) {
            BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            int x = 0;
            int y = 0;
            int width = IMG_W / 2;
            int height = IMG_H;
            g.setColor(colorPair.getColor());
            g.fillRect(x, y, width, height);

            x = width;
            g.setColor(colorPair.getDarkColor());
            g.fillRect(x, y, width, height);

            x = 0;
            width = IMG_W;
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);
            g.dispose();
            Icon icon = new ImageIcon(img);
            iconMap.put(colorPair, icon);
        }
    }

    @Override
    public Component getListCellRendererComponent(JList<? extends ColorPair> list, ColorPair value, int index,
            boolean isSelected, boolean cellHasFocus) {
        if (value != null) {
            label.setText(value.getText());
            label.setIcon(iconMap.get(value));
        } else {
            label.setText("");
            label.setIcon(null);
        }
        return label;
    }
}
</code>```

To see the whole thing in action, copy and paste the code below into your IDE into class file called ChangeColor.java, and run it (updated to show how easy it is to add new colors -- one line of code):

```<code>import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;

public class ChangeColor {
    private static void createAndShowGui() {
        MainPanel mainPanel = new MainPanel();

        JFrame frame = new JFrame("Change Color");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

@SuppressWarnings("serial")
class MainPanel extends JPanel {
    private JPanel centerPanel = new JPanel();
    private JPanel sidePanel = new JPanel();

    // create the dialog, passing the main panel into it:
    private DialogPanel dialogPanel = new DialogPanel(this);
    private JDialog dialog;

    public MainPanel() {
        centerPanel.setPreferredSize(new Dimension(400, 400));
        sidePanel.setPreferredSize(new Dimension(100, 400));
        setLayout(new BorderLayout());
        add(centerPanel, BorderLayout.CENTER);
        add(sidePanel, BorderLayout.LINE_END);

        centerPanel.add(new JButton(new ShowColorDialogAction("Change Colors")));
    }

    public void setCenterBackground(Color c) {
        centerPanel.setBackground(c);
    }

    public void setSideBackground(Color c) {
        sidePanel.setBackground(c);
    }

    private class ShowColorDialogAction extends AbstractAction {
        public ShowColorDialogAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (dialog == null) {
                Window frame = SwingUtilities.getWindowAncestor(MainPanel.this);
                dialog = new JDialog(frame, "Color Setter", ModalityType.MODELESS);
                dialog.getContentPane().add(dialogPanel);
                dialog.pack();
                dialog.setLocationByPlatform(true);
            }
            dialog.setVisible(true);
        }
    }
}

@SuppressWarnings("serial")
class DialogPanel extends JPanel {
    private MainPanel mainPanel;
    private JComboBox<ColorPair> colorCombo = new JComboBox<>(ColorPair.values());

    public DialogPanel(MainPanel mainPanel) {
        this.mainPanel = mainPanel;
        colorCombo.setSelectedIndex(-1);
        colorCombo.setRenderer(new ColorPairRenderer());
        colorCombo.addActionListener(new ColorComboListener());
        add(colorCombo);
    }

    private class ColorComboListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            ColorPair colorPair = (ColorPair) colorCombo.getSelectedItem();
            mainPanel.setCenterBackground(colorPair.getColor());
            mainPanel.setSideBackground(colorPair.getDarkColor());
        }
    }
}

class ColorPairRenderer implements ListCellRenderer<ColorPair> {
    private static final int IMG_W = 100;
    private static final int IMG_H = 20;
    private JLabel label = new JLabel();
    private Map<ColorPair, Icon> iconMap = new EnumMap<>(ColorPair.class);

    public ColorPairRenderer() {
        label.setOpaque(true);
        label.setHorizontalTextPosition(SwingConstants.TRAILING);
        label.setVerticalTextPosition(SwingConstants.CENTER);
        for (ColorPair colorPair : ColorPair.values()) {
            BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            int x = 0;
            int y = 0;
            int width = IMG_W / 2;
            int height = IMG_H;
            g.setColor(colorPair.getColor());
            g.fillRect(x, y, width, height);

            x = width;
            g.setColor(colorPair.getDarkColor());
            g.fillRect(x, y, width, height);

            x = 0;
            width = IMG_W;
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);
            g.dispose();
            Icon icon = new ImageIcon(img);
            iconMap.put(colorPair, icon);
        }
    }

    @Override
    public Component getListCellRendererComponent(JList<? extends ColorPair> list, ColorPair value, int index,
            boolean isSelected, boolean cellHasFocus) {
        if (value != null) {
            label.setText(value.getText());
            label.setIcon(iconMap.get(value));
        } else {
            label.setText("");
            label.setIcon(null);
        }

        if (isSelected) {
            label.setBackground(Color.LIGHT_GRAY);
        } else {
            label.setBackground(null);
        }
        return label;
    }
}

enum ColorPair {
    BLUE("Blue", new Color(52, 73, 94), new Color(44, 62, 80)),
    GREEN("Green", new Color(46, 204, 113), new Color(39, 174, 96)),
    TURQ("Turquoise", new Color(26, 188, 156), new Color(22, 160, 133)),
    RED("Red", new Color(204, 46, 113), new Color(174, 39, 96)),
    YELLOW("Yellow", new Color(204, 204, 46), new Color(174, 174, 39)),
    Violet("Violet", new Color(204, 46, 204), new Color(174, 39, 174)),
    GREY("Grey", new Color(149, 165, 166), new Color(127, 140, 141));

    private ColorPair(String text, Color color1, Color color2) {
        this.text = text;
        this.color = color1;
        this.darkColor = color2;
    }

    private String text;
    private Color color;
    private Color darkColor;

    public String getText() {
        return text;
    }
    public Color getColor() {
        return color;
    }
    public Color getDarkColor() {
        return darkColor;
    }
}
</code>```

Body:
I see your problem, it's here:

Chatroom c = new Chatroom();

You then call methods to try to change the state of this object, c.xxx.someMethod(); and your methods in fact work, they do change the state of c, but please understand that your changing the wrong object. Your Chatroom object, c, is not the same as the Chatroom that is actually displayed, and changing the state of c will have no magical effect on the displayed object. To visualize, imagine that your wife has a car, and it needs gas. Your above solution is similar to your buying a new car of the exact same make, model and year, then filling it with gas, and expecting that now your wife's car has gas. Doesn't work. Instead you need to get a hold of your wife's car, fill it with gas, and now things are good.

One possible solution is to make the state fields static, and this is a bad solution since it causes the class to lose OOP benefits, to make it tougher to debug, to increase potential complexity and increase the risk of bugs.

A better solution is to pass a reference to the visualized Chatroom object into this class, and call your methods on it. Pass the reference in via a constructor or setter parameter, and you'll be able to use it.

For an example of a MCVE that shows use of a JDialog as well as passing a reference of one object into another via a constructor parameter, note the program below. In this program, I have two JPanels, a MainPanel and a DialogPanel, one the main JPanel for the application, the other the JPanel that his held by the JDialog, and when I create the JDialog, I pass the main panel into like so:

class MainPanel extends JPanel {
    // ....

    // create the dialog, passing the main panel into it:
    private DialogPanel dialogPanel = new DialogPanel(this);

Then within the DialogPanel's constructor, I set a field with the parameter:

@SuppressWarnings("serial")
class DialogPanel extends JPanel {
    private MainPanel mainPanel;
    // ....

    public DialogPanel(MainPanel mainPanel) {
        this.mainPanel = mainPanel;

and then use this mainPanel field within an ActionListener held by the dialog panel:

public void actionPerformed(ActionEvent e) {
    ColorPair colorPair = (ColorPair) colorCombo.getSelectedItem();
    mainPanel.setCenterBackground(colorPair.getColor());
    mainPanel.setSideBackground(colorPair.getDarkColor());
}

Also, since you're working with Color pairs, I created an enum called ColorPair that ties the two colors together with a String:

public enum ColorPair {
    BLUE("Blue", new Color(52, 73, 94), new Color(44, 62, 80)),
    GREEN("Green", new Color(46, 204, 113), new Color(39, 174, 96)),
    TURQ("Turquoise", new Color(26, 188, 156), new Color(22, 160, 133)),
    GREY("Grey", new Color(149, 165, 166), new Color(127, 140, 141));

    private ColorPair(String text, Color color1, Color color2) {
        this.text = text;
        this.color = color1;
        this.darkColor = color2;
    }

    private String text;
    private Color color;
    private Color darkColor;

    public String getText() {
        return text;
    }
    public Color getColor() {
        return color;
    }
    public Color getDarkColor() {
        return darkColor;
    }
}

Why do this? Well it helps us create a nifty effect where we render the two colors plus the text in the JComboBox that lets us select colors by using a custom ListCellRenderer class:

public class ColorPairRenderer implements ListCellRenderer<ColorPair> {
    private static final int IMG_W = 100;
    private static final int IMG_H = 20;
    private JLabel label = new JLabel();
    private Map<ColorPair, Icon> iconMap = new EnumMap<>(ColorPair.class);

    public ColorPairRenderer() {
        label.setOpaque(true);
        label.setHorizontalTextPosition(SwingConstants.TRAILING);
        label.setVerticalTextPosition(SwingConstants.CENTER);
        for (ColorPair colorPair : ColorPair.values()) {
            BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            int x = 0;
            int y = 0;
            int width = IMG_W / 2;
            int height = IMG_H;
            g.setColor(colorPair.getColor());
            g.fillRect(x, y, width, height);

            x = width;
            g.setColor(colorPair.getDarkColor());
            g.fillRect(x, y, width, height);

            x = 0;
            width = IMG_W;
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);
            g.dispose();
            Icon icon = new ImageIcon(img);
            iconMap.put(colorPair, icon);
        }
    }

    @Override
    public Component getListCellRendererComponent(JList<? extends ColorPair> list, ColorPair value, int index,
            boolean isSelected, boolean cellHasFocus) {
        if (value != null) {
            label.setText(value.getText());
            label.setIcon(iconMap.get(value));
        } else {
            label.setText("");
            label.setIcon(null);
        }
        return label;
    }
}

To see the whole thing in action, copy and paste the code below into your IDE into class file called ChangeColor.java, and run it (updated to show how easy it is to add new colors -- one line of code):

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;

public class ChangeColor {
    private static void createAndShowGui() {
        MainPanel mainPanel = new MainPanel();

        JFrame frame = new JFrame("Change Color");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

@SuppressWarnings("serial")
class MainPanel extends JPanel {
    private JPanel centerPanel = new JPanel();
    private JPanel sidePanel = new JPanel();

    // create the dialog, passing the main panel into it:
    private DialogPanel dialogPanel = new DialogPanel(this);
    private JDialog dialog;

    public MainPanel() {
        centerPanel.setPreferredSize(new Dimension(400, 400));
        sidePanel.setPreferredSize(new Dimension(100, 400));
        setLayout(new BorderLayout());
        add(centerPanel, BorderLayout.CENTER);
        add(sidePanel, BorderLayout.LINE_END);

        centerPanel.add(new JButton(new ShowColorDialogAction("Change Colors")));
    }

    public void setCenterBackground(Color c) {
        centerPanel.setBackground(c);
    }

    public void setSideBackground(Color c) {
        sidePanel.setBackground(c);
    }

    private class ShowColorDialogAction extends AbstractAction {
        public ShowColorDialogAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (dialog == null) {
                Window frame = SwingUtilities.getWindowAncestor(MainPanel.this);
                dialog = new JDialog(frame, "Color Setter", ModalityType.MODELESS);
                dialog.getContentPane().add(dialogPanel);
                dialog.pack();
                dialog.setLocationByPlatform(true);
            }
            dialog.setVisible(true);
        }
    }
}

@SuppressWarnings("serial")
class DialogPanel extends JPanel {
    private MainPanel mainPanel;
    private JComboBox<ColorPair> colorCombo = new JComboBox<>(ColorPair.values());

    public DialogPanel(MainPanel mainPanel) {
        this.mainPanel = mainPanel;
        colorCombo.setSelectedIndex(-1);
        colorCombo.setRenderer(new ColorPairRenderer());
        colorCombo.addActionListener(new ColorComboListener());
        add(colorCombo);
    }

    private class ColorComboListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            ColorPair colorPair = (ColorPair) colorCombo.getSelectedItem();
            mainPanel.setCenterBackground(colorPair.getColor());
            mainPanel.setSideBackground(colorPair.getDarkColor());
        }
    }
}

class ColorPairRenderer implements ListCellRenderer<ColorPair> {
    private static final int IMG_W = 100;
    private static final int IMG_H = 20;
    private JLabel label = new JLabel();
    private Map<ColorPair, Icon> iconMap = new EnumMap<>(ColorPair.class);

    public ColorPairRenderer() {
        label.setOpaque(true);
        label.setHorizontalTextPosition(SwingConstants.TRAILING);
        label.setVerticalTextPosition(SwingConstants.CENTER);
        for (ColorPair colorPair : ColorPair.values()) {
            BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            int x = 0;
            int y = 0;
            int width = IMG_W / 2;
            int height = IMG_H;
            g.setColor(colorPair.getColor());
            g.fillRect(x, y, width, height);

            x = width;
            g.setColor(colorPair.getDarkColor());
            g.fillRect(x, y, width, height);

            x = 0;
            width = IMG_W;
            g.setColor(Color.BLACK);
            g.drawRect(x, y, width, height);
            g.dispose();
            Icon icon = new ImageIcon(img);
            iconMap.put(colorPair, icon);
        }
    }

    @Override
    public Component getListCellRendererComponent(JList<? extends ColorPair> list, ColorPair value, int index,
            boolean isSelected, boolean cellHasFocus) {
        if (value != null) {
            label.setText(value.getText());
            label.setIcon(iconMap.get(value));
        } else {
            label.setText("");
            label.setIcon(null);
        }

        if (isSelected) {
            label.setBackground(Color.LIGHT_GRAY);
        } else {
            label.setBackground(null);
        }
        return label;
    }
}

enum ColorPair {
    BLUE("Blue", new Color(52, 73, 94), new Color(44, 62, 80)),
    GREEN("Green", new Color(46, 204, 113), new Color(39, 174, 96)),
    TURQ("Turquoise", new Color(26, 188, 156), new Color(22, 160, 133)),
    RED("Red", new Color(204, 46, 113), new Color(174, 39, 96)),
    YELLOW("Yellow", new Color(204, 204, 46), new Color(174, 174, 39)),
    Violet("Violet", new Color(204, 46, 204), new Color(174, 39, 174)),
    GREY("Grey", new Color(149, 165, 166), new Color(127, 140, 141));

    private ColorPair(String text, Color color1, Color color2) {
        this.text = text;
        this.color = color1;
        this.darkColor = color2;
    }

    private String text;
    private Color color;
    private Color darkColor;

    public String getText() {
        return text;
    }
    public Color getColor() {
        return color;
    }
    public Color getDarkColor() {
        return darkColor;
    }
}


问:
Tensorflow predictions all come out true
In my tensorflow application, all the predictions are coming out True. I'm trying to adapt the MNIST example to my problem, but I'm worried that it's wrong to use that technique since its for multiple classes, and I have binary classification.

```<code># In[1]:

import tensorflow as tf
import numpy

# In[2]:

X = tf.placeholder(tf.float32, [None, 3], "training-data")
W1 = tf.Variable(tf.truncated_normal([3, 2]), "W")
b1 = tf.Variable(tf.zeros([2]), "B") # number of neurons

W2 = tf.Variable(tf.truncated_normal([2, 1]), "W1")
b2 = tf.Variable(tf.zeros([1]), "B1") # number of neurons

# In[9]:

Y = tf.nn.sigmoid(tf.matmul(X, W1) + b1)
Y1 = tf.nn.softmax(tf.matmul(Y, W2) + b2)
Y_ = tf.placeholder(tf.float32, [None, 1], "labels") # labels

#cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y1)) # error function
cross_entropy = tf.reduce_sum(tf.abs(Y1 - Y_))
is_correct = tf.equal(Y1, Y_)
# All the predictions are coming out True ?!?
accuracy = tf.reduce_sum(tf.cast(is_correct, tf.int32)) / tf.size(is_correct)

print("X", X)
print("Y", Y)
print("Y1", Y1)
print("Y_", Y_)
print("cross-entropy", cross_entropy)
print("is-correct", is_correct)
print("accuracy", accuracy)

# In[10]:

optimizer = tf.train.GradientDescentOptimizer(0.005)
train_step = optimizer.minimize(cross_entropy)

# In[11]:

def load(filename):
    filename_queue = tf.train.string_input_producer([filename])
    key, value = tf.TextLineReader(skip_header_lines=1).read(filename_queue)
    col1, col2, col3, col4, col5 = tf.decode_csv(records = value, record_defaults=[[1.0], [1.0], [1.0], [1.0], [1.0]])
    batch_size=100
    # A tensor for each column of the CSV
    load_time, is_east, is_west, is_europe, labels = tf.train.shuffle_batch([col1, col2, col3, col4, col5], batch_size=batch_size, capacity=batch_size*50, min_after_dequeue=batch_size)
    #features = tf.stack([load_time, is_east, is_west, is_europe], 1)
    features = tf.stack([is_east, is_west, is_europe], 1)
    return features, tf.reshape(labels, [-1, 1])

# In[12]:

features, labels = load("/Users/andrew.ehrlich/Desktop/labelled_clicks.csv")

# In[13]:

# Run!

test_features = numpy.loadtxt(open("/Users/andrew.ehrlich/Desktop/labelled_clicks_test.csv", "rb"), delimiter=",", skiprows=1, usecols = [1,2,3])
test_labels = numpy.loadtxt(open("/Users/andrew.ehrlich/Desktop/labelled_clicks_test.csv", "rb"), delimiter=",", skiprows=1, usecols = [4], ndmin = 2)

summ = tf.reduce_sum(test_labels)
size = tf.size(test_labels)

with tf.Session() as sess:
    file_writer = tf.summary.FileWriter('/Users/andrew.ehrlich/tf.log', sess.graph)
    init = tf.global_variables_initializer()

    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    sess.run(init)
    for i in range(1000):

        ran_features = sess.run(features)
        ran_labels = sess.run(labels)

        train_data = {X: ran_features, Y_: ran_labels}
        sess.run(train_step, feed_dict=train_data) # I guess this updates the tensors behind train_step (W and b)

        if (i % 100 == 0):
            train_acc, train_ent = sess.run([accuracy, cross_entropy], feed_dict=train_data)

            test_data = {X: test_features, Y_: test_labels}
            test_acc, test_ent = sess.run([accuracy, cross_entropy], feed_dict=test_data)

            size = sess.run(tf.size(ran_labels))
            print("batch size: %d [TRAIN - acc:%1.4f ent: %10.4f]    [TEST - acc:%1.4f ent: %10.4f]" % (size, train_acc, train_ent, test_acc, test_ent))

# In[ ]:
</code>```

Output:

```<code>batch size: 100 [TRAIN - acc:0.4100 ent:    59.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5300 ent:    47.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5900 ent:    41.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.4700 ent:    53.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5200 ent:    48.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.6000 ent:    40.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5500 ent:    45.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.6100 ent:    39.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.4100 ent:    59.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5300 ent:    47.0000]    [TEST - acc:0.4787 ent:  9423.0000]
</code>```

Accuracy doesn't change because the values of Y_ are always all True which results in a number that just shows the number of positive labels in the test set. Please let me know any feedback! I'm grateful!

答:
You have a single output and I assume you expect it to be 0 and 1 for false and true. If that is the case, one of the problems is the softmax function. Softmax is good for multiple classes because one of its properties is that it makes the sum of all classes equal to 1 and it becomes easier to interpret the results as probability distributions. In your case, it just ends up setting your single output to 1 because of this property.

There are two basic ways to fix it. Either drop softmax on your output layer and maybe use a different loss function (mean square might work) or make your output layer return two values, keep softmax and interpret the resulting two numbers as a one-hot encoding where the actual values are a measure of confidence of the network.

Body:
In my tensorflow application, all the predictions are coming out True. I'm trying to adapt the MNIST example to my problem, but I'm worried that it's wrong to use that technique since its for multiple classes, and I have binary classification.

# In[1]:

import tensorflow as tf
import numpy

# In[2]:

X = tf.placeholder(tf.float32, [None, 3], "training-data")
W1 = tf.Variable(tf.truncated_normal([3, 2]), "W")
b1 = tf.Variable(tf.zeros([2]), "B") # number of neurons

W2 = tf.Variable(tf.truncated_normal([2, 1]), "W1")
b2 = tf.Variable(tf.zeros([1]), "B1") # number of neurons

# In[9]:

Y = tf.nn.sigmoid(tf.matmul(X, W1) + b1)
Y1 = tf.nn.softmax(tf.matmul(Y, W2) + b2)
Y_ = tf.placeholder(tf.float32, [None, 1], "labels") # labels

#cross_entropy = -tf.reduce_sum(Y_ * tf.log(Y1)) # error function
cross_entropy = tf.reduce_sum(tf.abs(Y1 - Y_))
is_correct = tf.equal(Y1, Y_)
# All the predictions are coming out True ?!?
accuracy = tf.reduce_sum(tf.cast(is_correct, tf.int32)) / tf.size(is_correct)

print("X", X)
print("Y", Y)
print("Y1", Y1)
print("Y_", Y_)
print("cross-entropy", cross_entropy)
print("is-correct", is_correct)
print("accuracy", accuracy)

# In[10]:

optimizer = tf.train.GradientDescentOptimizer(0.005)
train_step = optimizer.minimize(cross_entropy)

# In[11]:

def load(filename):
    filename_queue = tf.train.string_input_producer([filename])
    key, value = tf.TextLineReader(skip_header_lines=1).read(filename_queue)
    col1, col2, col3, col4, col5 = tf.decode_csv(records = value, record_defaults=[[1.0], [1.0], [1.0], [1.0], [1.0]])
    batch_size=100
    # A tensor for each column of the CSV
    load_time, is_east, is_west, is_europe, labels = tf.train.shuffle_batch([col1, col2, col3, col4, col5], batch_size=batch_size, capacity=batch_size*50, min_after_dequeue=batch_size)
    #features = tf.stack([load_time, is_east, is_west, is_europe], 1)
    features = tf.stack([is_east, is_west, is_europe], 1)
    return features, tf.reshape(labels, [-1, 1])

# In[12]:

features, labels = load("/Users/andrew.ehrlich/Desktop/labelled_clicks.csv")

# In[13]:

# Run!

test_features = numpy.loadtxt(open("/Users/andrew.ehrlich/Desktop/labelled_clicks_test.csv", "rb"), delimiter=",", skiprows=1, usecols = [1,2,3])
test_labels = numpy.loadtxt(open("/Users/andrew.ehrlich/Desktop/labelled_clicks_test.csv", "rb"), delimiter=",", skiprows=1, usecols = [4], ndmin = 2)

summ = tf.reduce_sum(test_labels)
size = tf.size(test_labels)

with tf.Session() as sess:
    file_writer = tf.summary.FileWriter('/Users/andrew.ehrlich/tf.log', sess.graph)
    init = tf.global_variables_initializer()

    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    sess.run(init)
    for i in range(1000):

        ran_features = sess.run(features)
        ran_labels = sess.run(labels)

        train_data = {X: ran_features, Y_: ran_labels}
        sess.run(train_step, feed_dict=train_data) # I guess this updates the tensors behind train_step (W and b)

        if (i % 100 == 0):
            train_acc, train_ent = sess.run([accuracy, cross_entropy], feed_dict=train_data)

            test_data = {X: test_features, Y_: test_labels}
            test_acc, test_ent = sess.run([accuracy, cross_entropy], feed_dict=test_data)

            size = sess.run(tf.size(ran_labels))
            print("batch size: %d [TRAIN - acc:%1.4f ent: %10.4f]    [TEST - acc:%1.4f ent: %10.4f]" % (size, train_acc, train_ent, test_acc, test_ent))

# In[ ]:

Output:

batch size: 100 [TRAIN - acc:0.4100 ent:    59.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5300 ent:    47.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5900 ent:    41.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.4700 ent:    53.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5200 ent:    48.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.6000 ent:    40.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5500 ent:    45.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.6100 ent:    39.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.4100 ent:    59.0000]    [TEST - acc:0.4787 ent:  9423.0000]
batch size: 100 [TRAIN - acc:0.5300 ent:    47.0000]    [TEST - acc:0.4787 ent:  9423.0000]

Accuracy doesn't change because the values of Y_ are always all True which results in a number that just shows the number of positive labels in the test set. Please let me know any feedback! I'm grateful!


问:
Sort three numbers in array from least to greatest
I have to create a function that takes 3 numbers. The function should return an array containing the numbers from least to greatest. So far I have this.I know it isn't correct but it's a start.I'm not using native functions as well. Can anyone give me some tips? Appreciate any help.</p>

```<code>   function leastToGreatest (num) {
        var array = [];
        var num1 = 0;
        var num2 = 0;
        var num3 = 0;
        for (var i = 0; i < num.length; i++) {
           if(num[i] < num[i] && num[i] < num[i]) {
                  num[i] = num1;
                  array.push(num1);
           }
           else if(num[i] > num[i] && num[i] < num[i]) {
             num[i] = num2;
             array.push(num2);
           }
           else if(num[i] > num[i] && num[i] > num[i])
             num[i] = num3;
             array.push(num3);
           }
           return array;
     }
     leastToGreatest(2,1,3);
</code>```

答:
Here is a fun little variation on this:

var sortingFunction = function(){
  console.log([].slice.apply(arguments).sort(function(a, b) {  return a - b; }));
}

sortingFunction(3,2,5,1);```
</div>
</div>
</p>

<p>You can pass in as many numbers as you want, not just three. If you want to limit it to three you can test it in the function:</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var sortingFunction = function(){
  var values = [].slice.apply(arguments);
  if(values.length === 3) {
    console.log(values.sort(function(a, b) {  return a - b; }));
  }
  else
  {
    console.log('you didn\'t pass in three values');
  }
 }

sortingFunction(3,2,5,1);

sortingFunction(3,31,1);</code>```

Body:
I have to create a function that takes 3 numbers. The function should return an array containing the numbers from least to greatest. So far I have this.I know it isn't correct but it's a start.I'm not using native functions as well. Can anyone give me some tips? Appreciate any help.

   function leastToGreatest (num) {
        var array = [];
        var num1 = 0;
        var num2 = 0;
        var num3 = 0;
        for (var i = 0; i < num.length; i++) {
           if(num[i] < num[i] && num[i] < num[i]) {
                  num[i] = num1;
                  array.push(num1);
           }
           else if(num[i] > num[i] && num[i] < num[i]) {
             num[i] = num2;
             array.push(num2);
           }
           else if(num[i] > num[i] && num[i] > num[i])
             num[i] = num3;
             array.push(num3);
           }
           return array;
     }
     leastToGreatest(2,1,3);

Body:
Here is a fun little variation on this:

var sortingFunction = function(){
  console.log([].slice.apply(arguments).sort(function(a, b) {  return a - b; }));
}

sortingFunction(3,2,5,1);

You can pass in as many numbers as you want, not just three. If you want to limit it to three you can test it in the function:

var sortingFunction = function(){
  var values = [].slice.apply(arguments);
  if(values.length === 3) {
    console.log(values.sort(function(a, b) {  return a - b; }));
  }
  else
  {
    console.log('you didn\'t pass in three values');
  }
 }

sortingFunction(3,2,5,1);

sortingFunction(3,31,1);


问:
css3 multiple backgrounds - shorthand for gradient and image
Is there a way to use both a gradient & an image with the background shorthand? I have tried: backround: url(image_path) no-repeat top left, gradient -  but this doesn't seem to work.

答:
Loreley: you are doing it right. Here is a demo:

http://jsfiddle.net/ggULM/

The gradient syntax is quite delicate, and if you get anything wrong it will fail entirely. Test just with the gradient, and then add the image later.

A good practice in StackOverflow is sharing the specific piece of code so we are able to pinpoint to the exact source of the problem.


问:
filter between two dates from API with angularjs
i retrieve details of an account from an API statement based on the user ID with the below script

```<code>    $http.post("http://testingserver.net/statement.php",{'id':$scope.account_number}).success
    (function(data){
    console.log(JSON.stringify(data));
$scope.statement=data;
    });
</code>```

From the log i'm able to get the data in detail. The data from the log contains a field called Date which is formatted 2017-02-01T00:00:00Z and what i want to achieve is to let the user select from two date ranges and push back the results to the user.

From the HTML below they are two fields namely sdate and edate

HTML

```<code><form method="post" name="statement" id="statement">
<div class="list">
  <label class="item item-input">
    <span class="input-label">Search From</span>
    <input type="date" ng-model="sdate">
  </label>
  <label class="item item-input">
    <span class="input-label">Search To</span>
    <input type="date" ng-model="edate">
  </label>
</div>
</form>
</br>
<div align="center">
<p><button class="button button-positive" ng-disabled="statement.$invalid" ng-click="state_request()">
  <i class="icon ion-android-search icon"></i> Search
</button></p>
</div>
</code>```

HTML for results

```<code><div ng-repeat="item in statement">
  <table width="100%" border="0" cellspacing="5" cellpadding="5">
    <tr>
      <td width="70%"><div align="left">
        <p><strong> Period</strong>      </p>
      </div></td>
      <td width="82%">{{item.Date |date: 'MMMM yyyy'}}</td>
    </tr>
    <tr>
      <td><p><strong>Category</strong></p></td>
      <td>{{item.Category}}</td>
    </tr>
    <tr>
      <td><div align="left">
        <p><strong>Amount</strong>      </p>
      </div></td>
      <td><div align="left">{{item.Amount}}</div></td>
    </tr>
    <tr>
      <td colspan="2"> </td>
    </tr>
  </table>
</div>
</code>```

答:
We need to make an function for our businees logic and pass the sadte and edate: you can try for this:       </p>

```<code>state_request = function(sdate,edate){
    if(new Date(sadte) < new Date(edate)){
    // now write here the web service logic
    //$http.post('domain/startDate=sadte&endDate=edate'){

    }.then(function(req,res){
    //bind your html variable from here like, res.a,res.b etc
    });
    }
    }
</code>```

Body:
i retrieve details of an account from an API statement based on the user ID with the below script

    $http.post("http://testingserver.net/statement.php",{'id':$scope.account_number}).success
    (function(data){
    console.log(JSON.stringify(data));
$scope.statement=data;
    });

From the log i'm able to get the data in detail. The data from the log contains a field called Date which is formatted 2017-02-01T00:00:00Z and what i want to achieve is to let the user select from two date ranges and push back the results to the user.

From the HTML below they are two fields namely sdate and edate

HTML

<form method="post" name="statement" id="statement">

    Search From
    <input type="date" ng-model="sdate">

    Search To
    <input type="date" ng-model="edate">

</form>

<button class="button button-positive" ng-disabled="statement.$invalid" ng-click="state_request()">
   Search
</button>

HTML for results

 Period

      {{item.Date |date: 'MMMM yyyy'}}

Category

      {{item.Category}}

Amount

{{item.Amount}}

Body:
We need to make an function for our businees logic and pass the sadte and edate: you can try for this:

state_request = function(sdate,edate){
    if(new Date(sadte) < new Date(edate)){
    // now write here the web service logic
    //$http.post('domain/startDate=sadte&endDate=edate'){

    }.then(function(req,res){
    //bind your html variable from here like, res.a,res.b etc
    });
    }
    }


问:
Getting a List from another class
I've been trying to figure out how to make a List from classA accessible for ClassB
I've tried creating an instance/object of the list but it always returns empty when I get the size of the list (while in the main class its not empty).

Example:

ClassA:

```<code>List<String> players = new ArrayList<String>();
</code>```

If i used players.size() here it would return 2 for example

in ClassB I tried the following:

```<code> ClassA classA = new ClassA();
 List<String> newList = classA.players;
</code>```

newList.size() will always return 0 no matter what.

I've also tried using a getter but that doesn't seem to make a difference.

Example:

ClassA:

```<code>List<String> players = new ArrayList<String>();
public List<String> getList(){
    return this.players;
}
</code>```

ClassB:

```<code>ClassA.getList().size()
</code>```

This will also always return 0

How would I properly do this? I tried using a static and that seemed to work but i've been told:

"Static is not the right tool for the job. It's a memory management
  tool, not an access modifier."

He told me:

Instead of static and instead of creating new instances, you can pass
  instances to other classes by adding them as parameters to the
  constructor

However I don't really get what he means. If someone could explain this with an example that would be amazing. Thanks in advance!

Edit: Since a lot of you don't quite get where i want to go with this i'll post my source:
refered to as ClassA in the example

```<code>public class TeamManager {

String prefix = new Messages().prefix;
List<String> players = new ArrayList<String>();
List<String> human = new ArrayList<String>();
List<String> infected = new ArrayList<String>();

void join(Player p){
    if(!players.contains(p.getName())){
        players.add(p.getName());
        teleportToLobby(p);
        for (String temp : players) {
            Bukkit.getPlayer(temp).sendMessage("§e§l"+p.getName()+ " has joined infection. §7("+players.size()+"/16)");
        }
    }else{
        p.sendMessage(prefix + "§cFailed. You are already in the game!");
    }
}
void leave(Player p){
    if(players.contains(p.getName())){
        p.teleport(Bukkit.getWorlds().get(0).getSpawnLocation());
        players.remove(p.getName());
        for (String temp : players) {
            Bukkit.getPlayer(temp).sendMessage("§7§l"+p.getName()+ " has left infection. §7("+players.size()+"/16)");
        }
    }else{
        p.sendMessage(prefix + "§cYou are not in a game!");
    }
}
void addToHumans(String playername){
    human.add(playername);
}
void removeFromHumans(String playername){
    human.remove(playername);
}
void addToInfected(String playername){
    infected.add(playername);
}
void removeFromInfected(String playername){
    infected.remove(playername);
}

void teleportToLobby(Player p){
    Location lobby = getLocFromConfig("lobby");
    if(lobby != null){
        p.teleport(lobby);
        p.sendMessage(prefix + "§aSuccessfully added to game!");
    }else{
        p.sendMessage(prefix + "§cLobby not set! Make sure to set a lobby using /infection setlobby");
    }
}
void startGame(){
    /*if(human.size() >= 4){
    }*/
    for (String temp : players) {
        Bukkit.getPlayer(temp).sendMessage("Game will start shortly!");
    }
}
Location getLocFromConfig(String locationName){
    if(Main.plugin.getConfig().get("lobby") != null){
        double x = Main.plugin.getConfig().getInt(locationName+".x");
        double y = Main.plugin.getConfig().getInt(locationName+".y");
        double z = Main.plugin.getConfig().getInt(locationName+".z");
        World world = Main.plugin.getServer().getWorld(Main.plugin.getConfig().getString(locationName+".world"));
        Location l = new Location(world, x, y, z);
        return l;
    }else{
        Bukkit.getLogger().warning("[Infection] Lobby has not been set!");
        return null;
    }
}
int getPlayersInLobby(){
    return players.size();
}

public List<String> getPlayers(){
    List<String> players = this.players;
    return players;
}
public List<String> getHumans(){
    return human;
}
public List<String> getInfected(){
    return infected;
}
</code>```

}

Events class (referred to in the example as ClassB)

```<code>public class Events implements Listener{

TeamManager teamman = new TeamManager();
List<String> players = teamman.getPlayers();
List<String> humans = teamman.getHumans();
List<String> infected = teamman.getInfected();
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
    //Player p = (Player) e.getPlayer();
    //e.setJoinMessage("["+lvl+"]" + e.getPlayer().getName() +"has joined the game!");
    //p.setDisplayName("[lvl1]"+p.getName());

}
@EventHandler
public void onPlayerDamage(EntityDamageByEntityEvent  e){
    if(e.getEntity() instanceof Player){
        Player p = (Player) e.getEntity();
        Bukkit.getServer().broadcastMessage("Players: "+ players);
        if(players.contains(p.getName())){
            if((p.getHealth() - p.getLastDamage()) < 1){
                for (String temp : players) {
                    Bukkit.getPlayer(temp).sendMessage("§c"+p.getName()+" got infected by "+p.getKiller().getName()+"!");
                }
                e.setCancelled(true);
                 p.setHealth(20);
                 teamman.addToInfected(p.getName());
                 teamman.removeFromHumans(p.getName());
                 p.sendMessage("§cYou have been infected!!");
            }
        }
    }
}
</code>```

}

As said above i want to be able to access the lists from TeamManager and use them in Events. And as explained players is empty in the Events class. I hope this helps.

答:
The simple answer is that you need the same instance of ClassA that you created to be passed into ClassB.

When you create a class, you are created the class definition. Each time you use the new keyword, you create a new instance of that class. You can have as many instances of a class as you want, assuming you've got enough memory. But each instance is separate from all the others.

Just like String and List are classes and need to be instantiated, your custom classes do as well. So in your main, or wherever you're using ClassA and ClassB, you'll want to instantiate them like:

```<code>ClassA instanceOfClassA = new ClassA();
ClassB instanceOfClassB = new ClassB();
</code>```

Let's assume, since you didn't specify, that you did that in your main.

You're objective: Access the list of a specific instance of ClassA from within ClassB.

You've already created the getList() method in ClassA. That's good. You'll use that.

Next, you'll want to create a data member inside ClassB that is of type ClassA, as well as a getter and setter for that member:

```<code>public class ClassB {
    ...
    ClassA myInstanceOfClassA;

    public void setClassAInstance(ClassA instance){
        this.myInstanceOfClassA = instance;
    }
    public ClassA getClassAInstance(){
        return this.myInstanceOfClassA;
    }
}
</code>```

Then, back in your main, after you've updated the players in that instance of ClassA, and after you've instantiated your instance of ClassB like above:

```<code>instanceOfClassB.setClassAInstance(instanceofClassA);
</code>```

Then inside ClassB, the list of players is accessible using that instance.

```<code>List<String> playersFromClassA = myInstanceOfClassA.getList();
</code>```

Likewise, calling myInstanceOfClassA.getList().size(); from inside ClassB should return the appropriate number of players.

Title: Getting a List from another class

Body:
I've been trying to figure out how to make a List from classA accessible for ClassB
I've tried creating an instance/object of the list but it always returns empty when I get the size of the list (while in the main class its not empty).

Example:

ClassA:

List<String> players = new ArrayList<String>();

If i used players.size() here it would return 2 for example

in ClassB I tried the following:

 ClassA classA = new ClassA();
 List<String> newList = classA.players;

newList.size() will always return 0 no matter what.

I've also tried using a getter but that doesn't seem to make a difference.

Example:

ClassA:

List<String> players = new ArrayList<String>();
public List<String> getList(){
    return this.players;
}

ClassB:

ClassA.getList().size()

This will also always return 0

How would I properly do this? I tried using a static and that seemed to work but i've been told:

"Static is not the right tool for the job. It's a memory management
  tool, not an access modifier."

He told me:

Instead of static and instead of creating new instances, you can pass
  instances to other classes by adding them as parameters to the
  constructor

However I don't really get what he means. If someone could explain this with an example that would be amazing. Thanks in advance!

Edit: Since a lot of you don't quite get where i want to go with this i'll post my source:
refered to as ClassA in the example

public class TeamManager {

String prefix = new Messages().prefix;
List<String> players = new ArrayList<String>();
List<String> human = new ArrayList<String>();
List<String> infected = new ArrayList<String>();

void join(Player p){
    if(!players.contains(p.getName())){
        players.add(p.getName());
        teleportToLobby(p);
        for (String temp : players) {
            Bukkit.getPlayer(temp).sendMessage("§e§l"+p.getName()+ " has joined infection. §7("+players.size()+"/16)");
        }
    }else{
        p.sendMessage(prefix + "§cFailed. You are already in the game!");
    }
}
void leave(Player p){
    if(players.contains(p.getName())){
        p.teleport(Bukkit.getWorlds().get(0).getSpawnLocation());
        players.remove(p.getName());
        for (String temp : players) {
            Bukkit.getPlayer(temp).sendMessage("§7§l"+p.getName()+ " has left infection. §7("+players.size()+"/16)");
        }
    }else{
        p.sendMessage(prefix + "§cYou are not in a game!");
    }
}
void addToHumans(String playername){
    human.add(playername);
}
void removeFromHumans(String playername){
    human.remove(playername);
}
void addToInfected(String playername){
    infected.add(playername);
}
void removeFromInfected(String playername){
    infected.remove(playername);
}

void teleportToLobby(Player p){
    Location lobby = getLocFromConfig("lobby");
    if(lobby != null){
        p.teleport(lobby);
        p.sendMessage(prefix + "§aSuccessfully added to game!");
    }else{
        p.sendMessage(prefix + "§cLobby not set! Make sure to set a lobby using /infection setlobby");
    }
}
void startGame(){
    /*if(human.size() >= 4){
    }*/
    for (String temp : players) {
        Bukkit.getPlayer(temp).sendMessage("Game will start shortly!");
    }
}
Location getLocFromConfig(String locationName){
    if(Main.plugin.getConfig().get("lobby") != null){
        double x = Main.plugin.getConfig().getInt(locationName+".x");
        double y = Main.plugin.getConfig().getInt(locationName+".y");
        double z = Main.plugin.getConfig().getInt(locationName+".z");
        World world = Main.plugin.getServer().getWorld(Main.plugin.getConfig().getString(locationName+".world"));
        Location l = new Location(world, x, y, z);
        return l;
    }else{
        Bukkit.getLogger().warning("[Infection] Lobby has not been set!");
        return null;
    }
}
int getPlayersInLobby(){
    return players.size();
}

public List<String> getPlayers(){
    List<String> players = this.players;
    return players;
}
public List<String> getHumans(){
    return human;
}
public List<String> getInfected(){
    return infected;
}

}

Events class (referred to in the example as ClassB)

public class Events implements Listener{

TeamManager teamman = new TeamManager();
List<String> players = teamman.getPlayers();
List<String> humans = teamman.getHumans();
List<String> infected = teamman.getInfected();
@EventHandler
public void onPlayerJoin(PlayerJoinEvent e){
    //Player p = (Player) e.getPlayer();
    //e.setJoinMessage("["+lvl+"]" + e.getPlayer().getName() +"has joined the game!");
    //p.setDisplayName("[lvl1]"+p.getName());

}
@EventHandler
public void onPlayerDamage(EntityDamageByEntityEvent  e){
    if(e.getEntity() instanceof Player){
        Player p = (Player) e.getEntity();
        Bukkit.getServer().broadcastMessage("Players: "+ players);
        if(players.contains(p.getName())){
            if((p.getHealth() - p.getLastDamage()) < 1){
                for (String temp : players) {
                    Bukkit.getPlayer(temp).sendMessage("§c"+p.getName()+" got infected by "+p.getKiller().getName()+"!");
                }
                e.setCancelled(true);
                 p.setHealth(20);
                 teamman.addToInfected(p.getName());
                 teamman.removeFromHumans(p.getName());
                 p.sendMessage("§cYou have been infected!!");
            }
        }
    }
}

}

As said above i want to be able to access the lists from TeamManager and use them in Events. And as explained players is empty in the Events class. I hope this helps.

Body:
The simple answer is that you need the same instance of ClassA that you created to be passed into ClassB.

When you create a class, you are created the class definition. Each time you use the new keyword, you create a new instance of that class. You can have as many instances of a class as you want, assuming you've got enough memory. But each instance is separate from all the others.

Just like String and List are classes and need to be instantiated, your custom classes do as well. So in your main, or wherever you're using ClassA and ClassB, you'll want to instantiate them like:

ClassA instanceOfClassA = new ClassA();
ClassB instanceOfClassB = new ClassB();

Let's assume, since you didn't specify, that you did that in your main.

You're objective: Access the list of a specific instance of ClassA from within ClassB.

You've already created the getList() method in ClassA. That's good. You'll use that.

Next, you'll want to create a data member inside ClassB that is of type ClassA, as well as a getter and setter for that member:

public class ClassB {
    ...
    ClassA myInstanceOfClassA;

    public void setClassAInstance(ClassA instance){
        this.myInstanceOfClassA = instance;
    }
    public ClassA getClassAInstance(){
        return this.myInstanceOfClassA;
    }
}

Then, back in your main, after you've updated the players in that instance of ClassA, and after you've instantiated your instance of ClassB like above:

instanceOfClassB.setClassAInstance(instanceofClassA);

Then inside ClassB, the list of players is accessible using that instance.

List<String> playersFromClassA = myInstanceOfClassA.getList();

Likewise, calling myInstanceOfClassA.getList().size(); from inside ClassB should return the appropriate number of players.


问:
Opening iMessage with default body containing a link
I am trying to open up the iMessage app with a default message from my app. The default message contains a link to the app in the app store. This is used as a way for users to invite people to download the app.

The user types in a number and then hits a submit button and then it opens up the iMessage app with that number and a refilled message. However, for some reason, Swift won't generate the URL. Here is what I have

```<code>let body = "Download SomeApp by clicking the link below:\n\nhttps://appsto.re/us/someapp.i"

guard let phoneUrl = URL(string: "sms:\(numberTextField.text!)&body=\(body)") else {
            return
}

if UIApplication.shared.canOpenURL(phoneUrl) {
    UIApplication.shared.open(phoneUrl, options: [:], completionHandler: nil)
}
</code>```

Right now its not even getting past the guard statement.

All I want to do is open iMessage with a link to my app in the body.

答:
You need to escape the content passed into the &body= parameter. You can do this with addingPercentEncoding.

For example:

```<code>let body = "Download SomeApp by clicking the link below:\n\nhttps://appsto.re/us/someapp.i"

guard let escapedBody = body.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
    return
}

guard let phoneUrl = URL(string: "sms:\(numberTextField.text!)&body=\(escapedBody)") else {
    return
}
</code>```

Body:
I am trying to open up the iMessage app with a default message from my app. The default message contains a link to the app in the app store. This is used as a way for users to invite people to download the app.

The user types in a number and then hits a submit button and then it opens up the iMessage app with that number and a refilled message. However, for some reason, Swift won't generate the URL. Here is what I have

let body = "Download SomeApp by clicking the link below:\n\nhttps://appsto.re/us/someapp.i"

guard let phoneUrl = URL(string: "sms:\(numberTextField.text!)&body=\(body)") else {
            return
}

if UIApplication.shared.canOpenURL(phoneUrl) {
    UIApplication.shared.open(phoneUrl, options: [:], completionHandler: nil)
}

Right now its not even getting past the guard statement.

All I want to do is open iMessage with a link to my app in the body.

Body:
You need to escape the content passed into the &body= parameter. You can do this with addingPercentEncoding.

For example:

let body = "Download SomeApp by clicking the link below:\n\nhttps://appsto.re/us/someapp.i"

guard let escapedBody = body.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
    return
}

guard let phoneUrl = URL(string: "sms:\(numberTextField.text!)&body=\(escapedBody)") else {
    return
}