Download miswing
Document related concepts
no text concepts found
Transcript
Java GUI La librería Swing //java.sun.com/docs/books/tutorial/uiswing //programacion.com/java/tutorial/swing/ Programación conducida por eventos En programas tradicionales (basados en texto): el programa controla el flujo de la ejecución el programa controla la secuencia de las entradas Los programas con GUI son “event-driven” la secuencia de las entradas controlan el flujo de la ejecución el sistema invoca código del usuario Programación conducida por eventos Código del sistem a Su código Generación de eventos 1. Las acciones tales como: pulsar un botón, mover el mouse, etc. son reconocidas e identificadas por los sistemas operativos (OS) o la JVM. 2. Por cada acción el OS/JVM determinan cuál de los programas que se están ejecutando recibirán la señal (de la acción). 3. Las señales que la aplicaciones reciben del OS/JVM como resultado de una acción son llamadas eventos. Generación de eventos GUI Acciones Mouse, Teclado,etc. Sistema Operativo JAVA API /Windows Métodos y handlers Aplicación 1 Eventos Métodos y handlers Aplicación 2 Manejo de eventos Una aplicación responde a los eventos ejecutando código adecuado para cada tipo particular de eventos. No todos los eventos necesitan ser tenidos en cuenta por una aplicación. Por ejemplo: Una aplicación para dibujar puede estar interesada sólo en movimientos del mouse. Como diseñador de una aplicación manejada por eventos, deberá escribir clases/métodos para manejar los eventos relevantes. Java GUI Java provee dos librerías para crear GUIs: Java AWT (Abstract Window Toolkit) Java Foundation Classes (JFC o Swing), a partir de Java2 Java Foundation Classes JFC es una colección muy grande de software. AWT y Swing son las dos grandes familias para desarrollo de GUI en el entorno Java. AWT Swing Drag & Drop JFC APIs 2D API Accessibility Java Foundation Classes Swing Implementada sin usar código nativo (100% Java), con lo cual la GUI se verá de la misma forma en distintas plataformas. Basada en la arquitectura MVC. Ofrece una amplia variedad de Look & Feel. Los componentes de Swing continuarán siendo mejorados en el futuro. AWT y Swing Los componentes de Swing tienen nombres que comienzan con J. Ejemplo: Button en AWT es JButton en Swing Los componentes de AWT están en el paquete java.awt, los de Swing en javax.swing. import javax.swing.*; import java.awt.*; import java.awt.event.*; Paquetes JFC/Swing • javax.swing • • • • javax.swing.plaf javax.swing.plaf.basic javax.swing.plaf.metal javax.swing.plaf.multi • javax.swing.table • javax.swing.tree • javax.swing.border • javax.swing.colorchooser • javax.swing.filechooser • • • javax.swing.text javax.swing.text.html javax.swing.text.html.parser • javax.swing.text.rtf • javax.swing.event • javax.swing.undo Paquetes JFC/Swing Control del “Look & Feel” de Swing Widgets basados en texto ( incluyendo html/rtf ) Componentes, incluyendo componentes complejos Paquetes nuevos de eventos Aplicaciones basadas en GUI El desarrollo de una aplicación basada en GUI requiere la comprensión de: Estructura de la jerarquía de herencia, que define el comportamiento y atributos de los componentes en la GUI de la aplicación. Estructura de la jerarquía de contenedores, que define cómo se disponen todos los componentes en la GUI de la aplicación. Manejo de eventos. Jerarquía de Herencia Herencia “Heavy” java.awt.Window java.awt.Panel java.applet.Applet JApplet java.awt.Dialog JDialog JWindow JFrame Heavyweight vs. Lightweight Contenedores en Swing java.aw t.Container JMenu JMenuBar JComponent JLayeredPane JRootPane JPanel JTabbedPane JDesktopPane JSplitPane JPopupMenu JOptionPane JInternalFrame JToolbar JScrollPane Similar a AWT Nuevos de Swing Componentes de Swing La clase Component (y sus subclases) proveen soporte para manejo de eventos, cambio del tamaño de un componente, control de color y fuentes, pintado. Un componente es un objeto de una subclase concreta. Se distinguen dos clases de componentes: Componentes de control de la GUI: la interacción de la GUI con el usuario se realiza a través de ellos. Contenedores: contienen otros componentes (u otros contenedores). Contenedores Anidamiento de componentes (Jerarquía de contenedores en contraste con la Jerarquía de herencia). Cada programa Swing contiene al menos una. Usan un Layout Manager para determinar cómo se disponen los componentes en los contenedores. Swing provee 4 contenedores de alto nivel (ventana base de la GUI): JFrame, JApplet, JDialog y JWindow. La jerarquía está compuesta de diferentes capas. Cada contenedor de alto nivel contiene un contenedor intermedio conocido como “content pane ”. En casi todos los programas no es necesario conocer qué hay entre el contenedor de alto nivel y el content pane. Jerarquía de contenedores Jerarquía de contenedores La apariencia de una GUI está determinada por: La jerarquía de contenedores El Layout Manager de cada contenedor Las propiedades de los componentes individuales Todos estos ítems trabajan en conjunto para determinar el efecto visual final. Estructura de un JFrame Estructura de un JFrame Root Panes “Añadido” en forma invisible al contenedor de alto nivel. Creado por Swing cuando instancia un contenedor de alto nivel. Maneja prácticamente todo entre el contenedor de alto nivel y los componentes atómicos. Tener en cuenta si necesita interceptar clicks del mouse o pintar sobre varios componentes. Es una instancia de JLayeredPane la que contiene la barra de menús y el content pane. Content Panes Usualmente es un JPanel. En la mayoría de las aplicaciones Swing contiene casi todo, excepto la barra de menú. Debe ser creado explícitamente. Layered Panes Provisto por root pane pero también puede crearse. Contenedor con profundidad, tal que componentes que se superponen (ej:popup menus) pueden aparecer unos encima de otros (z-buffering). Glass panes Util para pintar o interceptar eventos (por ejemplo: bloquear todos los eventos del mouse) en un área que contenga uno o más componente Contenedores de alto nivel Applet Dialog Frame Contenedores generales Panel TabbedPane Scroll Pane SplitPane Toolbar Contenedores especiales InternalFrame Root Pane LayeredPane JFrame Algunos métodos de JFrame Para añadir componentes al content pane: myFrameInstance.getContentPane().add(myComponent); Usual “this” Requerido por Instancias de JFrame, JDialog y JInternalFrame Ej.: “myLabel” Algunos métodos de JFrame Para construir una ventana con un título y mostrarla: JFrame theWindow = new JFrame( "Graffiti" ); theWindow.show( ); //idem theWindow.setVisible(true); Para determinar su tamaño: theWindow.setJMenuBar(cyanMenuBar); theWindow.setSize( 220, 100 );//o mejor theWindow.pack(); Nueva funcionalidad de JFrame setDefaultCloseOperation(int) es la más importante: DO_NOTHING_ON_CLOSE HIDE_ON_CLOSE (default) oculta el frame cuando el usuario lo cierra pero no se deshace de los recursos del sistema asociados (puedo volver a mostrar). DISPOSE_ON_CLOSE oculta el frame y llama al método dispose(), para liberar recursos. EXIT_ON_CLOSE, cierra la aplicación (System.exit(0)) Hello World en Swing import javax.swing.*; public class HelloWorldSwing { public static void main(String[] args) {// crear un nuevo frame JFrame frame = new JFrame("HelloWorldSwing"); // crear una etiqueta y añadir al frame JLabel label = new JLabel("Hello World"); frame.getContentPane().add(label); //especifica la operación de cierre de la ventana frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // muestra el frame en pantalla frame.pack(); frame.setVisible(true);}} Componentes atómicos Componentes de tipo JPanel almacenan otros objetos de la GUI tales como: botones, etiquetas, campos de texto, etc. Estos objetos gráficos son considerados componentes atómicos, puesto que no pueden almacenar otros objetos de la GUI. Componentes atómicos básicos Buttons Menu Combo Box Slider Spinner List Text Fields Componentes atómicos no editables Label Progress Bar Tool tip Otros componentes atómicos Color Chooser Table File Chooser Text Tree API de los componentes GUI Componente GUI en Java= class Propiedades Métodos Eventos JButton Componentes GUI 1.- Crear Instanciar objeto: b = new JButton(“press me”); 2.- Configurar Propiedades: b.text = “press me”; (evitar en Java) Métodos: b2 = new JButton("Middle button", middleButtonIcon); b2.setVerticalTextPosition(AbstractButton.BOTTOM); b2.setHorizontalTextPosition(AbstractButton.CENTER); b2.setMnemonic(KeyEvent.VK_M); b2.setToolTipText("This middle button does nothing “ + "when you click it."); 3.- Añadir panel.add(b); 4.- Manejar eventos Características especiales Los componentes Swing ofrecen características especiales: Tool tip Cuando el cursor del mouse se detiene sobre un componente se muestra una línea de texto. Mnemonic Se ejecuta una acción como resultado del pulsado de una combinación de teclas. Un componente puede ser explícitamente habilitado o deshabilitado. Rodea un componente con un borde. Disable Border Características especiales Tool tips JButton button = new JButton ("Compute"); button.setToolTipText ("Calculate size."); Mnemonic button.setMnemonic ("C"); Disable JButton button = new JButton (“Do It”); button.setEnabled (false); Características especiales Bordes JPanel myPanel = new JPanel(); Border myBorder = BorderFactory.createEtchedBorder(); myPanel.setBorder(myBorder); Empty Titled Line Matte Etched Compound Bevel Bordes Anatomía de una aplicación GUI JFrame JFrame JPanel contenedores JPanel JButton JButton JLabel JLabel Estructura interna GUI Uso de un componente GUI 1. Crearlo 2. Configurarlo 3. Añadir hijo (si es contenedor) 4. Añadir al padre (si no es JFrame) 5. Manejar los eventos orden importante Construcción bottom up Listener Crear: Frame Panel JLabel JButton Componentes Listener JPanel Añadir (bottom up) Listeners a los componentes Componentes al panel Panel al Frame JFrame Window Layout contenedores componentes Window Layout Cada contenedor maneja la disposición de sus componentes. El programador sólo añade componentes, el contenedor se encarga de la disposición de los mismos. El contenedor usa un Layout Manager para manejar la disposición de los componentes en el mismo. Están disponibles diferentes Layout Managers. El layout puede ser determinado especificando Layout Managers para los contenedores. Layout Managers Hay varios Layout Managers predefinidos en: FlowLayout (en java.awt) BorderLayout (en java.awt) CardLayout (en java.awt) GridLayout (en java.awt) GridBagLayout (en java.awt) BoxLayout (en javax.swing) OverlayLayout (en javax.swing) Layout Managers (LM) Cada contenedor tiene un Layout Manager por defecto, aunque se puede establecer otro LM para el mismo, de forma explícita. Para anular el LM por defecto se usa el método setLayout (para contenedores de alto nivel se usa getContentPane().setLayout(). El Layout Manager intenta ajustar la disposición de los componentes en el contenedor cuando se añade un nuevo componente o cuando el contenedor cambia de tamaño. Puede crear su propio LM. Layout Managers de AWT null FlowLayout ninguno, programador setea x,y,w,h Left to right, Top to bottom BorderLayout n w c s e CardLayout One at a time GridLayout GridBagLayout JButton Null Layout setLayout(null); El programador es responsable de establecer el tamaño y posición de cada componente (setBounds(x,y,w,h)) Combinaciones JButton JButton JTextArea Combinaciones JButton JButton JFrame n JPanel: FlowLayout JPanel: BorderLayout c JTextArea Tareas comunes del LM Prestar atención a indicaciones de un componente: de tamaño: setMinimumSize(Dimension), setPreferredSize(..), setMaximumSize(..) de alineamiento: setAllignmentX(float), setAlignmentY(float) Poner espacios entre componentes: el LM puede especificar hgap y vgap poner componentes invisibles bordes vacíos: para componentes que no tienen bordes por default, por ej.:JPanel, JLabel. Estructura del Layout JPanel(BoxLayout(V)) label rigidArea(0,5) Center JScrollPane South HorizontalGlue JPanel (BorderLayout) JButton JButton JPanel(BoxLayout(H)) rigidArea(10,0) FlowLayout Container contentPane = getContentPane(); contentPane.setLayout(new FlowLayout()); contentPane.add(new JButton("Button 1")); Es el LM por defecto de JPanel. Dispone los componentes de izquierda aderecha a medida que se añaden, comenzando filas nuevas si es necesario. FlowLayout Cada fila de componentes está centrada por defecto, pero puede alinearse por derecha o izquierda. Pueden establecerse explícitamente espacios verticales y/o horizontales entre componentes. Usar sólo en aplicaciones muy simples (oculta componentes que no entran). GridLayout Container contentPane = getContentPane(); contentPane.setLayout(new GridLayout(0,2));//tantas filas como necesita contentPane.add(new JButton("Button 1")); Dispone los componentes en forma de matriz, con la cantidad de filas y columnas especificadas. Todas las filas tienen el mismo alto y todas las columnas tienen el mismo ancho. El tamaño de cada celda es determinado por el tamaño del contenedor. Permite establecer vgap y hgap. Usar si es seguro que los componentes tendrán igual tamaño. BorderLayout Container contentPane = getContentPane(); contentPane.add(new JButton("Button 1 (NORTH)"),BorderLayout.NORTH); //no hace falta setear el LM Es el LM por defecto de los content pane (contenedor principal en JFrame, JDialog y JApplet). Define 5 áreas en las cuales se pueden añadir los componentes. BorderLayout Si se agranda la ventana, la parte central toma tanto espacio como le sea posible, las otras 4 áreas se expanden sólo lo necesario para llenar el espacio disponible. Un contenedor, generalmente usa 1 o 2 de las 5 áreas de BorderLayout. Por ejemplo: centro o centro y sur. Se puede especificar vgap y hgap. CardLayout Jpanel cards = new JPanel(); cards.setLayout(new CardLayout()); cards.add(p1, "JPanel with JButtons"); Permite implementar un área que contiene distintos componentes en distintos instantes de tiempo (naipes). Normalmente controlado por una Combo Box, el estado de ésta determina cuál grupo de componentes muestra el LM. GridBagLayout Container contentPane = getContentPane(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); contentPane.setLayout(gridbag); c.fill = GridBagConstraints.HORIZONTAL; Jbutton button = new JButton("Button 1"); c.weightx = 0.5; c.gridx = 0; c.gridy = 0; gridbag.setConstraints(button, c); Es el LM más sofisticado y flexible. Alinea componentes en una matriz de celdas permitiendo a algunos componentes abarcar más de una celda. BoxLayout JPanel buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS)); buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(cancelButton); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(setButton); Pone los componentes en una sola fila o una sola columna Respeta los tamaños máximos requeridos de los componentes y el alineamiento X/Y. BoxLayout Los componentes son dispuestos de arriba abajo o de izquierda a derecha en el orden en el cual son añadidos al contenedor. Pueden crearse muchas configuraciones distintas, combinando múltiples contenedores que usen BoxLayout. Preferido a un único contenedor que use el más complicado GridBagLayout (mejor: BoxLayouts anidados), es útil también en algunas situaciones donde se podría considerar el uso de GridLayout o BorderLayout. BoxLayout BoxLayout tiene en cuenta el alineamiento, tamaños mínimos, máximos y preferidos que se eligen para los componentes: btn.setAlignmentX(float alignmentX); lbl.setAlignmentY(float alignmentY); lbl.setMaximumSize(new Dimension(int width, int height); lbl.setMinimumSize(new Dimension(int width, int height); lbl.setPreferredSize(new Dimension(int width, int height); Para añadir espacio entre componentes se usa la clase Box o bordes invisibles a uno o ambos componentes. BoxLayout Tipo Rigid area Tamaño Cómo crearla? Box.createRigidArea(size) horizont al Box.createHorizontalGlue() vertical Box.createVerticalGlue() customBox.Filler new Box.Filler(minSize, prefSize, maxSize) Glue Otras estrategias Swing JSplitPane JTabbedPane (CardLayout) JToolBar Pasos en el desarrollo de una aplicación simple con GUI Extienda la aplicación de JFrame Declare las referencias a componentes necesarios Defina el constructor Instancie un content pane y decida Layout Instancie objetos para los componentes necesarios y establezca sus propiedades Añada al objeto content pane Añada los listeners de los componentes y defina código del método actionPerformed Añada un método main() que instancie el objeto creado y tome los recaudos para cerrar la ventana Pintado Cuando la GUI necesita cambiar su apariencia visual se pinta en la pantalla, comenzando siempre desde el contenedor de alto nivel (Ej.: JFrame o JApplet) y procediendo de esta forma hacia abajo en la jerarquía de contenedores El pintado es double-buffered por eficiencia Los componentes Swing normalmente se repintan ellos mismos en forma automática Paint se ejecuta en el event-dispatching-thread Pintado Los componentes se pintan automáticamente Todo lo demás:Programador JButton Cuándo se pinta? Pintado disparado por el sistema (se invoca paint()) La primera vez que el componente es visible Cuando un componente es cubierto y luego descubierto Cuando es necesario reflejar un cambio en el estado del programa Pintado disparado por la aplicación Cuando cambia texto, colores,etc. Cuando desea repintar (invoca a repaint(), no a paint() que pone en la cola este requerimiento) El thread de manejos de eventos llama a paint() del componente Pintado Pintado de un componente que extiende JComponent 1.fondo (si es opaco) 2. custom painting (si hay) 3. borde (si hay) 4. hijo (si tiene) Pintado custom Nunca llamar paint() directamente. Llamar repaint() JComponent paint paintComponent paintBorder paintChildren extends paint JPanel paintComponent paintBorder paintChildren extends PaintPanel paint paintComponent paintBorder paintChildren El método correcto a anular en pintado custom Pintado Qué ocurre cuando se invoca paint()? paint(Graphics g) paintComponent(Graphics g) paintBorder(Graphics g) paintChildren(Graphics g) Antes de hacer cualquier cosa en paintComponent(...): invoque super.paintComponent (pinta background) Pintado Cada componente tiene su propio sistema de coordenadas desde (0,0) hasta (ancho-1, alto-1) (0, 0) X Component (ancho -1, alto -1) Pintado Tener en cuenta el borde del componente (si lo tiene), reduce el área de pintado y desplaza coordenadas. Objeto Graphics El objeto Graphics provee un contexto para el pintado y métodos para la misma función. El contexto gráfico consiste en el estado actual:color de pintado, fuente, área de pintado Pintado de formas La clase Graphics define métodos para pintar formas: void drawLine(int x0, int y0, int x1, int y1) void drawArc(int x, int y, int width, int height, int startAngle,int arcAngle) void drawPolygon(Polygon p) void drawPolygon(int xPoints[ ], int yPoints[ ], int numPoints) void drawRect(int x, int y, int width, int height) void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) void draw3DRect(int x, int y, int width, int height, boolean raised) void drawOval(int x, int y, int width, int height) Pintado de formas Pintado de texto La clase Graphics define métodos para pintar texto: String (drawString) Pintado de texto La clase Graphics define métodos para pintar texto: String (drawString) Imágenes Cargar y mostrar imágenes es muy simple Class ImageIcon de javax.swing. Ej.:ImageIcon myIcon=new ImageIcon(“imagefile.gif”); Image image3 = getImage( new URL("http://java.sun.com/graphics/people.gif")); Imágenes • ImageIcon myImage = new ImageIcon("book.gif"); • JLabel myLabel = new JLabel(myImage); • getContentPane().add(myLabel); •JButton JButFeedback = new JButton(myImage); •JButton JButWrite = new JButton("Write"); •JButWrite.setIcon(myImage2); •JButton JButChange = new JButton(myImage3); •JButChange.setRolloverEnabled(true); •JButChange.setRolloverIcon(myImage4); Carga de imágenes myImage = Toolkit.getDefaultToolkit().getImage(filenameOrURL); retorna inmediatamente, no hay que esperar que la imagen se cargue antes de realizar otras operaciones. Algunos programas requieren más control o información acerca de la carga: clase MediaTracker método imageUpdate de la interface ImageObserver (útiles ambas también para no mostrar una imagen hasta que esté completamente cargada o informar a ProgressBar) Mostrar imágenes Métodos gráficos:(invocar en paintComponent) drawImage(image, x, y, observer) drawImage(image, x, y, w, h, observer) drawImage(image, x, y, bgcol, observer) drawImage(image, x, y, w, h, bgcol, ob.) La clase Component implementa la interface ImageObserver, casi siempre el último argumento es this Imágenes class MyPanel extends JPanel { private ImageIcon myImage; public MyPanel() { myImage = new ImageIcon("nasa.gif"); setPreferredSize(new Dimension(myImage.getIconWidth(), myImage.getIconHeight())); } public void paintComponent(Graphics g) { g.drawImage(myImage.getImage(), 10, 10, null); }} Imágenes Animación Se muestran sucesivos frames a una velocidad relativamente alta (usualmente 10-20 frames por segundo), se crea una sensación de movimiento Para actualizar periódicamente la pantalla se usa un “loop de animación”, normalmente se implementa con un objeto javax.swing.Timer (se necesita un thread separado, nunca poner en paintComponent ya que la aplicación queda congelada) Animación Timer Timer timer = new Timer(delay, this); …//this:action handler public synchronized void startAnimation() { if (!timer.isRunning()) {timer.start();} } … public synchronized void stopAnimation() { if (timer.isRunning()) { timer.stop();}}