PDA

View Full Version : [Java - Swing] Centrare un'immagine in un JDialog


malocchio
08-11-2009, 16:13
Allora la situazione è questa:
ho progettato un JPanel tramite il designer grafico di NetBeans e questa è l'anteprima

http://img69.imageshack.us/img69/1664/shotdices.jpg

Ora io vorrei trasformare questo oggetto JPanel in un JDialog, in modo da poter essere istanziato e visualizzato direttamente senza fare un add().
Ho provato a modificare il codice generato da NetBeans da così a così

public class StartForm extends javax.swing.JPanel
public class StartForm extends javax.swing.JDialog
ma mi dà il seguente errore in compilazione (ho ovviamente modificato il codice che utilizza la classe in modo da essere corretto. Sembra che l'errore sia generato dal GroupLayout in fase di visualizzazione (setVisible(true))
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: GroupLayout can only be used with one Container at a time
at javax.swing.GroupLayout.checkParent(GroupLayout.java:1095) <<<<<<<<
at javax.swing.GroupLayout.invalidateLayout(GroupLayout.java:987)
at java.awt.Container.invalidate(Container.java:1455)
at java.awt.Component.addNotify(Component.java:6432)
at java.awt.Container.addNotify(Container.java:2585)
at javax.swing.JComponent.addNotify(JComponent.java:4683)
at java.awt.Container.addNotify(Container.java:2592)
at javax.swing.JComponent.addNotify(JComponent.java:4683)
at java.awt.Container.addNotify(Container.java:2592)
at javax.swing.JComponent.addNotify(JComponent.java:4683)
at javax.swing.JRootPane.addNotify(JRootPane.java:735)
at java.awt.Container.addNotify(Container.java:2592)
at java.awt.Window.addNotify(Window.java:638)
at java.awt.Dialog.addNotify(Dialog.java:747)
at java.awt.Dialog.conditionalShow(Dialog.java:891)
at java.awt.Dialog.show(Dialog.java:1034)
at java.awt.Component.show(Component.java:1422)
at java.awt.Component.setVisible(Component.java:1375)
at java.awt.Window.setVisible(Window.java:806)
at java.awt.Dialog.setVisible(Dialog.java:985) <<<<<<<
at backtris.StartForm.<init>(StartForm.java:22)
at backtris.TrisApplication.showStarterForm(TrisApplication.java:33)
at backtris.TrisApplication.<init>(TrisApplication.java:22)
at backtris.TrisWindow.<init>(TrisWindow.java:12)
at backtris.TrisWindow$1.run(TrisWindow.java:23)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

L'errore mi viene visualizzato in console 2 volte e non visualizza niente (la JVM però non termina).
Non ho voglia di scoprire cosa c'è che non funziona e mi piacerebbe scrivere a mano il codice del pannello.

Però non saprei come fare. Prenderò ovviamente spunto dal codice auto-generato, ma non userò il GroupLayout.
Quell'immagine dei dadi, nella mia idea, deve stare al centro della finestra o, meglio, al centro del riquadro ideale formato dai bordi della finestra e dal bordo inferiore della label "Click to...".
Come posso fare?
L'immagine è visualizzata, nel codice auto-generato, tramite un JButton avente un'icona coprente. Questo il codice:
jButton1 = new javax.swing.JButton();
...
jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/backtris/dice.jpg")));

banryu79
09-11-2009, 09:01
Imposti il LayoutManager della tua JDialog a BorderLayout (se non lo è già di default, ora non ricordo) e aggiungi il JButton (un add() da qualche parte dovrà pure farlo) in BorderLayout.CENTER.

Forse non ho capito la situazione?

malocchio
09-11-2009, 11:07
Imposti il LayoutManager della tua JDialog a BorderLayout (se non lo è già di default, ora non ricordo) e aggiungi il JButton (un add() da qualche parte dovrà pure farlo) in BorderLayout.CENTER.

Forse non ho capito la situazione?

Ho pensato anche io a questo, ma il JButton non si ridimensiona fino a toccare i bordi? Oppure specificando una dimensione mi viene corretto?

banryu79
09-11-2009, 12:02
Ho pensato anche io a questo, ma il JButton non si ridimensiona fino a toccare i bordi? Oppure specificando una dimensione mi viene corretto?
Sì, scusa, mi ero dimenticato del problemuccio dell'espansione :doh:

Infilando il button in un JPanel gestito da GridBagLayout e infilando quest'ultimo nella JDialog con posizione BorderLayout.CENTER il bottone resta sempre centrato:

import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.Window;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
*
* @author francesco
*/
public class ButtonCentered extends JDialog
{
public static void main(String... args) {
java.awt.Window nullOwner = null;
ButtonCentered bc = new ButtonCentered(nullOwner, "Button is Centered");
bc.showUp();
}

public ButtonCentered(Window owner, String title) {
super(owner, title);
initialize();
}

private void initialize() {
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setSize(500, 350);
this.setLayout(new BorderLayout());
JPanel container = new JPanel();
container.setLayout(new GridBagLayout());
JButton button = new JButton("CENTERED");
container.add(button);
this.add(container, BorderLayout.CENTER);
}

private void showUp() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ButtonCentered.this.setVisible(true);
}
});
}

}

malocchio
09-11-2009, 21:40
Sì, scusa, mi ero dimenticato del problemuccio dell'espansione :doh:

Infilando il button in un JPanel gestito da GridBagLayout e infilando quest'ultimo nella JDialog con posizione BorderLayout.CENTER il bottone resta sempre centrato:

import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.Window;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
*
* @author francesco
*/
public class ButtonCentered extends JDialog
{
public static void main(String... args) {
java.awt.Window nullOwner = null;
ButtonCentered bc = new ButtonCentered(nullOwner, "Button is Centered");
bc.showUp();
}

public ButtonCentered(Window owner, String title) {
super(owner, title);
initialize();
}

private void initialize() {
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setSize(500, 350);
this.setLayout(new BorderLayout());
JPanel container = new JPanel();
container.setLayout(new GridBagLayout());
JButton button = new JButton("CENTERED");
container.add(button);
this.add(container, BorderLayout.CENTER);
}

private void showUp() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ButtonCentered.this.setVisible(true);
}
});
}

}


Oh, grazie. 2/3 mesi fa ho letto per metà il tutorial di PGI sul GridBag e non mi ricordo niente, sarà ora di dare una rinfrescata! :p
Appena posso provo quel codice.

malocchio
12-11-2009, 00:42
GridBagLayout rinfrescato e risultato ottenuto senza particolari difficoltà! :D

Il codice
package backtris;

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class StartForm extends JDialog {

private Player starter;
private boolean clicked = false;

public StartForm(Window owner) {
super(owner, ModalityType.DOCUMENT_MODAL);
initComponents();
this.centerOnScreen(new Dimension(320, 260));
}

private JButton jButton1;
private JLabel jLabel1, jLabel2;
private ImageIcon dice;

private void initComponents() {
this.setLayout(new GridBagLayout());
GridBagConstraints lim = new GridBagConstraints();
lim.insets = new Insets(10, 10, 10, 10);
jLabel1 = new JLabel("Click the dices to see which player will start...");
lim.gridx = 0;
lim.gridy = 0;
this.add(jLabel1, lim);
dice = new ImageIcon(getClass().getResource("/backtris/dice.jpg"));
jButton1 = new JButton();
jButton1.setIcon(dice);
jButton1.setPreferredSize(new Dimension(dice.getIconWidth(), dice.getIconHeight()));
jButton1.setBorder(null);
jButton1.setBorderPainted(false);
jButton1.setFocusPainted(false);
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!clicked) {
clicked = true;
int r = new Random().nextInt();
if (r % 2 == 1) {
jLabel2.setText("Cpu player starts");
starter = Player.CPU;
} else {
jLabel2.setText("Human player starts");
starter = Player.HUMAN;
}
Timer t = new Timer(3000, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
dispose();
}
});
t.setRepeats(false); //occhio
t.start();
}
}
});
lim.gridx = 0;
lim.gridy = 1;
this.add(jButton1, lim);
jLabel2 = new JLabel(" ");
jLabel2.setFont( new Font("Tahoma", Font.BOLD, 11) );
lim.gridx = 0;
lim.gridy = 2;
this.add(jLabel2, lim);
}

private void centerOnScreen(Dimension window) {
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
this.setBounds(screen.width / 2 - window.width / 2, screen.height / 2 - window.height / 2, window.width, window.height);
}

public Player getStarter() {
return this.starter;
}
}
produce la seguente finestra

http://img5.imageshack.us/img5/7311/dicesshot.jpg

Grazie dell'aiuto!