|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Oct 2003
Città: Pisa/Cosenza
Messaggi: 1364
|
[Java e Grafica] Layout per Implementare l'interfaccia grafica desiderata
Ciao, sto progettando un giochino per l'università e ovviamente ho a che fare con interfaccia grafica.
So che a ogni pannello posso applicare un determinato Layout che si differenzia dagli altri per come posizione poi gli oggetti. Ho letto che per implementare un interfaccia un po' più complessa e gradevole è meglio dividere la propria idea in zone.. ed ad ogni zona associare un pannello con il layout più opportuno. Ora, una bozza della mia idea è questa: ![]() La mia idea era quella di dividere i pannelli in livelli.. cioè spiego meglio.. Un pannello di primo livello che conterrà i pannelli di secondo livello che a loro volta conterranno i pannelli di terzo livello. Avevo pensato di usare un Border Layout per il primo livello in modo da poter inserire due pannelli di secondo livello a OVEST e a EST.. ma ho dei problemi.. perchè questi si schiacciano ai lati del primo pannello e non si vede niente.. si vedono solo se li metto come CENTER.. Prima domanda: -C'è un modo per regolare (e quindi nel mio caso aumentare) lo spazio occupato da un pannello inserito per esempio a NORD di un pannello con Border Layout? Se il mio approccio è completamente sbagliato o quasi, mi suggerite voi come affrontare la cosa per avere l'interfaccia come nell'immagine che ho postato? Ho letto del Layout: GridBagLayout.. che divide la zona in righe e colonne di dimensioni variabili.. però so che è molto difficile da usare.. voi che mi dite? Aiutatemi Gentilmente ![]()
__________________
![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Secondo gli ingegneroni di Sun dovresti usare GridBagLayout o SpringLayout. Il primo è 'na specie di Sudoku. Il secondo è molto semplice se usi un solo componente. Con due componenti ti viene la sindrome del vaffanc##@.
Le alternative sono due. La prima è usare uno degli strumenti per la costruzione visuale di interfacce utente. Aggiungono quattro milioni di linee di codice per ogni etichetta inserita e poi lo blindano in modo tale che se cambi una virgola ti esplode il PC. La seconda è creare un tuo LayoutManager che è facilissmo. Nel tuo caso hai quattro aree rettangolari. Le due a destra sono alte ognuna il 50% dell'altezza del contenitore e larghe complessivamente il 67% della larghezza del contenitore. La cella in alto a sinistra è larga il 33% e alta il 25%. Il componente lungo è largo il 33% e alto il 75. Te la cavi con due conti e qualche linea. |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Oct 2003
Città: Pisa/Cosenza
Messaggi: 1364
|
Quote:
In ogni caso appena ho tempo mi spulcio un po' il codice delle classi layout di java..
__________________
![]() |
|
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
E' facilissimo. Hai un Container in cui infili i componenti. I componenti sono disegnati in regioni dello spazio assegnate al Container secondo quanto stabilito nel LayoutManager. E qui abbiam già detto tutto.
Supponiamo di voler disegnare un componente nell'angolo in alto a sinistra del suo contenitore. Non che sia proprio utilissimo ma si fa per dire. Codice:
import java.awt.*; public class Lollayout implements LayoutManager { /* questo metodo è invocato quando al contenitore bersaglio si richiesta un add(String, Component). Per questo layout non c'è effetto */ public void addLayoutComponent(String name, Component comp) { } /* Se alla rimozione di un componente del contenitore un qualche stato del layout deve mutare... si passa di qui */ public void removeLayoutComponent(Component comp) { } /* Qui si attribuiscono ai componenti del contenitore le regioni di spazio da occupare */ public void layoutContainer(Container parent) { //mo si conta synchronized(parent.getTreeLock()) { //Toro seduto tenere sempre conto del bordo Insets insets = parent.getInsets(); int x0 = insets.left; int y0 = insets.top; int width = parent.getWidth() - insets.right - insets.left; int height = parent.getHeight() - insets.top - insets.bottom; //(x0, y0, width, height) è l'area effettivamente disponibile //per la proiezione del contenuto. Inizia la spartizione. Component[] comps = parent.getComponents(); if(comps.length > 0) { Component theOne = comps[0]; /* dove ti metto, dove ti metto... lo spariamo nel quadrante in alto a sinistra */ Rectangle rect = new Rectangle(x0, y0, width / 2, height / 2); theOne.setBounds(rect); } } } /** Questo calcola la dimensione preferita del contenitore */ public Dimension preferredLayoutSize(Container parent) { return minimumLayoutSize(parent); //un bel rinvio di comodo } /** Questo calcola la dimensione minima del contenitore */ public Dimension minimumLayoutSize(Container parent) { synchronized(parent.getTreeLock()) { Dimension size = new Dimension(); Component[] comps = parent.getComponents(); if(comps.length > 0) { Dimension compSize = comps[0].getPreferredSize(); //grande il doppio del primo componente... size.width = compSize.width * 2; size.height = compSize.height * 2; } //Tieni conto del bordo Insets margini = parent.getInsets(); size.width += margini.left + margini.right; size.height += margini.top + margini.bottom; return size; } } } ![]() Per controllare: Codice:
import java.beans.*; public class RefRunner implements Runnable { private Statement stat; public RefRunner(Object ref, String method) { stat = new Statement(ref, method, null); } public void run() { try { stat.execute(); } catch(Exception ex) { throw new RuntimeException(ex); } } } import java.awt.*; import javax.swing.*; public class Main { public static void main(String[] args) { RefRunner runner = new RefRunner(new Main(), "start"); SwingUtilities.invokeLater(runner); } public void start() { JPanel panel = new JPanel(new Lollayout()); JButton button = new JButton("Ciao!"); panel.add(button); JFrame window = new JFrame("Lol"); window.setContentPane(panel); window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); window.pack(); window.setVisible(true); } } Codice:
import java.awt.*; import java.util.*; public class CustomGridLayout implements LayoutManager { private int rowCount, columnCount, lineWidth; private Map<Component, GridData> componentData = new HashMap<Component, GridData>(); private ComponentList[] rows, columns; public void addLayoutComponent(String name, Component comp) {} public void removeLayoutComponent(Component comp) {} public CustomGridLayout(int rowCount, int columnCount) { this.lineWidth = lineWidth; this.rowCount = rowCount; this.columnCount = columnCount; initStructures(); } private void initStructures() { rows = new ComponentList[rowCount]; columns = new ComponentList[columnCount]; for(int i = 0; i < rows.length; i++) { rows[i] = new ComponentList(); } for(int i = 0; i < columns.length; i++) { columns[i] = new ComponentList(); } } public void setComponentData(Component c, GridData d) { componentData.put(c, d); for(int i = d.row(); i < d.rows(); i++) { rows[i].add(c); } for(int i = d.column(); i < d.columns(); i++) { columns[i].add(c); } } public void layoutContainer(Container parent) { synchronized(parent.getTreeLock()) { Insets margin = parent.getInsets(); Component[] components = parent.getComponents(); int cellWidth = (parent.getWidth() - margin.left - margin.right) / columnCount; int cellHeight = (parent.getHeight() - margin.top - margin.bottom) / rowCount; for(Component c : components) { GridData data = componentData.get(c); if(data != null) { //calcola le dimensioni della regione occupata dal componente int rx = data.column() * cellWidth + margin.left; int ry = data.row() * cellHeight + margin.top; int rw = data.columns() * cellWidth; int rh = data.rows() * cellHeight; Rectangle bounds = new Rectangle(rx, ry, rw, rh); setComponentBounds(c, data, bounds); } } } } private void setComponentBounds(Component c, GridData d, Rectangle area) { Dimension dim = c.getPreferredSize(); if(d.fill() == GridData.NONE) { int x, y, w, h; if(dim.width < area.width) { x = area.x + area.width / 2 - dim.width / 2; w = dim.width; } else { x = area.x; w = area.width; } if(dim.height < area.height) { y = area.y + area.height / 2 - dim.height / 2; h = dim.height; } else { y = area.y; h = area.height; } Rectangle r = new Rectangle(x, y, w, h); c.setBounds(r); } else if(d.fill() == GridData.BOTH) { c.setBounds(area); } else if(d.fill() == GridData.VERTICAL) { int y = area.y; int h = area.height; int x, w; if(dim.width < area.width) { x = area.x + area.width / 2 - dim.width / 2; w = dim.width; } else { x = area.x; w = area.width; } Rectangle r = new Rectangle(x, y, w, h); c.setBounds(r); } else if(d.fill() == GridData.HORIZONTAL) { int x = area.x; int w = area.width; int y, h; if(dim.height < area.height) { y = area.y + area.height / 2 - dim.height / 2; h = dim.height; } else { y = area.y; h = area.height; } Rectangle r = new Rectangle(x, y, w, h); c.setBounds(r); } } public Dimension minimumLayoutSize(Container parent) { synchronized(parent.getTreeLock()) { int totalWidth = 0; //per ogni colonna for(int i = 0; i < columnCount; i++) { int maxWidth = 0; //per ogni componente nella colonna for(Component c : columns[i]) { //calcola la larghezza del più largo dei componenti Dimension dim = c.getPreferredSize(); if(dim.width > maxWidth) maxWidth = dim.width; } //somma quella larghezza alla larghezza totale totalWidth += maxWidth; } int totalHeight = 0; for(int i = 0; i < rowCount; i++) { int maxHeight = 0; for(Component c : rows[i]) { Dimension dim = c.getPreferredSize(); if(dim.height > maxHeight) maxHeight = dim.height; } totalHeight += maxHeight; } //calcola il lato della cella int cellWidth = totalWidth / columnCount; int cellHeight = totalHeight / rowCount; //usa la dimensione maggiore per determinare le dimensioni del //componente int edge = cellWidth > cellHeight ? cellWidth : cellHeight; int containerWidth = edge * columnCount; int containerHeight = edge * rowCount; Insets margin = parent.getInsets(); containerWidth += margin.left + margin.right; containerHeight += margin.top + margin.bottom; return new Dimension(containerWidth, containerHeight); } } public Dimension preferredLayoutSize(Container parent) { return minimumLayoutSize(parent); } } Codice:
import java.awt.*; public class GridData { public static final int HORIZONTAL = 0; public static final int VERTICAL = 1; public static final int BOTH = 2; public static final int NONE = 3; private int row, column, rows, columns; private int fill = NONE; public GridData(int row, int column, int rows, int columns, int fill) { this.row = row; this.column = column; this.rows = rows; this.columns = columns; this.fill = fill; } public int fill() { return fill; } public int row() { return row; } public int column() { return column; } public int rows() { return rows; } public int columns() { return columns; } } Codice:
import java.awt.*; import javax.swing.*; public class Grid { private CustomGridLayout layout; private JPanel panel; public Grid(int rowCount, int columnCount) { layout = new CustomGridLayout(rowCount, columnCount); panel = new JPanel(layout); } public void add(Component c, int row, int column, int rows, int columns, int fill) { GridData data = new GridData(row, column, rows, columns, fill); layout.setComponentData(c, data); panel.add(c); } public JComponent panel() { return panel; } } Codice:
import java.awt.*; import javax.swing.*; public class Main { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { startUI(); } }); } private static void startUI() { Grid grid = new Grid(4, 3); grid.add(new JButton("a"), 0, 0, 1, 1, GridData.BOTH); grid.add(new JButton("b"), 0, 1, 2, 2, GridData.BOTH); grid.add(new JButton("c"), 1, 0, 3, 1, GridData.BOTH); grid.add(new JButton("d"), 2, 1, 2, 2, GridData.BOTH); JFrame f = new JFrame("..."); f.setContentPane(grid.panel()); f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); f.pack(); f.setVisible(true); } } |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Oct 2003
Città: Pisa/Cosenza
Messaggi: 1364
|
Sei stato gentilissimo! Grazie davvero.
Ho un'altra domandina... C'è un modo per far si che un immagine possa essere vista come un Component e quindi aggiunta tranquillamente ad un pannello come per esempio un bottone un JLabel? ..so che piccole immagini possono essere usate come icone sopra i label..ma se l'immagine è un po' grande non funziona! Lo chiedo perchè ho dei problemi a procedere diversamente... ecco cosa faccio io: -mi creo un mio pannello personale dove disegno l'immagine. Codice:
import java.awt.*; import javax.swing.*; import java.io.*; import javax.imageio.*; public class PannelloImmagineGiocatore extends JPanel { Image image; public static int sizex; public static int sizey; public PannelloImmagineGiocatore(){ try{ image = ImageIO.read(new File("immagini/test.GIF")); }catch (IOException e){ e.printStackTrace(); } sizex=image.getHeight(this); sizey=image.getWidth(this); this.setSize(sizex,sizey); } public void paintComponent(Graphics g){ super.paintComponent(g); if (image == null) return; Graphics2D g2 = (Graphics2D) g; g2.drawImage(image, 0, 0, null); } } Però se poi da un'altra classe mi creo l'oggetto PannelloImmagineGiocatore e lo aggiungo ad un frame.. l'immagine non si vede.. dove sbaglio?
__________________
![]() |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Il pannello che hai creato ha una dimensione preferita di 0x0. Alcuni LayoutManager "se ne fregano" e attribuiscono al pannello una certa regione di spazio, altri la tengono la in considerazione e, in quest'ultimo caso, il tuo pannello non si vedrà.
Quello che puoi fare è stabilire che la dimensione preferita del tuo pannello sia pari alla dimensione del suo bordo più la dimensione dell'immagine e usare un LayoutManager che ne tenga conto nel contenitore in cui quel pannello sarà inserito. Per la questione della dimensione preferita è sufficiente che tu sovrascriva il metodo getPreferredSize che PannelloImmagineGiocatore riceve da JPanel: Codice:
//in PannelloImmagineGiocatore public Dimension getPreferredSize() { Insets bordo = getInsets(); int width = image.getWidth(null) + bordo.left + bordo.right; int height = image.getHeight(null) + bordo.top + bordo.bottom; return new Dimension(width, height); } |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Oct 2003
Città: Pisa/Cosenza
Messaggi: 1364
|
Ok! Capito! ...Grazie
![]()
__________________
![]() |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Oct 2003
Città: Pisa/Cosenza
Messaggi: 1364
|
So che questa non è la sezione giusta per porre questa domanda, ma non so dove chiedere se no.. vorrei aggiungere al mio progetto un bel video poker.. però non so proprio dove reperire le immagini (ad una buona risoluzione) delle carte.. ho provato con google ma invano.. voi sapete indicarmi qualche risorsa? E poi più in generale, quando un programmatore vuole inserire nel suo progetto una determinata grafica che richiede come nel mio caso di immagini specifiche di oggetti... come procede di solito? a colpi di scanner?
__________________
![]() |
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Si rivolge a un grafico: un amico grafico, un parente grafico o un professionista grafico, dipende da quello che hai sottomano e dalla natura del progetto.
Come programmatore potresti anche usare quattro scarabocchi autoprodotti. Non è detto che siccome programmi non hai senso artistico: magari hai una dote nascosta e saltano fuori delle carte bellissime. Personalmente non sarei in grado di disegnare neanche il due di picche ![]() |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:53.