Clonacion de objetos en vb.net

trinytron

Hola, necesito que me ayudeis en un tema que me esta dando quebraderos de cabeza porque no se como hacerlo. La forma que dice la web de microsoft no me funciona. A ver si vosotros me podeis ayudar:

Necesito clonar o crear una vez arrancado X veces un objeto de la clase picturebox. En la Web de Microsoft ponia esto:

Dim equipo_pic As New Windows.Forms.PictureBox()
Me.List.Add(equipo_pic)

Pero no me funciona :S.

Alguien me puede decir como puedo clonar X veces este objeto o crear una matriz de este objeto para usarla tantas veces como sea necesario????

IS4kO

Hola trinytron, da un poco más de datos, probablemente el error esté en la declaración de List (que imagino habrás importado de System.Collections.Generic y no de System.Web.UI.MobileControls.List).

Y en realidad no estas clonando, estas creandote objetos de tipo PictureBox que es distinto...

En cuanto a lo de usarlo cuantas veces sea necesario no entiendo, para que necesitas una matriz...

Tu una vez que te creas la instancia a picture box para el objeto X podrás usar X las veces que te de la gana... y como quieras...

Bueno resumiendo intenta darnos un poquillo mas de info aer si podemos arreglaro ;)

trinytron

Bueno #2 jaja quiza me he colado.... si es creacion de objetos una vez esta ejecutada la aplicacion.

La libreria que tu dices no es de web???? yo estoy desarrollando una aplicacion para windows y seguramente no pueda hacer un list.add porque me falte la libreria.....

Bueno, gracias por contestarme :)

IS4kO

Nose si tienes un poco de lio con lo de list.. mira

Tenemos dos clases List:

1º) Una perteneciente a: System.Collections.Generic OjO ese espacio de nombres y la clase list es nueva para el FW2.0

Si quieres sustituir todo el nameSpace System.Collections.Generic.list pues tengrás que importarla al proyecto.

Esta clase la podras usar en cualquier proyecto .net, windows, web...

Y lo que hace es que representa una lista de objetos con establecimiento inflexible de tipos a la que se puede obtener acceso por índice. Proporciona métodos para buscar, ordenar y manipular listas, que creo es lo que buscas no?

2) Y por otro lado tenemos el control List de System.Web.UI.MobileControls q es un control q procesa una lista de elementos en un dispositivo móvil, y este si que es para usarse para asp.net movile


Dicho esto, por eso te decia si has importado a tu proyecto el nameSpace System.Web.UI.MobileControls te estará cascando per cuyons....

Si por el contrario estas usando (el que deberias), de System.Collections.Generic, mirate como te has declarado el control, deberias tener algo asi, en el caso de no haber importado ningun namespace:

Dim miList As New System.Collections.Generic.List(Of TipoVariable)

trinytron

Bueno te explico para que me entiendas quiza postee mal lo que realmente queria hacer.

Tengo un picturebox que necesito usarlo X veces (cuantas veces no lo se, eso lo tengo que calcular una vez ejecutado el programa). Entonces necesito crear un objeto de la clase picturebox cuando el programa ya esta ejecutado. En la web de Microsoft lo ponia como lo puse yo arriba pero cuando hago "Me." no me sale para elegir el "Me.List" entonces supongo que tendre que importar alguna clase.

He importado el "System.Collection.Generic" y sigue sin aparecer el "Me.List" para poder añadir el objeto al formulario.

De nuevo te doy las gracias por intentar ayudarme :)

IS4kO

Con Me haces referencia a tu clase, ventana de windows, etc... Si como ponias anteriormente, es una aplicación win, cuando pongas Me. te apareceran todas las propiedades métodos etc... de System.Windows.Forms pero como es lógico no te aparecerán los de System.Collections.Generic aunque hayas importado el namespace a tu form..

para usar el list ya que has importado el namespace System.Collections.Generic Tienes q crearte una instancia de List (te recuerdo que es una clase) y usar el objeto instanciado cuando quieras usarla desde tu programa. Como te ponía en la declaración del post anterior (pero ahora sin el namespace, ya que lo has importado):

Dim miList As New List(Of TipoVariable)

y cuando quieras usarlo pues:

miList.ad() ..... o lo que sea

trinytron

Bueno gracias a ti puedo editar ya los atributos del objeto que he creado el problema esque no se muestra en pantalla no se porque :S, es decir, hago lo que tu me has dicho milista.add(equipo_pic) y luego edito los atributos y le doy un location = a otro objeto que tengo por ahi para que se muestre y el visible = true pero no aparece jajaja no se porque.

Me podrias decir porque??? quiza o hago todo mal :S... yo solo quiero crear objetos una vez arrancado el programa, es decir, cuando esta en ejecucion

IS4kO

Veras es más facil de lo que creo imaginas..

Tu cuando tienes un programa en ejecucion puedes crear los objetos que quieras en tiempo real, por ejemplo, imaginate que queremos crearnos un objeto una vez arrancado el programa cuando pinchas un boton:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
dim miObjetoEnTiempoReal as new miClase
End Sub

Es tan simple, como declarar la instancacion del objeto en cualquiera de los eventos de tu form, cuando cargue (load), cuando se maximice, cuando pinches un boton, en definitiva, cuando ocurra "algo"

trinytron

Como tu dices, un objeto en tiempo de ejecucion solo es reservarle un espacio en memoria con lo cual hacemos lo de new.

Yo ya tenia creado esto:


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click


Dim equipo_pic As New Windows.Forms.PictureBox()
Me.milista.Add(equipo_pic)

    equipo_pic.Top = pic_equipo.Top
    equipo_pic.Left = pic_equipo.Left
    equipo_pic.Image = pic_equipo.Image
    equipo_pic.ErrorImage = pic_equipo.ErrorImage
    equipo_pic.Visible = True

[/b][/i]

Pero no sale en pantalla una vez aprieto el boton "button1".

Nota: Pic_equpo es un objeto plantilla que tengo oculto, cojo su Image, Top, Left, etc... todo pero sigue sin aparecer en el form

- EDITED

He creado un nuevo proyecto para probar la creacion de objetos y he echo lo siguiente:

Dim milista as new Microsoft.VisualBasic.Generic (creoq ue era asi...)

Button1_click...........

Dim boton 2 as New Windows.System.Forms()
milista.add(boton2)

Button1.Location = boton2.location
Button1.Size = boton2.size

Al hacer esto lo que ha ocurrido esque el button1 se ha movido a arriba a la izquierda y no ha cambiado de tamaño.... No hay forma de que aparezca boton2 jajajajajajaja

IS4kO

Mira, aquí tienes la creación en "tiempo de ejecución" de un objeto de tipo picturebox. Se visualiza perfectamente, cuando pincho sobre Button1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim isako As New Windows.Forms.PictureBox
    isako = Me.PictureBox1
    isako.Show()

End Sub

Siendo PictureBox1 ese objeto plantilla invisible que decias antes, con sus propiedades y demás...

trinytron

Ostia tio!!!!!!!!!! Muchas gracias :D:D:D:D:D ahora si que me funcionaaaaa jijijijijijiji

Eres un genio gracias :D

IS4kO

Nada hombre, me alegro de que funcione ;) ves como no era tan dificil :P

trinytron

Jejeje eres un genio tio :) de nuevo te doy las gracias :P. He estado haciendo pruebas y solo te crea 1 imagen aunque le des 10 veces al Button1 puesto que he realizado una funcion que te crea la imagen y la mueve dentro del formulario 100 veces y lo que hace es mover el mismo objeto 100 veces y no crea 1 por cada llamada a la funcion digamos.

Creo que la solucion esta en usar un array pero si hago esto:

Dim equipo_pic() as New....

Me dice el VB que no se puede usar con un array New.

IS4kO

Bueno esto tampoco es muy complicado, vas encaminado...

1º Te tienes que crear un vector, tabla, matriz o como lo quieran llamar, este puede ser bien un array normal, un arrayList o un List (como el que usabas el otro día, que es una especie e ArrayList para el FW2.0). En el ejemplo que voy a usar utilizaremos ArrayList, ya que creo que es mucho mas potente que un arrayNormal, y mas simple de usar, aunque ocupe algo más de memoria

2º Será importante que los valores del arrayList permanezcan durante toda la ejecucion del programa, pinchemos lo que pinchemos, hagamos lo que hagamos luego tendremos que declararos como privado

3º Deberias dejarlo de la siguiente manera:

Public Class Form1

'Declaramos el arrayLIst como privado

Private miArrayList As New ArrayList

'Creamos el objeto isako y lo metemos en el arrayList

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim isako As New Windows.Forms.PictureBox
    isako = Me.PictureBox1
    miArrayList.Add(isako)
End Sub

'Vamos a mostrar el objeto que hemos creado y que está en la posicion 0 del arrayList

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    miArrayList.Item(0).show()
End Sub

End Class

Esta debería ser la base de tu programa, ahora, esto puedes modificarlo de mil formas, meteindo por ejemplo una funcion o clase de creacion de objetos, para que no te meta siempre el mismo objeto (en mi caso isako), añadir lo que te parezca de los objetos, etc...

trinytron

He probado lo del arraylist y no ha funcionado te pasteo el codigo a ver si me dices porque... seguro que es otra chorrada como la del .Show()

Lo que me hace es que solo mueve un objeto y he probado haciendolo manualmente en vez de usar la variable conta a ver si mostraba los 2 pics y no ha habido forma. He pensado que era que las coordenadas eran las mismas pero no ha sido asi puesto que he cogido 2 objetos del arraylist y le he dado coordenadas distintas.


Private miArraylist As New ArrayList
Dim Conta As Integer = 0

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    While barrabusqueda.Value <= 100
        If barrabusqueda.Value = 0 Then
            x = 100
            y = 90
        Else
            If x >= 350 Then
                x = 100
                y = y + 20
            ElseIf y >= 300 Then
                y = 300
            Else
                x = x + 20
            End If
        End If

        If barrabusqueda.Value = 100 Then
            Exit While
        Else
            CrearEstacion(x, y)
            barrabusqueda.Value = barrabusqueda.Value + 1
        End If

    End While
    Timer1.Enabled = True
End Sub

Private Sub CrearEstacion(ByVal x As Integer, ByVal y As Integer)
Dim equipo_pic As New Windows.Forms.PictureBox()

    equipo_pic = Me.pic_equipo
    equipo_pic.Top = y
    equipo_pic.Left = x


    miArraylist.Add(equipo_pic)
    miArraylist.Item(Conta).Show()

    Conta = Conta + 1
End Sub

[/b][/i]

P.D: Me podrias decir alguna web o algun libro para aprender mas sobre Vb.net??? Muchas gracias por querer ayudarme :)

IS4kO

Eso es pq como el objeto se llama siempre iwal, la instanciación se queda en memoria y les asigna a todas las casillas los valores del último objeto instanciado.... pero no problem

Podemos hacer lo mismo pero con un HashTable, para que te hagas una idea, un arraylist es como una cajonera sin etiquetas, solo lo puedes abrir cajon a cajon, sin saber lo que va a haber dentro. Un Hastable, es como una cajonera tuneada, que tiene una etiqueta para cada cajon, de manera que puedes insertar y obtener un objeto en base a su identificador, es decir su etiqueta.

Ademas, no necesita ser dimensionado, ni tiene orden (es decir, no metes las cosas en el cajon 1, luego en el 2, luego en el 3), eso da igual, tu metes las cosas en el cajon "calcetines", "gayumbos" o "camisetas", independientemente de que la Hash ponga uno u otro primero. Por lo tanto la obtención tambien es así, es decir, le dices, dame algo del cajon "calcetines", sin tener que recorrer el resto de cajones. Aún así, si quieres recorrer todos los cajones de la Hashtable, estos se llaman DirectoryEntry que es un par etiqueta-valor, es decir, identificador (propiedad Key) y objeto (propiedad Value).

Eso es lo conceptual, como se hace... muy simple.

Dim myHT As New Hashtable()
Dim calcetos() as Calcetines
myHT.Add("calcetines", calcetos)
myHT.Add("camisetas", nothing)
myHT.Add("gayumbos", )

' puedes obtener directamente así
calcetos = Ctype(myHT("calcetines"), Calcetines)

' o bien recorre la HT entera
For Each de as DictionaryEntry in myHT
calcetos = Ctype(de.Value, Calcetines)
End For

Como ves, los cajones son todos iguales, por tanto, para sacar el valor y meterlo en una variable, hay que castearlo con un ctype.... si no no tira

Sobre webs y libros:

Libros:
www.lalibreriadigital.com
Webs:
www.msdn.com
www.elguille.info

trinytron

Hola IS4k0 perdona por mi tardancia al contestar pero tenia asuntos personales que resolver...

He estado mirando tu Hashtable y me recuerda a lo que es una "pila" que vas memorizando uno tras otro cada elemento en la memoria.

He estado jugando con el Hashtable a ver si podia sacarlo adelante e incluso he mirado en el msdn y no me ha dejado nada claro. Como cada objeto tiene su propio nombre digamos, para poder memorizarse he generado automaticamente un nombre y he echo lo siguiente:


Private Sub CrearEstacion(ByVal x As Integer, ByVal y As Integer)
Dim equipo_pic As New Windows.Forms.PictureBox()
Dim equipo_aux As New Windows.Forms.PictureBox()
Dim mezcla As String

    equipo_pic = Me.pic_equipo
    equipo_pic.Top = y
    equipo_pic.Left = x

    mezcla = CType(Conta, String) & "_equipo_pic"

    MessageBox.Show(mezcla)


    myHT.Add(mezcla, equipo_pic)

    equipo_aux = CType(myHT(mezcla), Windows.Forms.PictureBox)

    equipo_aux.Show()

    Conta = Conta + 1
End Sub

[/i][/b]
El resultado es el mismo que con el Arraylist solo consigo mover un objeto y los demas no se si existen o simplemente no se han creado.

kas

Buenas chicos!

A ver, creo que el titulo del post no tiene nada que ver con lo que preguntas, ya que necesitas X instancias nuevas de un objeto.

De todas maneras, cuando uses objetos complejos (como tu PctBox), ten mucho cuidado con las colecciones, listas y matrices y con los parametros de funciones.

Yo si que he tenido que implementar la Clonacion en los objetos, ya que la asignacion en vb.net no es mas que un puntero oculto.

Para clonar un objeto no necesitas mas que:

Public Class Isako

...

Public Function Clone() as Isako

Dim i as New Isako(...)
' Las inizializaciones o manipulaciones que creas que
' debes hacer para dejar el objeto i igual que tu clase
' actual (me)

Return i

End Function

End Class

La llamada cuando necesites crear una instancia nueva de un objeto Isako que ya tienes seria:

...
' Asumiendo que MyPrimerIsako ya esta instanciado
Dim myIsakoQuerido2 as Isako = me.MyPrimerIsako.Clone()

Además, Microsoft proporciona una Interface estandar ICloneable. A mi no me gusta mucho, ya que al ser Estandar el objeto devuelto es un "Object" y t puedes pasar la vida haciendo Casting. Ahora no recuerdo si es heredable, pero esa sera una solucion tambien. Pero volviendo al principio, eh aki la implementacion de la Interface ICloneable:

Public Class Isako
Implements ICloneable

' Codigo añadido automaticamente por el IDE
Public Function Clone() As Object Implements System.ICloneable.Clone

Dim i as New Isako(...)
' Las inizializaciones o manipulaciones que creas que
' debes hacer para dejar el objeto i igual que tu clase
' actual (me)

Return i
End Function
End Class

Como sabras no hay que hacer un Cast de i (tipo Isako) a Object ya que Object es heredado por fuerza por todas las clases, la llamada quedaria:

...
' Asumiendo que MyPrimerIsako ya esta instanciado
Dim myIsakoQuerido2 as Isako = me.MyPrimerIsako.Clone()

Como ves no hace falta un Cast, por lo de siempre. De todas maneras a mi no me gusta nada trabajar con tipos Object.

Bueno ahi queda la cosa, un saludo!

IS4kO

Todo un honor ser tu objeto kas xdd

El problem es que ese objeto debe crearse independientemente x veces, y existir x veces, y la única forma que veo independiente para luego poder darle propiedades distintas a cada uno de ellos, es meterlo en alguna colección ya sea arrayList, hashtable, tabla....

Esta bien, es cierto que tu luego puedes poner dim miIsako2 as new isako pero y si tienes hasta miIsako43, ¿como lo controlas si de principio no sabes cuantos objetos vas a tener que clonar?

Pero bueno en el maravilloso mundo de .net siempre hay soluciones para todo (no?) xD, se me ocurre crear la clase isako teniendola que pasar las caracteristicas del objeto directamente como propiedades publicas y sus miembros privados a la propia clase...

Es la unica via de escape que veo, aunque la verdad es como debería haberse hecho desde un principio, ya que es la forma mas "pr0?..." ya que en realidad, lo que te estas haciendo es toda una dll isako, con sus miembros etc.... siguiendo las reglas de la poo de encapsulación, herencia etc...

Sorry por tardar pero me tomé una semanita de vacas hombree :^)

Ooooo samps deliseee, OOooooo samps deliseee ... xDD PARIS RLZ

kas

Bueno, puedes implementar la clonacion independientemente de la forma de almacenarlos.

Quizas una hashtable seria lo adecuado, o una coleccion si crees que puedes buscar por indice. Siempre podriamos escribir un codigo parecido a esto:

Dim myIsakoCol as New Collection
' Usaremos un tipo standar

'
' Asumiendo que la primera posicion de la coleccion (1,
' ya que 0 esta reservada) contiene un objeto de tipo
' Isako

dim IsakoTemp as Isako = myIsakoCol.Item(1).Clone()
'
' Manipulaciones
' Asumiendo X entero

myIsacoCol.Item(X) = IsakoTemp

Usuarios habituales

  • kas
  • IS4kO
  • trinytron