Construcción de Interfaces a Usuario: Ejemplo



Descargar 20,05 Kb.
Fecha de conversión25.04.2017
Tamaño20,05 Kb.

Construcción de Interfaces a Usuario: Ejemplo

Representacion de Vistas

  • Component
  • Rectangle
  • bounds
  • getSize() -- returns bounds extent
  • setSize(Dimension)
  • getLocation() -- returns bounds origin
  • paint() <>
  • Component debe definir:
    • el área que ocupara el componente visual
    • la interface mínima para acceder ese área
    • la interface para mostrar gráficamente el componente
  • La metáfora de la transparencia puede ser representada a través de una clase abstracta Component...

Presentación

  • public class MyView extends Component {
  • ......
  • public void paint(Graphics g) {
  • Dimension d = getSize();
  • g.drawRect(0,0, d.width - 1, d.height - 1);
  • }
  • En Java se implementaría del modo siguiente
  • El argumento Graphics representa la interface
  • genérica al sistema gráfico nativo...
  • Como se implementa la metáfora de las transparencias
  • superpuestas?
  • Un componente simple es responsable de producir la representación visual de si mismo

Componentes Compuestos

  • Container
  • Component
  • components
  • add(Component)
  • remove(Component)
  • *
  • Component
  • Vista-Subvista
  • Supervista
  • Subvista
  • components
  • Inv for all s:Supervista, ss:Subvista s.isHide => ss.isHide
  • isHide
  • paint
  • for all c:components
  • c.paint
  • isHide
  • Un container propaga, en general, los mensajes a sus hijos visibles
  • Composite
  • padre

Componentes Compuestos

  • Container::paint(Graphics g){
  • int i;
  • Rectangle oldBox;
  • oldBox:= g.clipRect;
  • g.translate(this.bounds.origin);
  • g.clipRect( this.bounds);
  • for(i=0; i< components size; i++)
  • if (this.bounds.intesects(c.bounds)
  • c.paint(g);
  • g.clipRect(oldBox)
  • }
  • El método paint de un Container es un método template...
  • Como se distribuyen espacialmente los componentes hijos?
  • paint
  • paint
  • paint
  • paint
  • paint
  • Los componentes compuestos deben verificar que sus hijos estén dentro de la región visible que determinan

Distribución de Espacio

  • Alternativa 1: Cada vista compuesta decide la ubicación de sus hijos de acuerdo a su política...
  • import Math.*
  • class PanelView extends Container{
  • Component north,south,west,east,center;
  • setUp(Component c){ up:= c}
  • setDown...
  • reshape(int x,y; int width, height){
  • super.reshape(x,y,width,height);
  • north.reshape(0,0,width, Math.trunc(height*.02))
  • south.reshape(0,height-Math.trunc(height*0.2))
  • .....
  • }
  • Como se varía la distribución ?
  • Una vista compuesta puede definir la distribución espacial de las vistas hijas...

Distribución de Espacio

  • Component-Layout
  • Component
  • Layout
  • strategy
  • strategy
  • components
  • add(Component c)
  • strategy.add(c)
  • setLayout(Layout)
  • Strategy
  • context
  • add(Component c)
  • context.components.add(c)
  • c.reshape(x,y,w,h)
  • La distribución de espacio puede ser delegada en objetos que implementen estrategias de distribución específicas...

Distribución de Espacio

  • import java.awt.*;
  • public class GridWindow extends Frame {
  • public GridWindow() {
  • setLayout(new GridLayout(0,2));
  • add(new Button("Button 1"));
  • add(new Button("2"));
  • add(new Button("Button 3"));
  • add(new Button("Long-Named Button 4"));
  • add(new Button("Button 5"));
  • }
  • public class GridLayout implements LayoutManager {
  • ...
  • public void layoutContainer(Container parent)
  • {
  • Insets insets = parent.insets();
  • int ncomponents = parent.countComponents();
  • int nrows = rows;
  • int ncols = cols;
  • if (ncomponents == 0) {return;}
  • if (nrows > 0) { ncols = (ncomponents + nrows - 1) / nrows; }
  • else { nrows = (ncomponents + ncols - 1) / ncols; }
  • int w = parent.width - (insets.left + insets.right);
  • int h = parent.height - (insets.top + insets.bottom);
  • w = (w - (ncols - 1) * hgap) / ncols;
  • h = (h - (nrows - 1) * vgap) / nrows;
  • for (int c = 0, x = insets.left ; c < ncols ; c++, x += w + hgap) {
  • for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) { int i = r * ncols + c;
  • if (i < ncomponents) { parent.getComponent(i).reshape(x, y, w, h); }
  • }
  • }
  • }

Distribución de Espacio

  • Cada componente debe informar:
      • Tamaño preferido (preferredSize())
      • Tamaño mínimo si es necesario (minumsSize())
  • Lo componentes compuestos deben tener en cuenta estas restricciones para atribuir el espacio ocupado por un componente, bien como calcular su propio tamaño, si no hay restricciones
  • Container::preferredSize(){
  • int i;
  • Dimension d;
  • for(i=0; i< components size; i++)
  • d := d + components[i].preferredSize;
  • }
  • Los componentes pueden poseer difrentes requerimientos de espacio, asi, un protocolo mas complejo es necesario...

Sincronización de Presentaciones

  • Observable
  • hasChanged
  • <>
  • notifyObservers(arg)
  • for all o in observers
  • o.update
  • setChanged ()
  • <>
  • addObserver(Observer)
  • removeObserver(Observer)
  • Observer
  • update(Observable,arg)
  • inv self reflects sub.state
  • *
  • Observable-Observer-Abstract
  • Inv for all s:Observable , o: s.observers => o.isUpdated
  • observers
  • El mecanismo de anuncio de cambios requiere un soporte implementado para la administración de la lista de observadores.
  • Los observadores sólo deben definir el método que manejará
  • la observación.
  • Una clase observable debe notificar a sus observadores que ha cambiado, un observador solo debe implementar el protocolo necesario para la notificación...

Editor de Circuitos

  • public class CircuitApp extends Applet {
  • Circuit circuit=new Circuit();
  • public void init() {
  • setLayout(new BorderLayout());
  • add("East",new PartListView(circuit));
  • add("Center", new LayoutView(circuit));
  • validate();
  • }
  • public static void main(String args[]) {
  • Frame f = new Frame("Editor de circuitos");
  • CircuitApp cir = new CircuitApp();
  • cir.init();
  • f.add("Center",cir);
  • f.setSize(400, 200);
  • }
  • }

Sincronización de Presentaciones

  • class Circuit extends Observable {
  • Vector chips, wires;
  • ...
  • public void addChip(Point center) {
  • Chip c=new Chip(center);
  • chips.addElement(c);
  • setChanged();
  • notifyObservers(c); }
  • }
  • class ListView extends Panel
  • implements Observer {
  • Observable subject;
  • public CircuitView(Circuit c) {
  • setsubject(c);
  • setLayout(new GridLayout(10,1));
  • for (Enumeration e = c.chips.elements() ;
  • e.hasMoreElements() ;) {
  • add(new ChipText(7,(Chip) e.nextElement()));
  • }
  • setSubject(Observable s){
  • if( subject != NULL)
  • subject.removeObserver(this)
  • subject:= s;
  • subject.addObserver(this)
  • }
  • update(Observable o, Object arg){
  • if (arg.instanceOf(Chip) {
  • add(new ChipText(7,arg); }
  • }
  • }
  • public class LayoutView extends Panel
  • implements Observer{
  • Observable subject;
  • public LayoutView(Circuit c) {
  • setsubject(c);
  • setLayout(null);
  • setBounds(0,0,400,400);
  • for (Enumeration e = circuit.chips.elements() ;
  • e.hasMoreElements() ;) {
  • add(new ChipV((Chip) e.nextElement())); }
  • }
  • .....

Sincronización de Presentaciones

  • public class ChipV extends Canvas
  • implements Observer{
  • Observable subject;
  • ...
  • public ChipV(Chip c) { .. }
  • public void update(Observable o, Object arg) {
  • repaint(); }
  • public void paint(Graphics g) {
  • .....
  • g.drawString(subject.name,0,0);
  • } }
  • class Chip extends Observable {
  • Point center;
  • String name;
  • .....
  • public void name(String s) {
  • if (name.compareTo(s) != 0) {
  • name=s;
  • setChanged();
  • notifyObservers(this); }
  • }
  • }
  • public class ChipText extends TextField
  • implements Observer {
  • public ChipText(int f,Chip c) {
  • super(f);
  • setSubject(c);
  • }
  • public void update(Observable o, Object arg) {
  • setText(subject.name); }
  • }

Tratamiento de Eventos

  • Los componentes compuestos propagan el evento a sus hijos. Si estos no lo tratan, entonces debe intentar tratarlo el mismo...
  • Este mecanismo implica convenciones...
  • Si un componente no esta interesado en tratar un evento entonces debe retornar false...
  • window
  • menu
  • editorView
  • iconPallete
  • simpleView
  • simpleView
  • evento
  • Las vistas deben ser capaces de reaccionar a eventos de entrada y comunicarlos a la aplicación

Tratamiento de Eventos

  • public boolean processEvent(Event evt) {
  • switch (evt.id) {
  • case Event.MOUSE_ENTER:
  • return mouseEnter(evt, evt.x, evt.y);
  • case Event.MOUSE_EXIT:
  • return mouseExit(evt, evt.x, evt.y);
  • case Event.MOUSE_MOVE:
  • return mouseMove(evt, evt.x, evt.y);
  • case Event.MOUSE_DOWN:
  • return mouseDown(evt, evt.x, evt.y);
  • case Event.MOUSE_DRAG:
  • return mouseDrag(evt, evt.x, evt.y);
  • case Event.MOUSE_UP:
  • return mouseUp(evt, evt.x, evt.y);
  • ....
  • public boolean mouseDown(Event evt, int x, int y){ return false; }
  • public boolean mouseDrag(Event evt, int x, int y) { return false; }
  • public boolean mouseUp(Event evt, int x, int y) { return false; }
  • Cada vista podría determinar si trata un evento o no implementando un método determinado...

Flexibilizando el Manejo de Eventos

  • Solución: Delegar el manejo de eventos en objetos separados
  • Component-Listener
  • Component
  • Listener
  • listeners
  • *
  • Los listeners se propagan el evento hasta que alguno lo trate, retornando true.
  • El manejo de eventos embutidos en las vistas no permite variar dinámicamente las manipulaciones ni la reutilización de las mismas....

Tratamiento de Eventos

  • public class CircuitApp extends Applet{
  • ..
  • public static void main(String args[]) {
  • Frame f = new Frame("Editor de circuitos");
  • CircuitApp cir = new CircuitApp();
  • cir.init();
  • f.add("Center",cir);
  • f.setSize(400, 200);
  • f.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0);}});
  • f.show(); }
  • }
  • public class ChipV extends Canvas
  • implements Observer{
  • public ChipV(Chip c) {
  • ....
  • addMouseMotionListener(new DragChip());
  • }
  • class DragChip implements MouseMotionListener {
  • public void mouseDragged(MouseEvent e) {
  • setBounds(e.getX()-W/2,e.getY()-H/2,W,H); }
  • }
  • }

Usando toolkits nativos

  • Component-Implementation
  • Component
  • ComponentPeer
  • peer
  • paint()
  • handleEvent()
  • Bridge
  • context
  • paint()
  • handleEvent()
  • Toolkit
  • createScrollbar()
  • createButton()...
  • defaultToolkit
  • creates
  • Abstract Factory
  • Inv for all c:Component
  • c.addNotify => Toolkit.defaultToolkit.createComponentPeer
  • Cada componente visual puede delegar la implementación concreta en otra clase que implemente la interfaz con el sistema nativo.
  • Una clase Toolkit puede implementar la interfaz abstracta para crear componentes específicos del sistema nativo
  • La interfaz debiera ser adaptable a diferentes looks and feels provistos por los manejadores de ventanas nativos...

Swing



La base de datos está protegida por derechos de autor ©absta.info 2016
enviar mensaje

    Página principal