Swing
Criação de interfaces gráficasCriação de interfaces gráficas
Modelos
Interacção por terminal de texto
Pergunta-resposta fácil de seguir
Alternativa: criação de uma interface complexa com objectos variados
Interacção pode ser com vários desses objectos Gera-se um evento, ao nível do sistema operativo (tecla, rato, ...), que é passado ao
Java e tratado pela aplicação Construir a interface, aguardar eventos e processá-los
Em vez de atitude activa de interrogar cada objecto para saber se tem algum pedido Os eventos podem ocorrer sem ordem nem momento pre-determinados
Mais próximo do paradigma de objectos
Cada objecto trata dos seus eventos Fluxo da computação passa mais para as mãos do utilizador
Swing
Criação de GUIs em JavaCriação de GUIs em Java Biblioteca de classes AWT (Abstract Window Toolkit)
Fornece todas as classes básicas para a construção de interfaces
Incluída em todos os sistemas Java no pacote java.awt
Portável entre plataformas
Modelo de eventos suportado pelo pacote java.awt.event
Com problemas de eficiência e aspecto
Biblioteca Swing
Trabalha sobre a AWT, mas mais eficiente
Incluída em javax.swing
Tem mais estruturas para a construção do GUI
Suporta look-and-feel (Windows, Unix, Macintosh, independente, adaptado)
Swing
Objectos em SwingObjectos em Swing
Apenas se mostram alguns objectos simples; a biblioteca Swing tem muitos mais
Janela (Jframe)
Campo de texto não editável
Caixa de escolha (JCheckBox)
Botão de rádio (JRadioButton)
Etiqueta (JLabel)Combo box (JComboBox)
Tela (Jpanel) Campo de texto (JTextField)Lista (Jlist)
Botão (JButton)
Grupo de botões (ButtonGroup)
desenho
Swing
Hierarquia de classesHierarquia de classes
Maior parte dos objectos descende de Component
Tem posição e tamanho, pode ser mostrado no ecrã e receber eventos
Classe abstracta
Alguns métodos
void setSize( int width, int height ); Usar antes setPreferredSize;
void setBackground ( Color c ); void setFont( Font f ); void show()
Torna o componente visível
As classes Font e Color estão definidas noutra hierarquia, em AWT (Só se mostra parte da hierarquia)
Swing
ContentoresContentores
Container
Um contentor é um componente que pode conter outros componentes
É necessário saber-se como dispor os componentes
Ajudante: posicionador (LayoutManager) associado com void setLayout( LayoutManager mgr );
Depois adicionam-se os componentes por ordem
void add( Component c ); ou void add( Component c, Object where ); Dois tipos de contentores
Janelas de topo, até Jframe
Componente pesado porque interage com o sistema de janelas nativo na máquinaJComponent e suas subclasses (muitos dos outros componentes)
Componente leve porque é completamente desenhado numa tela pelo Swing
Swing
JanelasJanelas
Tipos de janelas de topo
JWindow : janela sem caixilho
JFrame : janela com caixilho que pode ter também um menu (JMenuBar)
JDialog : janela para criar diálogos
Uma aplicação deve ter um JFrame ou uma sua subclasse
Não é possível adicionar componentes directamente à janela
Para deixar ao Swing controlo sobre o posicionamento
Obtém-se um contentor que representa o conteúdo da janela
Container getContentPane( );
Swing
PainelPainel
Um painel destina-se a organizar componentes numa unidade de apresentação
Podem existir contentores dentro de contentores e painéis dentro de painéis
É habitual usar uma subclasse de Jpanel para permitir acrescentar código específico (GUI é uma subclasse de Jpanel)
GUI implementa a interface ActionListener
É um atendedor para tratar o evento “carregar no botão” Tem que fornecer o método actionPerformed Tem que ligar o atendedor ao objecto que pode produzir o evento
theDrawButton.addActionListener( this )
JPanel herda de JComponent várias funcionalidades, incluindo palpites e dimensionamento
void setToolTipText( String txt ); void setPreferredSize( Dimension d );
Swing
Classe GUI principalClasse GUI principalimport java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class GUI extends JPanel implements ActionListener
{
public GUI( )
{
makeTheObjects( );
doTheLayout( );
theDrawButton.addActionListener( this );
}
// Make all the objects
private void makeTheObjects( )
{ /* ver a frente*/ }
// Layout all the objects
private void doTheLayout( )
{ /* ver a frente*/ }
public void actionPerformed( ActionEvent evt )
{ /* ver a frente*/ }
private GUICanvas theCanvas;
private JComboBox theShape;
private JList theColor;
private JTextField theXCoor;
private JTextField theYCoor;
private JRadioButton smallPic;
private JRadioButton mediumPic;
private JRadioButton largePic;
private JCheckBox theFillBox;
private JButton theDrawButton;
private JTextField theMessage;
}
Swing
Relacionamento entre classesRelacionamento entre classes
JComponent
JPanel
GUI
GUICanvasJComboBox
JList ...
ActionListener
ActionPerformed
implements
GUICanvasincludes
extends
extends
Swing
Etiquetas e botõesEtiquetas e botões
Componente destinado a etiquetas: JLabel
Normalmente associado a campos de texto, campos combo, listas e paineis, uma vez que os outros já têm etiqueta própria
Construção de um objecto etiqueta vazio: JLabel( );
Construção de um objecto com a etiqueta theLabel: JLabel( String theLabel );
Alteração da etiqueta no objecto: setText( String theLabel );
Pode ser usado para mensagens para o utilizador mas habitualmente usa-se campos de texto não editáveis para esse fim
Um botão (caso de Draw) pode ser visto como uma etiqueta activa: gera eventos para “click com o botão esquerdo”
Métodos: JLabel( ); JLabel( String theLabel ); setText( String theLabel );
Swing
Caixas de selecçãoCaixas de selecção
Nas caixas de selecção (“combo box”), é possível escolher um objecto de uma lista pop-up de alternativas, ficando apenas a escolha visível
No caso de a lista ser editável, pode escrever-se um valor não previsto
A lista de valores pode ser fornecida na criação do objecto ou ser manipulada posteriormente
Criação de caixa de selecção vazia: JComboBox( );
Idem, com as opções: JComboBox( Object[] choices );
Acrescentar opção no fim: void addItem( Object item );
Devolver o objecto correspondente ao item seleccionado: Object getSelectedItem( ); ou o respectivo número de ordem int getSelectedIndex( );
Permitir a especificação de um novo valor: void setEditable( boolean edit );
Indicar o valor seleccionado (ex. por omissão): void setSelectedIndex( int index );
Swing
ListasListas O componente JList permite fazer escolhas numa lista de valores
possivelmente com rolamento, se o número de valores exceder o espaço disponível
Principais diferenças relativamente à combo box:
A lista permite, por omissão, selecção múltipla A lista deixa ver vários valores simultaneamente A lista ocupa maior superfície do ecrã
Criação de lista vazia: JList( ); ou com os valores: JList( Object[] values );
Indicar os valores: void setListData( Object[] values );
Selecção simples, devolver o objecto correspondente: Object getSelectedValue( ); ou o respectivo número de ordem int getSelectedIndex( );
Selecção múltipla: Object [] getSelectedValues( ); int[] getSelectedIndices( );
Escolher modo de selecção simples: void setSelectionMode( ListSelectionMode.SINGLE_SELECTION);
Indicar o valor seleccionado: void setSelectedIndex( int index ); void setSelectedValue( Object value );
Swing
Caixas de marcação e botões de rádioCaixas de marcação e botões de rádio Estes componentes (JCheckBox e JRadioButton) só têm dois estados: on (true)
e off (false)
Por isso, têm etiqueta no próprio objecto e podem ser agrupados
JCheckBox para dizer sim ou não JRadioButton para escolher um entre alternativas
Criação de uma caixa sem etiqueta: JCheckBox( ); com etiqueta: JCheckBox( String theLabel); com etiqueta e estado inicial: JCheckBox( String theLabel, boolean state);
Idem para JRadioButtonAltera a etiqueta: void setLabel( String theLabel );
Indicar o estado: void setSelected( boolean state);
Consulta o estado: boolean isSelected ( );
Para criar um grupo de escolha mutuamente exclusiva: ButtonGroup( );
Não é um componente
Para adicionar os botões (ou caixas) em causa: void add( AbstractButton b );
Swing
TextoTexto
Um campo de texto JTextField permite escrever uma linha de texto
Para mais do que uma linha, usa-se a área de texto JTextArea
A tecla Enter funciona aqui como uma mudança de linha e não como um evento do teclado a significar “fim de entrada de dados”
Métodos
Campo de texto: JTextField( );
Idem com indicação do comprimento: JTextField( int cols);
Idem com valor inicial e comprimento: JTextField( String text, int cols);
Obter o texto escrito no campo: String getText( );
Indicar o texto escrito no campo: void setText( String text );
Indicar se é editável ou não (só para display de mensagens): void setEditable( boolean editable );
Swing
// Make all the objects// Make all the objectsprivate void makeTheObjects( )
{
theCanvas = new GUICanvas( );
theCanvas.setBackground( Color.green );
theCanvas.setPreferredSize(
new Dimension( 100, 100 ) );
theShape = new JComboBox(
new String [ ] { "Circle", "Square" } );
theColor = new JList(
new String [ ] { "red", "blue" } );
theColor.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION );
theColor.setSelectedIndex( 0 ); // make red default
theXCoor = new JTextField( 3 );
theYCoor = new JTextField( 3 );
ButtonGroup theSize = new ButtonGroup( );
smallPic = new JRadioButton( "Small", false );
mediumPic = new JRadioButton( "Medium", true );
largePic = new JRadioButton( "Large", false );
theSize.add( smallPic );
theSize.add( mediumPic );
theSize.add( largePic );
theFillBox = new JCheckBox( "Fill" );
theFillBox.setSelected( false );
theDrawButton = new JButton( "Draw" );
theMessage = new JTextField( 25 );
theMessage.setEditable( false );
}
Swing
// Layout all the objects// Layout all the objects
private void doTheLayout( )
{
JPanel topHalf = new JPanel( );
JPanel bottomHalf = new JPanel( );
// Layout the top half
topHalf.setLayout( new FlowLayout( ) );
topHalf.add( theCanvas );
topHalf.add( new JLabel( "Shape" ) );
topHalf.add( theShape );
topHalf.add( theColor );
topHalf.add( new JLabel( "X coor" ) );
topHalf.add( theXCoor );
topHalf.add( new JLabel( "Y coor" ) );
topHalf.add( theYCoor );
// Layout the bottom half
bottomHalf.setLayout( new FlowLayout( ) );
bottomHalf.add( smallPic );
bottomHalf.add( mediumPic );
bottomHalf.add( largePic );
bottomHalf.add( theFillBox );
bottomHalf.add( theDrawButton );
bottomHalf.add( theMessage );
// Now layout GUI
setLayout( new BorderLayout( ) );
add( topHalf, "North" );
add( bottomHalf, "South" );
}
Swing
TelasTelas
Uma tela é uma área rectangular onde se pode desenhar e que recebe eventos
Em AWT, usava-se a classe Canvas
Em Swing, cria-se uma subclasse de JPanel, que permite redefinir o método de desenhar a interface: void paintComponent( Graphics g );
g é uma instância da classe abstracta Graphics que o Swing associa ao dispositivo de visualização
Métodos para desenhar
void drawOval( int x, int y, int width, int heigth );
drawRect, fillOval, fillRect; indica canto superior esquerdo e dimensõesvoid drawLine( int x1, int y1, int x2 int y2 ); superior esquerdo e inferior direito
void DrawString( String str, int x, int y );
void setColor ( Color c );
Swing
Definição da telaDefinição da telaclass GUICanvas extends JPanel
{
public void setParams( String aShape,
String aColor, int x, int y, int size, boolean fill )
{
this.theShape = aShape;
this.theColor = aColor;
xcoor = x;
ycoor = y;
theSize = size;
fillOn = fill;
repaint( );
}
public void update( Graphics g )
{ System.out.println( "Update called" );
}
public void paintComponent( Graphics g )
{ super.paintComponent( g );
if( theColor.equals( "red" ) )
g.setColor( Color.red );
else if( theColor.equals( "blue" ) )
g.setColor( Color.blue );
theWidth = 25 * ( theSize + 1 );
if( theShape.equals( "Square" ) )
if( fillOn )
g.fillRect( xcoor, ycoor, theWidth, theWidth );
else
g.drawRect( xcoor, ycoor, theWidth, theWidth );
else if( theShape.equals( "Circle" ) )
if( fillOn )
g.fillOval( xcoor, ycoor, theWidth, theWidth );
else
g.drawOval( xcoor, ycoor, theWidth, theWidth );
}
Swing
Resto da telaResto da tela
private String theShape = "";
private String theColor = "";
private int xcoor;
private int ycoor;
private int theSize; // 0 = small, 1 = med, 2 = large
private boolean fillOn;
private int theWidth;
}
Swing
Responder ao eventoResponder ao evento public void actionPerformed( ActionEvent evt )
{
try
{
theCanvas.setParams(
(String) theShape.getSelectedItem( ),
(String) theColor.getSelectedValue( ),
Integer.parseInt( theXCoor.getText( ) ),
Integer.parseInt( theYCoor.getText( ) ),
smallPic.isSelected( ) ? 0 :
mediumPic.isSelected( ) ? 1 : 2,
theFillBox.isSelected( ) );
theMessage.setText( "" );
}
catch( NumberFormatException e )
{ theMessage.setText( "Incomplete input" ); }
}
Swing
Adaptadores e classes internasAdaptadores e classes internas
JFrame
ClosableFrame
BasicGUI
extends
extends
WindowListener
windowClosingwindowClosedwindowIconifiedwindowOpened
...
implements
• Jframe por si só não fecha
• Para ter uma janela que feche implementa-se o WindowListener
• Obriga a implementar muitos métodos vazios
JFrame
ClosableFrame
BasicGUI
(classe interior)
extends
extends
WindowListener
windowClosingwindowClosedwindowIconifiedwindowOpened
...
implements
• Adaptador implementa todos os métodos vazios e permite overriding
• Por não haver herança múltipla, cria-se uma classe interior (para ter acesso às variáveis de ClosableFrame) que trata dos eventos
• esta classe pode ser anónima
WindowAdapter
extends
Swing
Tratamento de eventosTratamento de eventos
// Class that implements a Window that closes on a window-close event
class CloseableFrame extends JFrame
{
public CloseableFrame( )
{
addWindowListener( new WindowAdapter( )
{
public void windowClosing( WindowEvent event )
{ System.exit( 0 ); }
}
);
}
}
Swing
Classe principalClasse principal
class BasicGUI extends CloseableFrame
{
public static void main( String [ ] args )
{
JFrame f = new BasicGUI( );
f.setTitle( "GUI Demo" );
Container contentPane = f.getContentPane( );
contentPane.add( new GUI( ) );
f.pack( );
f.show( );
}
}
Swing
Quadro completoQuadro completo
JComponent
JPanel
GUI
GUICanvasJComboBox
JList ...
ActionListener
ActionPerformed
implements
GUICanvasincludes
extends
extends
BasicGUI(contentPane)
GUI
extends
includes
JFrame
ClosableFrame
BasicGUI
(classe interior)
extends
extends
WindowListener
windowClosing
implements
WindowAdapter
extends
Swing
Arquitectura MVCArquitectura MVC
Arquitectura para construção de aplicações OO em que se separam três dimensões
Modelo: mantém dados usando os algoritmos apropriados e fornece métodos de acesso
Vista: constroi uma representação visual de parte ou todos os dados do modelo
Controlador: trata os eventos
Quando o modelo altera os seus dados, gera eventos que fazem com que a vista actualize a sua representação, segundo as ordens do controlador
Podem existir várias vistas e controladores para o mesmo modelo, o qual pode permancer inalterado quando este evolui
Swing
Comunicação MVCComunicação MVC
Uma alteração no modelo provoca um evento de alteração que é difundido para todos os objectos que estão à escuta desse evento e desencadeia as alterações
Facilita manter o sincronismo entre vistas diferentes de um mesmo modelo
Actuar numa vista pode provocar alterações no modelo que são reflectidas nas outras vistas
No exemplo anterior, o modelo não está claramente separado da vista (GUI)
as variáveis estão “misturadas” na tela GUICanvas
Modelo
Vista 2Vista 1
Controlador
Evento
altera
actualiza
vê dados
altera
altera
vê dados
actualiza
Swing
Arquitectura MVC em SwingArquitectura MVC em Swing
Um componente Swing leve inclui os seguintes objectos
Um modelo que mantém os dados ( modelo da MVC básica)
fornece métodos de acesso notifica os listeners quando é alterado
Um delegado da IU que é uma vista ( vista) com listeners ( controladores)
combina as duas funções colocando os listeners junto dos objectos controlados listeners são habitualmente implementados por classes internas
Um componente que estende JComponent
um componente fornece uma API para o programador transfere a construção de interfaces para os delegados; passa-lhes os eventos torna o modelo transparente para o programador; atravessado pelos métodos
Facilita acopular diferentes estilos de interfaces (look & feel)
Macintosh, Windows, Motif, Metal
Swing
Comunicação MVC em SwingComunicação MVC em Swing
Componente
Faz alterações ao modelo e faz seguir para o modelo alterações que venham da interface
Escutam o modelo para passarem os eventos para os seus listeners
Listeners do delegado IU
Tanto escutam o modelo como o componente
Pedem informação ao modelo
Alteram o próprio delegado
Modelo
Delegado IU
Listeners
Componente
Evento
actualiza
vê dados
altera
altera
actualiza
actualiza
altera
Swing
Perspectiva estática de um componentePerspectiva estática de um componente
JComponent
JSliderBounded
RangeModel
DefaultBoundedRangeModel
ComponentUI
SliderUI
BasicSliderUI
WindowsSliderUI
MotifSliderUI
MetalSliderUI
FocusHandler
ScrollListener
TrackListener
ChangeHandler
PropertyChangeHandler
ComponentHandler
Swing
Eventos de modeloEventos de modelo
Um modelo pode produzir muitos eventos
Eventos leves: ChangeEvent
só indicam o objecto fonte do evento Ex: posição de uma barra de deslocamento ChangeListener
Eventos com estado
Transportam os parâmetros tipicamente necessários para o processamento Ex: retirar um elemento de uma lista PropertyChangeListener